Testnet

為什麼我無法在同一個區塊中發布兩個交易(第二個來自第一個的更改地址)?

  • March 27, 2015

我正在嘗試在測試網上進行交易,其中包含 OP_RETURN 和更改地址,然後在同一塊中從第一個交易的更改地址進行第二個 OP_RETURN 交易。我的程式碼目前編寫第二筆交易的方式不應依賴於正在處理的第一筆交易(它從水龍頭獲取硬幣)。

這是維護問題的程式碼的簡化版本(我的“寫入”函式是此 bitcoinjs-lib 範例的修改版本):

var assert = require('assert'),
   bitcoin = require('bitcoinjs-lib'),
   blockchain = new (require('cb-helloblock'))('testnet'),
   dynamicKey,
   dynamicChangeKey;

connect = function (callback) {
   dynamicKey = bitcoin.ECKey.makeRandom();
   dynamicChangeKey = bitcoin.ECKey.makeRandom();

   write("Connecting to blockchain!", callback);
};

message = function (callback) {
   dynamicKey = dynamicChangeKey;
   dynamicChangeKey = bitcoin.ECKey.makeRandom();

   write("Posting to blockchain!", callback);
};

write = function (arbitraryData, callback) {
   var address = dynamicKey.pub.getAddress(bitcoin.networks.testnet).
           toString();

   blockchain.addresses.__faucetWithdraw(address, 2e4, function (err) {

       if (err) return callback(err);

       blockchain.addresses.unspents(address, function (err, unspents) {
           var tx,
               data,
               dataScript,
               unspent,
               txBuilt;

           if (err) return callback(err);

           tx = new bitcoin.TransactionBuilder();
           data = new Buffer(arbitraryData.toString());
           dataScript = bitcoin.scripts.nullDataOutput(data);
           unspent = unspents.pop();

           tx.addInput(unspent.txId, unspent.vout);
           tx.addOutput(dataScript, 1000);
           tx.addOutput(dynamicChangeKey.pub.getAddress(bitcoin.networks.
                   testnet).toString(), 1000);
           tx.sign(0, dynamicKey);
           txBuilt = tx.build();

           blockchain.transactions.propagate(txBuilt.toHex(), function (err) {

               if (err) return callback(err);

               // check that the message was propagated
               blockchain.transactions.get(txBuilt.getId(), function (err, 
                       transaction) {
                   var actual,
                       dataScript2,
                       data2;

                   if (err) return callback(err);

                   actual = bitcoin.Transaction.fromHex(transaction.txHex);
                   dataScript2 = actual.outs[0].script;
                   data2 = dataScript2.chunks[1];

                   assert.deepEqual(dataScript, dataScript2);
                   assert.deepEqual(data, data2);

                   callback();
               });
           });
       });
   });
};

log = function (value) {
   console.log(value);
};

connect(message.bind(undefined, log));

執行此程式碼時,第一個事務處理正確,但第二個事務返回此錯誤:

{ [AssertionError: Invalid JSend Response {"status":"fail","message":"Propagation unsuccessful","details":"TX rejected"}]
 name: 'AssertionError',
 actual: false,
 expected: true,
 operator: '==',
 message: 'Invalid JSend Response {"status":"fail","message":"Propagation unsuccessful","details":"TX rejected"}' }

如果我將第 15 行改為閱讀

   dynamicKey = bitcoin.ECKey.makeRandom();

代替

   dynamicKey = dynamicChangeKey;

兩個交易都正確處理,所以問題肯定在於我使用更改密鑰作為下一個交易密鑰。

有人知道我在哪裡搞砸了嗎?

我認為我的問題是我不小心試圖花費我的第一筆交易的輸出(對於給定的費用和給定的零錢都沒有足夠的資金)而不是我從水龍頭得到的輸出,我的意思是花費。我還沒有為這個問題寫一個好的解決方案,但是我在這個簡化的例子中通過在傳播之前建構兩個事務來解決它。

是其中一筆交易,是另一筆交易。

這是製造它們的可怕程式碼:

var assert = require('assert'),
   bitcoin = require('bitcoinjs-lib'),
   blockchain = new (require('cb-helloblock'))('testnet'),
   dynamicKey,
   dynamicChangeKey,
   transactions = [],
   dataPoints = [],
   dataScripts = [];

connect = function (callback) {
   dynamicKey = bitcoin.ECKey.makeRandom();
   dynamicChangeKey = bitcoin.ECKey.makeRandom();

   buildTransaction(dynamicKey, dynamicChangeKey, 
           "Connecting to blockchain...", callback);
};

message = function (callback) {
   dynamicKey = dynamicChangeKey; //bitcoin.ECKey.makeRandom();
   dynamicChangeKey = bitcoin.ECKey.makeRandom();

   buildTransaction(dynamicKey, dynamicChangeKey, "Posted to blockchain.", 
           callback);
};

buildTransaction = function (key, changeKey, arbitraryData, callback) {
   var address = key.pub.getAddress(bitcoin.networks.testnet).
           toString();

   blockchain.addresses.__faucetWithdraw(address, 2e4, function (err) {

       if (err) return callback(err);

       blockchain.addresses.unspents(address, function (err, unspents) {
           var tx,
               data,
               dataScript,
               unspent,
               txBuilt;

           if (err) return callback(err);

           tx = new bitcoin.TransactionBuilder();
           data = new Buffer(arbitraryData.toString());
           dataScript = bitcoin.scripts.nullDataOutput(data);
           unspent = unspents.pop();

           tx.addInput(unspent.txId, unspent.vout);
           tx.addOutput(dataScript, 1000);
           tx.addOutput(changeKey.pub.getAddress(bitcoin.networks.
                   testnet).toString(), 1000);
           tx.sign(0, key);
           txBuilt = tx.build();

           dataPoints.push(data);
           dataScripts.push(dataScript);
           transactions.push(txBuilt);

           callback();
       });
   });
};

propogateTransaction = function (data, dataScript, txBuilt, callback) {

   blockchain.transactions.propagate(txBuilt.toHex(), function (err) {

       if (err) return callback(err);

       // check that the message was propagated
       blockchain.transactions.get(txBuilt.getId(), function (err, 
              transaction) {
           var actual,
               dataScript2,
               data2;

           if (err) return callback(err);

           actual = bitcoin.Transaction.fromHex(transaction.txHex);
           dataScript2 = actual.outs[0].script;
           data2 = dataScript2.chunks[1];

           assert.deepEqual(dataScript, dataScript2);
           assert.deepEqual(data, data2);

           callback();
       });
   });
};

propogateBothTransactions = function () {
   propogateTransaction(dataPoints[0], dataScripts[0], transactions[0], 
           propogateTransaction.bind(undefined, dataPoints[1], dataScripts[1], 
           transactions[1], log));
};


log = function (value) {
   console.log(value);
};

connect(message.bind(undefined, propogateBothTransactions));

引用自:https://bitcoin.stackexchange.com/questions/36618