void key_get_pubkey_hash160(const struct key *k, uint160 *hash) { ASSERT(k->pub_key); ASSERT(k->pub_len > 0); Log_Bytes(LGPFX " pubkey: ", k->pub_key, k->pub_len); hash160_calc(k->pub_key, k->pub_len, hash); }
static void txdb_set_txo(btc_msg_tx *tx, int idx, const char *btc_addr, uint64 value) { struct btc_msg_tx_out *txo; uint160 pubkey; b58_pubkey_to_uint160(btc_addr, &pubkey); Log_Bytes(LGPFX" hash-addr:", &pubkey, sizeof pubkey); ASSERT(idx < tx->out_count); txo = tx->tx_out + idx; txo->value = value; script_txo_generate(&pubkey, &txo->scriptPubKey, &txo->scriptLength); }
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; }
int script_sign(struct wallet *wallet, const struct btc_msg_tx_out *txo, struct btc_msg_tx *tx, uint32 idx, enum script_hash_type hashType) { struct btc_msg_tx_in *txi; enum script_txout_type type; struct buff *scriptSig; struct buff scriptPubKey; uint8 *data_addr; size_t data_len; uint256 hash; int res; ASSERT(idx < tx->in_count); scriptSig = buff_alloc(); buff_init(&scriptPubKey, txo->scriptPubKey, txo->scriptLength); Log_Bytes("scriptPubKey:", txo->scriptPubKey, txo->scriptLength); script_tx_sighash(wallet, &hash, &scriptPubKey, tx, idx, hashType); res = script_match_type(&scriptPubKey, &type, &data_addr, &data_len); if (res) { NOT_TESTED(); goto exit; } switch (type) { case TX_PUBKEY: Warning(LGPFX " script TX_PUBKEY\n"); NOT_IMPLEMENTED(); break; case TX_PUBKEYHASH: (void)0; // XXX: clang bug? uint160 *keyHash = (uint160 *)data_addr; ASSERT(data_len == sizeof(uint160)); res = script_sign_hash(wallet, keyHash, &hash, hashType, scriptSig); if (res) { NOT_TESTED(); goto exit; } res = script_push_pubkey(wallet, keyHash, scriptSig); if (res) { NOT_TESTED(); goto exit; } break; default: NOT_IMPLEMENTED(); Warning(LGPFX " script TX_NONSTANDARD\n"); break; } txi = tx->tx_in + idx; txi->scriptLength = buff_curlen(scriptSig); txi->scriptSig = buff_base(scriptSig); exit: free(scriptSig); free(data_addr); return res; }