'The node is not in a connected state' error when trying to execute OP_RETURN transaction with NBitcoin

3

This is my first time trying out the NBitcoin library to create a transaction. I am trying to create an OP_RETURN transaction, but every time I try to execute the Version Handshake with the node I get the error: The node is not in a connected state.

This is self explanatory, but I've tried a number of what are considered reliable nodes.

I guess this is a four part question:

  1. When attempting an OP_RETURN transaction in NBitcoin, is it necessary to add the miner fees into the TransactionBuilder manually?

  2. Is there a way to use Node.Connect so it will just search for available nodes, rather than specifying a specific node?

  3. Is it an issue that I have the OP_RETURN and not anything else? Do I need to create another output with no value and add the miner fees in order to send it? There are libraries in PHP, Python, and Javascript to do this, but I am trying to figure out how to do this with NBitcoin.

  4. If I wanted to store the incoming hash in the OP_RETURN script, am I doing it correctly? The byte stream seems to be too long.

Heres my code, which is in a .NET MVC4 Controller Action:

[HttpPost]
public ActionResult NewTransaction(string hash)
{
        var paymentSecret = new BitcoinSecret("//Private Key");
        // Example hash is "45e114a7f2c6122c9c1dabbd4df187e66545c17ca0bd28de732499dbee476811"
        var message = hash;
        var bytes = Encoding.UTF8.GetBytes(message);
        var blockr = new BlockrTransactionRepository();
        var fundingTransaction = blockr.Get("60db94bfb43dd0d98ba7fdfbbg4f29a850f7s5ea7d79a32c4r954096f2945b04");
        var payment = new Transaction();

        payment.Inputs.Add(new TxIn()
        {
            PrevOut = new OutPoint(fundingTransaction.GetHash(), 1)
        });

        payment.Outputs.Add(new TxOut()
        {
            Value = Money.Zero,
            ScriptPubKey = TxNullDataTemplate.Instance.GenerateScriptPubKey(bytes)
        });

        payment.Inputs[0].ScriptSig = paymentSecret.ScriptPubKey;
        payment.Sign(paymentSecret, false);

        using (var node = Node.Connect(Network.Main, "67.221.193.55", new NodeConnectionParameters()
        {
            IsTrusted = true,
            IsRelay = false
        }))
        {
            // Always fails on the handshake
            node.VersionHandshake();
            node.SendMessage(new InvPayload(InventoryType.MSG_TX, payment.GetHash()));
            node.SendMessage(new TxPayload(payment));
            Thread.Sleep(500);
        }
        return View("Index");
}

EDIT

I tried to actually use the TransactionBuilder, but still came up with the same error. This time I am actually setting the fee amount. I am also using a different node and specifying the port. Here is the attempt:

var paymentSecret = new BitcoinSecret("//Private Key");
// Example hash is "45e114a7f2c6122c9c1dabbd4df187e66545c17ca0bd28de732499dbee476811"
var message = hash;
var bytes = Encoding.UTF8.GetBytes(message);

var funding = new Transaction()
{
    Outputs =
    {
        new TxOut("0.01", paymentSecret.GetAddress())
    }
};

var coins = funding
                .Outputs
                .Select((o, i) => new Coin(new OutPoint(funding.GetHash(), i), o))
                .ToArray();

var txBuilder = new TransactionBuilder();
var tx = txBuilder
            .AddCoins(coins)
            .AddKeys(paymentSecret.PrivateKey)
            .Send(TxNullDataTemplate.Instance.GenerateScriptPubKey(bytes), Money.Zero)
            .SendFees("0.00001")
            .SetChange(paymentSecret.PubKey)
            .BuildTransaction(true);

txBuilder.Verify(tx);

using (var node = Node.Connect(Network.Main, "67.221.193.55:8333", new NodeConnectionParameters()
{
    IsTrusted = true,
    IsRelay = false
}))
{
    node.VersionHandshake();
    node.SendMessage(new InvPayload(InventoryType.MSG_TX, tx.GetHash()));
    node.SendMessage(new TxPayload(tx));
    Thread.Sleep(500);
 }

Could anyone help out. There is a lack of documentation specifying how to conduct an OP_RETURN transaction. Thanks.

cfly24

Posted 2015-11-17T18:22:54.127

Reputation: 91

Based on the reason you posted, it looks like the remote node is timing out. Is this connected to a bitcoin node on your local network, or one over the internet? – Nick ODell – 2015-11-20T00:33:18.437

One on the Internet. It is timing out...but I've tried a number of reliable nodes with open ports with the same result. That leads me to believe I am not creating the transaction correctly. – cfly24 – 2015-11-20T00:55:18.770

Answers

1

I think the problem is that there is only OP_RETURN, I remember seeing in the Bitcoin code that only OP_RETURN without anything else is forbidden.

Except that, your code looks like what is in my book https://blockchainprogramming.azurewebsites.net/ so I'm almost sure it is the problem.

EDIT : You are crashing during Handshake, can you check Node.DisconnectReason ?

Nicolas Dorier

Posted 2015-11-17T18:22:54.127

Reputation: 729

OP_RETURN without a push is okay. See the tests: https://github.com/bitcoin/bitcoin/blob/9fa54a1b0c1ae1b12c292d5cb3158c58c975eb24/src/test/transaction_tests.cpp#L394 Of course, you can disable OP_RETURN standardness entirely by passing datacarrier=0 in bitcoin's config file.

– Nick ODell – 2015-11-19T04:47:47.150

I just checked Node.DisconnectReason. The Reason is Unexpected exception while connecting to socket and the exception is Unable to read data from the transport connection: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. – cfly24 – 2015-11-19T16:25:21.063

I think your problem is more simpler : your node does not accept new connection. It can happen if there is already too much for it and you are not whitelisted. – Nicolas Dorier – 2015-11-20T05:43:23.103

@NickODell, yes but a OP_RETURN without any other TxOut is not ok. But he crashes before sending the transaction, so it should not be the problem. – Nicolas Dorier – 2015-11-20T05:44:02.577

@NicolasDorier I think that's okay too. See how the test has only one item in vout? – Nick ODell – 2015-11-20T06:00:03.680

@NicolasDorier I've been using bitnodes.21.co to ensure that the node is accepting connections. They have a feature that allows you to type in an IP and test.

– cfly24 – 2015-11-20T17:50:04.160

@cfly24 if you can't handshake with the node, then it means the node has a problem, try another one.

I tried to find back in bitcoin code where having only op_return txout made the transaction rejected, but I don't find it anymore. I may have dreamed it. However this is not your problem since you crash at the handshake. – Nicolas Dorier – 2015-11-21T07:27:56.777

The tool on bitnodes tells me that the nodes I am using are accepting incoming connections. I may just switch over to node.js and use the chain api – cfly24 – 2015-11-25T16:34:24.433

Node accepting connections is different from node accepting handshake.

So either use Node.Connect(Network) so NBitcoin try to discover a node for you (can take time), or host your own node. If both are out of question, then third party api is fine. – Nicolas Dorier – 2015-11-26T17:39:55.843