static void script_tx_sighash(struct wallet *wallet, uint256 *hash, const struct buff *scriptPubKey, const struct btc_msg_tx *tx, uint32 idx, enum script_hash_type hashType) { struct btc_msg_tx *tx2; struct buff *buf; int i; ASSERT(idx < tx->in_count); memset(hash, 0, sizeof *hash); tx2 = btc_msg_tx_dup(tx); Log(LGPFX " Computing sighash for txi-%u/%llu\n", idx, tx2->in_count); /* * Zero-out all the inputs' signatures. */ for (i = 0; i < tx2->in_count; i++) { tx2->tx_in[i].scriptLength = 0; } size_t len = buff_maxlen(scriptPubKey); ASSERT(len > 0); ASSERT(tx2->tx_in[idx].scriptSig == NULL); ASSERT(tx2->tx_in[idx].scriptLength == 0); tx2->tx_in[idx].scriptLength = len; tx2->tx_in[idx].scriptSig = safe_malloc(len); memcpy(tx2->tx_in[idx].scriptSig, buff_base(scriptPubKey), len); ASSERT((hashType & 0x1f) == SIGHASH_ALL); /* * Final step: * * Serialize tx + hashType (as a uint32) and compute hash. */ buf = buff_alloc(); serialize_tx(buf, tx2); serialize_uint32(buf, hashType); hash256_calc(buff_base(buf), buff_curlen(buf), hash); buff_free(buf); btc_msg_tx_free(tx2); free(tx2); }
int txdb_craft_tx(struct txdb *txdb, const struct btc_tx_desc *tx_desc, btc_msg_tx *tx) { struct buff *buf; char hashStr[80]; uint256 txHash; uint64 change; uint32 numCoins; bool relevant; mtime_t ts; int res; res = 0; relevant = 0; tx->version = 1; txdb_prepare_txout(tx_desc, tx); /* * In order to properly size 'tx->txIn', we need to determine how many coins * we're going to use. Right now, let's just vastly overestimate. */ numCoins = hashtable_getnumentries(txdb->hash_txo); tx->tx_in = safe_calloc(numCoins, sizeof *tx->tx_in); txdb_print_coins(txdb, 1); txdb_select_coins(txdb, tx_desc, tx, &change); /* * Change! XXX: fix me. */ if (change > 0) { const char *btc_change; btc_change = wallet_get_change_addr(btc->wallet); tx->out_count++; txdb_set_txo(tx, tx->out_count - 1, btc_change, change); Warning(LGPFX" change: %llu -- %.8f BTC\n", change, change / ONE_BTC); } txdb_sign_tx_inputs(txdb, tx); /* * Now that the tx is ready, serialize it and check that it's not too big. */ btcmsg_print_tx(tx); buf = buff_alloc(); serialize_tx(buf, tx); if (buff_curlen(buf) > BTC_TX_MAX_SIZE) { Warning(LGPFX" tx too large: %zu\n", buff_curlen(buf)); res = 1; goto exit; } hash256_calc(buff_base(buf), buff_curlen(buf), &txHash); uint256_snprintf_reverse(hashStr, sizeof hashStr, &txHash); Warning(LGPFX" %s (%zu bytes)\n", hashStr, buff_curlen(buf)); Log_Bytes(LGPFX" TX: ", buff_base(buf), buff_curlen(buf)); if (bitc_testing) { Warning("TESTING! Not saving/relaying tx.\n"); goto exit; } ts = time(NULL); res = txdb_remember_tx(txdb, 0 /* save to disk */, ts, buff_base(buf), buff_curlen(buf), &txHash, NULL, &relevant); txdb_save_tx_label(tx_desc, hashStr); txdb_export_tx_info(txdb); res = peergroup_new_tx_broadcast(btc->peerGroup, buf, ts + 2 * 60 * 60, &txHash); if (res) { Warning(LGPFX" failed to transmit tx: %d\n", res); bitcui_set_status("got errors while broadcasting tx"); } exit: buff_free(buf); /* * XXX: We should mark the coins used by this tx as "reserved", so that we * do not attempt to use conflicting coins in subsequent TXs. */ return res; }