Example #1
0
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);
}
Example #2
0
File: txdb.c Project: haraldh/bitc
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;
}