successful tx broadcast.
This commit is contained in:
parent
547bd02ba3
commit
b05ee032c5
|
@ -23,6 +23,13 @@ bitcoind.start(function(err) {
|
|||
// print('Found tx:');
|
||||
// print(tx);
|
||||
// });
|
||||
bitcoind.once('tx', function(tx) {
|
||||
console.log('Broadcasting tx...');
|
||||
bitcoind._broadcastTx(tx, function(err, hash) {
|
||||
if (err) throw err;
|
||||
console.log('tx hash: %s', hash);
|
||||
});
|
||||
});
|
||||
bitcoind.on('mptx', function(mptx) {
|
||||
print('Found mempool tx:');
|
||||
print(mptx);
|
||||
|
|
149
lib/bitcoind.js
149
lib/bitcoind.js
|
@ -365,13 +365,19 @@ Transaction.prototype.toHex = function() {
|
|||
};
|
||||
|
||||
Transaction.toHex = function(tx) {
|
||||
return new bn(Transaction.binary(tx)).toString('hex');
|
||||
};
|
||||
|
||||
/**
|
||||
* Broadcast TX
|
||||
*/
|
||||
|
||||
Bitcoin._broadcastTx = function(tx, options, callback) {
|
||||
Bitcoin._broadcastTx =
|
||||
Bitcoin.prototype._broadcastTx = function(tx, options, callback) {
|
||||
if (typeof tx === 'string') {
|
||||
tx = { hex: tx };
|
||||
}
|
||||
|
||||
if (!callback) {
|
||||
callback = options;
|
||||
options = null;
|
||||
|
@ -382,26 +388,36 @@ Bitcoin._broadcastTx = function(tx, options, callback) {
|
|||
}
|
||||
|
||||
options.overrideFees = options.overrideFees || false;
|
||||
options.ownOnly = options.ownOnly || false;
|
||||
|
||||
return bitcoindjs.broadcastTx(tx, options.overrideFees, callback);
|
||||
return bitcoindjs.broadcastTx(tx,
|
||||
options.overrideFees,
|
||||
options.ownOnly,
|
||||
callback);
|
||||
};
|
||||
|
||||
Transaction.binary = function(tx) {
|
||||
var p = [];
|
||||
var off = utils.writeU32(p, tx.nVersion, 0);
|
||||
var off = utils.writeU32(p, tx.nVersion || tx.version, 0);
|
||||
off += utils.varint(p, tx.vin.length, off);
|
||||
|
||||
for (var i = 0; i < tx.vin.length; i++) {
|
||||
var input = tx.vin[i];
|
||||
|
||||
off += utils.copy(utils.toArray(input.out.hash, 'hex'), p, off, true);
|
||||
off += utils.writeU32(p, input.out.index, off);
|
||||
if (input.coinbase) {
|
||||
off += utils.copy(new bn(input.coinbase, 'hex').toArray(), p, off, true);
|
||||
off += utils.writeU32(p, input.sequence, off);
|
||||
} else {
|
||||
off += utils.copy(new bn(input.txid, 'hex').toArray(), p, off, true);
|
||||
off += utils.writeU32(p, input.vout, off);
|
||||
|
||||
var s = script.encode(input.script);
|
||||
off += utils.varint(p, s.length, off);
|
||||
off += utils.copy(s, p, off, true);
|
||||
// var s = script.encode(input.scriptSig.asm.split(' '));
|
||||
var s = script.encode(new bn(input.scriptSig.hex, 'hex').toArray());
|
||||
off += utils.varint(p, s.length, off);
|
||||
off += utils.copy(s, p, off, true);
|
||||
|
||||
off += utils.writeU32(p, input.seq, off);
|
||||
off += utils.writeU32(p, input.sequence, off);
|
||||
}
|
||||
}
|
||||
|
||||
off += utils.varint(p, tx.vout.length, off);
|
||||
|
@ -409,17 +425,19 @@ Transaction.binary = function(tx) {
|
|||
var output = tx.vout[i];
|
||||
|
||||
// Put LE value
|
||||
var value = output.value.toArray().slice().reverse();
|
||||
var value = new bn(output.value).toArray().slice().reverse();
|
||||
assert(value.length <= 8);
|
||||
off += utils.copy(value, p, off, true);
|
||||
for (var j = value.length; j < 8; j++, off++)
|
||||
for (var j = value.length; j < 8; j++, off++) {
|
||||
p[off] = 0;
|
||||
}
|
||||
|
||||
var s = script.encode(output.script);
|
||||
//var s = script.encode(output.scriptPubKey.asm.split(' '));
|
||||
var s = script.encode(new bn(output.scriptPubKey.hex, 'hex').toArray());
|
||||
off += utils.varint(p, s.length, off);
|
||||
off += utils.copy(s, p, off, true);
|
||||
}
|
||||
off += utils.writeU32(p, tx.nLockTime, off);
|
||||
off += utils.writeU32(p, tx.nLockTime || tx.locktime, off);
|
||||
|
||||
return p;
|
||||
};
|
||||
|
@ -427,9 +445,10 @@ Transaction.binary = function(tx) {
|
|||
var script = {};
|
||||
|
||||
script.encode = function encode(s) {
|
||||
if (!s)
|
||||
if (!s) {
|
||||
return [];
|
||||
var opcodes = constants.opcodes;
|
||||
}
|
||||
|
||||
var res = [];
|
||||
for (var i = 0; i < s.length; i++) {
|
||||
var instr = s[i];
|
||||
|
@ -443,25 +462,117 @@ script.encode = function encode(s) {
|
|||
} else if (1 <= instr.length && instr.length <= 0x4b) {
|
||||
res = res.concat(instr.length, instr);
|
||||
} else if (instr.length <= 0xff) {
|
||||
res = res.concat(opcodes.pushdata1, instr.length, instr);
|
||||
// res = res.concat(script.opcodes.pushdata1, instr.length, instr);
|
||||
res = res.concat(0x4c, instr.length, instr);
|
||||
} else if (instr.length <= 0xffff) {
|
||||
res.push(opcodes.pushdata2);
|
||||
// res.push(script.opcodes.pushdata2);
|
||||
res.push(0x4d);
|
||||
utils.writeU16(res, instr.length, res.length);
|
||||
res = res.concat(instr);
|
||||
} else {
|
||||
res.push(opcodes.pushdata4);
|
||||
// res.push(script.opcodes.pushdata4);
|
||||
res.push(0x4e);
|
||||
utils.writeU32(res, instr.length, res.length);
|
||||
res = res.concat(instr);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
res.push(opcodes[instr] || instr);
|
||||
// res.push(script.opcodes[instr] || instr);
|
||||
res.push(instr);
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
script.opcodes = {
|
||||
0: 0,
|
||||
pushdata1: 0x4c,
|
||||
pushdata2: 0x4d,
|
||||
pushdata4: 0x4e,
|
||||
negate1: 0x4f,
|
||||
|
||||
nop: 0x61,
|
||||
if_: 0x63,
|
||||
notif: 0x64,
|
||||
else_: 0x67,
|
||||
endif: 0x68,
|
||||
verify: 0x69,
|
||||
ret: 0x6a,
|
||||
|
||||
toaltstack: 0x6b,
|
||||
fromaltstack: 0x6c,
|
||||
ifdup: 0x73,
|
||||
depth: 0x74,
|
||||
drop: 0x75,
|
||||
dup: 0x76,
|
||||
nip: 0x77,
|
||||
over: 0x78,
|
||||
pick: 0x79,
|
||||
roll: 0x7a,
|
||||
rot: 0x7b,
|
||||
swap: 0x7c,
|
||||
tuck: 0x7d,
|
||||
drop2: 0x6d,
|
||||
dup2: 0x6e,
|
||||
dup3: 0x6f,
|
||||
over2: 0x70,
|
||||
rot2: 0x71,
|
||||
swap2: 0x72,
|
||||
|
||||
cat: 0x74,
|
||||
substr: 0x7f,
|
||||
left: 0x80,
|
||||
right: 0x81,
|
||||
size: 0x82,
|
||||
|
||||
invert: 0x83,
|
||||
and: 0x84,
|
||||
or: 0x85,
|
||||
xor: 0x86,
|
||||
eq: 0x87,
|
||||
eqverify: 0x88,
|
||||
|
||||
add1: 0x8b,
|
||||
sub1: 0x8c,
|
||||
mul2: 0x8d,
|
||||
div2: 0x8e,
|
||||
negate: 0x8f,
|
||||
abs: 0x90,
|
||||
not: 0x91,
|
||||
noteq0: 0x92,
|
||||
add: 0x93,
|
||||
sub: 0x94,
|
||||
mul: 0x95,
|
||||
div: 0x96,
|
||||
mod: 0x97,
|
||||
lshift: 0x98,
|
||||
rshift: 0x99,
|
||||
booland: 0x9a,
|
||||
boolor: 0x9b,
|
||||
numeq: 0x9c,
|
||||
numeqverify: 0x9d,
|
||||
numneq: 0x9e,
|
||||
lt: 0x9f,
|
||||
gt: 0xa0,
|
||||
lte: 0xa1,
|
||||
gte: 0xa2,
|
||||
min: 0xa3,
|
||||
max: 0xa4,
|
||||
within: 0xa5,
|
||||
|
||||
ripemd160: 0xa6,
|
||||
sha1: 0xa7,
|
||||
sha256: 0xa8,
|
||||
hash160: 0xa9,
|
||||
hash256: 0xaa,
|
||||
codesep: 0xab,
|
||||
checksig: 0xac,
|
||||
checksigverify: 0xad,
|
||||
checkmultisig: 0xae,
|
||||
checkmultisigverify: 0xaf
|
||||
};
|
||||
|
||||
/**
|
||||
* Utils
|
||||
*/
|
||||
|
|
|
@ -271,6 +271,7 @@ struct async_broadcast_tx_data {
|
|||
std::string tx_hex;
|
||||
std::string tx_hash;
|
||||
bool override_fees;
|
||||
bool own_only;
|
||||
Persistent<Function> callback;
|
||||
};
|
||||
|
||||
|
@ -947,34 +948,32 @@ async_poll_mempool_after(uv_work_t *req) {
|
|||
}
|
||||
|
||||
/**
|
||||
* BroadcastTx(tx, override_fees, callback)
|
||||
* bitcoind.broadcastTx(tx, override_fees, callback)
|
||||
* BroadcastTx(tx, override_fees, own_only, callback)
|
||||
* bitcoind.broadcastTx(tx, override_fees, own_only, callback)
|
||||
*/
|
||||
|
||||
NAN_METHOD(BroadcastTx) {
|
||||
NanScope();
|
||||
|
||||
if (args.Length() < 3
|
||||
if (args.Length() < 4
|
||||
|| !args[0]->IsObject()
|
||||
|| !args[1]->IsBoolean()
|
||||
|| !args[2]->IsFunction()) {
|
||||
|| !args[2]->IsBoolean()
|
||||
|| !args[3]->IsFunction()) {
|
||||
return NanThrowError(
|
||||
"Usage: bitcoindjs.broadcastTx(tx, override_fees, callback)");
|
||||
"Usage: bitcoindjs.broadcastTx(tx, override_fees, own_only, callback)");
|
||||
}
|
||||
|
||||
Local<Object> js_tx = Local<Object>::Cast(args[0]);
|
||||
Local<Function> callback = Local<Function>::Cast(args[2]);
|
||||
Local<Function> callback = Local<Function>::Cast(args[3]);
|
||||
|
||||
String::Utf8Value tx_hex_(js_tx->Get(NanNew<String>("hex"))->ToString());
|
||||
std::string tx_hex = std::string(*tx_hex_);
|
||||
if (tx_hex[1] != 'x') {
|
||||
tx_hex = "0x" + tx_hex;
|
||||
}
|
||||
std::string strHex(tx_hex);
|
||||
|
||||
async_broadcast_tx_data *data = new async_broadcast_tx_data();
|
||||
data->tx_hex = strHex;
|
||||
data->tx_hex = tx_hex;
|
||||
data->override_fees = args[1]->ToBoolean()->IsTrue();
|
||||
data->own_only = args[2]->ToBoolean()->IsTrue();
|
||||
data->err_msg = std::string("");
|
||||
data->callback = Persistent<Function>::New(callback);
|
||||
|
||||
|
@ -994,16 +993,22 @@ static void
|
|||
async_broadcast_tx(uv_work_t *req) {
|
||||
async_broadcast_tx_data* data = static_cast<async_broadcast_tx_data*>(req->data);
|
||||
|
||||
const std::vector<unsigned char> tx_hex(data->tx_hex.begin(), data->tx_hex.end());
|
||||
CDataStream ssData(tx_hex, SER_NETWORK, PROTOCOL_VERSION);
|
||||
// const std::vector<unsigned char> tx_hex(data->tx_hex.begin(), data->tx_hex.end());
|
||||
// CDataStream ssData(tx_hex, SER_NETWORK, PROTOCOL_VERSION);
|
||||
CDataStream ssData(ParseHex(data->tx_hex), SER_NETWORK, PROTOCOL_VERSION);
|
||||
CTransaction tx;
|
||||
|
||||
bool fOverrideFees = false;
|
||||
bool fOwnOnly = false;
|
||||
|
||||
if (data->override_fees) {
|
||||
fOverrideFees = true;
|
||||
}
|
||||
|
||||
if (data->own_only) {
|
||||
fOwnOnly = true;
|
||||
}
|
||||
|
||||
try {
|
||||
ssData >> tx;
|
||||
} catch (std::exception &e) {
|
||||
|
@ -1016,7 +1021,7 @@ async_broadcast_tx(uv_work_t *req) {
|
|||
bool fHave = false;
|
||||
CCoinsViewCache &view = *pcoinsTip;
|
||||
CCoins existingCoins;
|
||||
{
|
||||
if (ownOnly) {
|
||||
fHave = view.GetCoins(hashTx, existingCoins);
|
||||
if (!fHave) {
|
||||
CValidationState state;
|
||||
|
|
Loading…
Reference in New Issue