Пример #1
0
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);
}
Пример #2
0
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);
}
Пример #3
0
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;
}
Пример #4
0
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;
}