diff --git a/lib/bitcoind.js b/lib/bitcoind.js index 308a0f32..71510727 100644 --- a/lib/bitcoind.js +++ b/lib/bitcoind.js @@ -448,6 +448,23 @@ Transaction.prototype.verify = function() { return this.verified = this.verified || bitcoindjs.verifyTransaction(this); }; +Transaction.prototype.sign = +Transaction.prototype.fill = function() { + var self = this; + var tx = Transaction.fill(this); + Object.keys(tx).forEach(function(key) { + self[key] = tx[key]; + }); + self.toHex(); +}; + +Transaction.sign = +Transaction.fill = function(tx) { + tx = bitcoin.tx(tx); + tx = bitcoindjs.fillTransaction(tx); + return bitcoin.tx(tx); +}; + Transaction.prototype.getSerializeSize = function() { ; }; diff --git a/src/bitcoindjs.cc b/src/bitcoindjs.cc index 81375cfd..5b78f800 100644 --- a/src/bitcoindjs.cc +++ b/src/bitcoindjs.cc @@ -137,6 +137,7 @@ NAN_METHOD(PollMempool); NAN_METHOD(BroadcastTx); NAN_METHOD(VerifyBlock); NAN_METHOD(VerifyTransaction); +NAN_METHOD(FillTransaction); NAN_METHOD(WalletNewAddress); NAN_METHOD(WalletGetAccountAddress); @@ -232,6 +233,12 @@ static inline void jstx_to_ctx(Local jstx, CTransaction& ctx); #endif +static inline void +hexblock_to_cblock(std::string block_hex, CBlock& cblock); + +static inline void +hextx_to_ctx(std::string tx_hex, CTransaction& ctx); + extern "C" void init(Handle); @@ -1207,6 +1214,45 @@ NAN_METHOD(VerifyTransaction) { NanReturnValue(NanNew(valid && standard)); } +NAN_METHOD(FillTransaction) { + NanScope(); + + if (args.Length() < 1 || !args[0]->IsObject()) { + return NanThrowError( + "Usage: bitcoindjs.fillTransaction(tx)"); + } + + Local js_tx = Local::Cast(args[0]); + + String::Utf8Value tx_hex_(js_tx->Get(NanNew("hex"))->ToString()); + std::string tx_hex = std::string(*tx_hex_); + + // jstx_to_ctx(jstx, ctx); + CTransaction tx; + CDataStream ssData(ParseHex(tx_hex), SER_NETWORK, PROTOCOL_VERSION); + ssData >> tx; + + // Fill vin + if (tx.vin.empty()) { + BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins) { + tx.vin.push_back(CTxIn(coin.first->GetHash(),coin.second)); + } + } + + // Sign + int nIn = 0; + BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins) { + if (!SignSignature(*pwalletMain, *coin.first, tx, nIn++)) { + return NanThrowError("Signing transaction failed"); + } + } + + Local entry = NanNew(); + ctx_to_jstx(tx, 0, entry); + + NanReturnValue(tx); +} + /** * Wallet */ @@ -2122,6 +2168,26 @@ jstx_to_ctx(Local jstx, CTransaction& ctx) { } #endif +static inline void +hexblock_to_cblock(std::string block_hex, CBlock& cblock) { + CDataStream ssData(ParseHex(block_hex), SER_NETWORK, PROTOCOL_VERSION); + try { + ssData >> cblock; + } catch (std::exception &e) { + NanThrowError("Block decode failed"); + } +} + +static inline void +hextx_to_ctx(std::string tx_hex, CTransaction& ctx) { + CDataStream ssData(ParseHex(tx_hex), SER_NETWORK, PROTOCOL_VERSION); + try { + ssData >> ctx; + } catch (std::exception &e) { + NanThrowError("TX decode failed"); + } +} + /** * Init */ @@ -2143,6 +2209,7 @@ init(Handle target) { NODE_SET_METHOD(target, "broadcastTx", BroadcastTx); NODE_SET_METHOD(target, "verifyBlock", VerifyBlock); NODE_SET_METHOD(target, "verifyTransaction", VerifyTransaction); + NODE_SET_METHOD(target, "fillTransaction", FillTransaction); NODE_SET_METHOD(target, "walletNewAddress", WalletNewAddress); NODE_SET_METHOD(target, "walletGetAccountAddress", WalletGetAccountAddress);