示例#1
0
文件: script.c 项目: jma127/bitc-rpc
int script_parse_pubkey_hash(const uint8 *scriptPubKey, size_t scriptLength,
                             uint160 *pubkey) {
  enum script_txout_type type;
  struct buff buf;
  size_t datalen;
  uint8 *data;
  int res;

  uint160_zero_out(pubkey);
  buff_init(&buf, (uint8 *)scriptPubKey, scriptLength);

  res = script_match_type(&buf, &type, &data, &datalen);
  if (res) {
    NOT_TESTED();
    return 1;
  }

  switch (type) {
    case TX_PUBKEY:
      Warning(LGPFX " script TX_PUBKEY\n");
      NOT_TESTED();
      hash160_calc(data, datalen, pubkey);
      break;
    case TX_PUBKEYHASH:
      ASSERT(datalen == sizeof(uint160));
      memcpy(pubkey, data, sizeof(uint160));
      break;
    default:
      NOT_TESTED();
      res = 1;
      break;
  }
  free(data);
  return res;
}
示例#2
0
文件: bitc_ui.c 项目: jma127/bitc-rpc
static int bitcui_notify_init(int *readFd, int *writeFd) {
  int fd[2];
  int flags;
  int res;

  res = pipe(fd);
  if (res != 0) {
    res = errno;
    Log(LGPFX " Failed to create pipe: %s\n", strerror(res));
    return res;
  }
  *readFd = fd[0];
  *writeFd = fd[1];

  flags = fcntl(*readFd, F_GETFL, 0);
  if (flags < 0) {
    NOT_TESTED();
    return flags;
  }

  res = fcntl(*readFd, F_SETFL, flags | O_NONBLOCK);
  if (res < 0) {
    NOT_TESTED();
    return res;
  }
  poll_callback_device(btcui->poll, btcui->eventFd, 1, 0, 1, bitcui_notify_cb,
                       NULL);
  btcui->notifyInit = 1;

  return 0;
}
示例#3
0
文件: key.c 项目: jma127/bitc-rpc
bool key_sign(struct key *k, const void *data, size_t datalen, uint8 **sig,
              size_t *siglen)

{
  unsigned int len;
  uint8 *sig0;
  int res;

  ASSERT(sig);
  ASSERT(siglen);

  len = ECDSA_size(k->key);
  sig0 = safe_calloc(1, len);

  res = ECDSA_sign(0, data, datalen, sig0, &len, k->key);
  if (res != 1) {
    NOT_TESTED();
    free(sig0);
    return 0;
  }
  *sig = sig0;
  *siglen = len;

  return 1;
}
示例#4
0
文件: txdb.c 项目: haraldh/bitc
static void
txdb_select_coins(struct txdb              *txdb,
                  const struct btc_tx_desc *desc,
                  btc_msg_tx               *tx,
                  uint64                   *change)
{
    struct txo_entry *txo_array;
    uint64 value;
    int txo_num;
    int i;

    i = 0;
    value = 0;
    tx->in_count = 0;
    txo_array = txdb_get_coins_sorted(txdb);
    txo_num = hashtable_getnumentries(txdb->hash_txo);

    /*
     * txo_array is sorted in chronological order, so we'll be consuming old
     * coins first.
     */
    Log(LGPFX" select_coins: total_value=%llu fee=%llu\n",
        desc->total_value, desc->fee);

    while (value < (desc->total_value + desc->fee) && i < txo_num) {
        struct txo_entry *txo_ent = &txo_array[i++];
        char hashStr[80];

        if (txo_ent->spent == 1 ||
                txo_ent->spendable == 0) {
            continue;
        }
        if (uint256_iszero(&txo_ent->blkHash)) {
            NOT_TESTED();
            continue;
        }

        uint256_snprintf_reverse(hashStr, sizeof hashStr, &txo_ent->txHash);
        Log(LGPFX" using txo for %s id=%3u of %s\n",
            txo_ent->btc_addr, txo_ent->outIdx, hashStr);
        value += txo_ent->value;
        memcpy(&tx->tx_in[tx->in_count].prevTxHash, &txo_ent->txHash, sizeof txo_ent->txHash);
        tx->tx_in[tx->in_count].prevTxOutIdx = txo_ent->outIdx;
        tx->tx_in[tx->in_count].sequence = UINT_MAX;
        tx->in_count++;
    }

    ASSERT(value >= desc->total_value);
    *change = value - desc->total_value - desc->fee;
    Log(LGPFX" change=%llu\n", *change);
    free(txo_array);
}
示例#5
0
文件: wallet.c 项目: Methimpact/bitc
static struct wallet *
wallet_open_file(struct config      *config,
                 struct secure_area *pass,
                 char              **errStr,
                 enum wallet_state  *wallet_state)
{
   struct wallet *wallet;
   struct config *wcfg;
   int res;

   *wallet_state = WALLET_UNKNOWN;

   wallet = safe_calloc(1, sizeof *wallet);
   wallet->filename   = wallet_get_filename();
   wallet->hash_keys  = hashtable_create();
   wallet->pass       = pass;
   wallet->ckey_store = secure_alloc(sizeof *wallet->ckey);
   wallet->ckey       = (struct crypt_key *)wallet->ckey_store->buf;

   if (!file_exists(wallet->filename)) {
      wcfg = config_create();
   } else {
      res = config_load(wallet->filename, &wcfg);
      if (res) {
         *errStr = "failed to read wallet file";
         NOT_TESTED();
         goto exit;
      }
   }

   res = wallet_load_keys(wallet, errStr, wcfg, wallet_state);
   config_free(wcfg);
   if (res) {
      goto exit;
   }

   ASSERT(wallet);

   return wallet;
exit:

   wallet_close(wallet);

   return NULL;
}
示例#6
0
文件: key.c 项目: jma127/bitc-rpc
static bool key_get_pubkey_int(struct key *k, uint8 **pub, size_t *len) {
  uint8 *data;

  ASSERT(pub);
  *pub = NULL;
  *len = 0;

  if (!EC_KEY_check_key(k->key)) {
    NOT_TESTED();
    return 0;
  }

  *len = i2o_ECPublicKey(k->key, 0);
  ASSERT(*len <= 65);
  data = safe_malloc(*len);
  *pub = data;
  i2o_ECPublicKey(k->key, &data);

  return 1;
}
示例#7
0
文件: config.c 项目: BitJaeger/bitc
int64
config_getint64(struct config *config,
                int64          defaultValue,
                const char    *format,
                ...)
{
   struct KeyValuePair *e;
   char key[1024];
   va_list ap;

   ASSERT(config);
   ASSERT(format);

   va_start(ap, format);
   vsnprintf(key, sizeof key, format, ap);
   va_end(ap);

   e = config_get(config, key);

   if (e) {
      if (e->type == CONFIG_KV_UNKNOWN) {
#ifdef __CYGWIN__
         int64 v = atol(e->u.str);
         NOT_TESTED();
#else
         int64 v = atoll(e->u.str);
#endif
         free(e->u.str);
         e->u.val = v;
         e->type = CONFIG_KV_INT64;
      } else {
         ASSERT(e->type == CONFIG_KV_INT64);
      }
      return e->u.val;
   } else {
      config_setint64(config, defaultValue, "%s", key);
      e = config_get(config, key);
      e->save = 0;
      return defaultValue;
   }
}
示例#8
0
文件: script.c 项目: jma127/bitc-rpc
static int script_match_type(struct buff *buf, enum script_txout_type *type,
                             uint8 **data_addr, size_t *data_len) {
  struct script *script;

  ASSERT(type);
  ASSERT(data_addr);
  ASSERT(data_len);

  *data_addr = NULL;

  script = script_parse(buf);
  if (script == NULL) {
    NOT_TESTED();
    return 1;
  }

  *type = script_classify(script);

  switch (*type) {
    case TX_PUBKEY:
      *data_len = script->inst[0].len;
      *data_addr = safe_malloc(*data_len);
      memcpy(*data_addr, script->inst[0].data, *data_len);
      ASSERT(*data_addr);
      break;
    case TX_PUBKEYHASH:
      *data_len = script->inst[2].len;
      *data_addr = safe_malloc(*data_len);
      ASSERT(*data_len == sizeof(uint160));
      memcpy(*data_addr, script->inst[2].data, *data_len);
      break;
    default:
      *data_addr = NULL;
      *data_len = 0;
      break;
  }

  script_free(script);
  return 0;
}
示例#9
0
文件: txdb.c 项目: haraldh/bitc
static void
txdb_remove_from_hashtable(struct txdb      *txdb,
                           const uint256    *txHash)
{
    struct tx_entry *txe;
    char hashStr[80];
    bool s;

    txe = txdb_get_tx_entry(txdb, txHash);
    if (txe == NULL || txe->relevant == 1) {
        NOT_TESTED();
        return;
    }

    txdb_free_tx_entry(txe);

    uint256_snprintf_reverse(hashStr, sizeof hashStr, txHash);

    s = hashtable_remove(txdb->hash_tx, txHash, sizeof *txHash);
    Warning(LGPFX" %s removed from hash_tx: %d (count=%u)\n",
            hashStr, s, hashtable_getnumentries(txdb->hash_tx));
}
示例#10
0
int deserialize_str(struct buff *buf, char *str, size_t size) {
  uint64 len;
  int res;

  memset(str, 0, size);

  res = deserialize_varint(buf, &len);
  if (res) {
    return res;
  }
  if (len == 0) {
    return 0;
  }

  if (len >= size) {
    NOT_TESTED();
    return 1;
  }
  str[size - 1] = '\0';
  if (len < size) {
    str[len] = '\0';
  }
  return deserialize_bytes(buf, str, len);
}
示例#11
0
static int
blockset_open_file(struct blockstore *blockStore,
                   struct blockset *bs)
{
   uint64 offset;
   mtime_t ts;
   int res;

   res = file_open(bs->filename, 0 /* R/O */, 0 /* !unbuf */, &bs->desc);
   if (res) {
      return res;
   }

   bs->filesize = file_getsize(bs->desc);
   if (bs->filesize < 0) {
      return errno;
   }

   if (bs->filesize > 0) {
      char *s = print_size(bs->filesize);
      char *name = file_getname(bs->filename);
      Log(LGPFX" reading file %s -- %s -- %llu headers.\n",
          name, s, bs->filesize / sizeof(btc_block_header));
      free(name);
      free(s);
   }

   ts = time_get();
   offset = 0;
   while (offset < bs->filesize) {
      btc_block_header buf[10000];
      size_t numRead;
      size_t numBytes;
      int numHeaders;
      int i;

      numBytes = MIN(bs->filesize - offset, sizeof buf);

      res = file_pread(bs->desc, offset, buf, numBytes, &numRead);
      if (res != 0) {
         break;
      }

      if (btc->stop != 0) {
         res = 1;
         NOT_TESTED();
         break;
      }

      numHeaders = numRead / sizeof(btc_block_header);
      for (i = 0; i < numHeaders; i++) {
         struct blockentry *be;
         uint256 hash;

         be = blockstore_alloc_entry(buf + i);
         be->written = 1;
         hash256_calc(buf + i, sizeof buf[0], &hash);

         if (!blockstore_validate_chkpt(&hash, blockStore->height + 1)) {
            return 1;
         }

         blockstore_add_entry(blockStore, be, &hash);

         if (i == numHeaders - 1) {
            bitcui_set_status("loading headers .. %llu%%",
                             (offset + numBytes) * 100 / bs->filesize);
         }
         if (i == numHeaders - 1 ||
             (numBytes < sizeof buf && i > numHeaders - 256)) {
            bitcui_set_last_block_info(&hash, blockStore->height,
                                      be->header.timestamp);
         }
      }

      offset += numRead;
   }

   ts = time_get() - ts;

   char hashStr[80];
   char *latStr;

   uint256_snprintf_reverse(hashStr, sizeof hashStr, &blockStore->best_hash);
   Log(LGPFX" loaded blocks up to %s\n", hashStr);
   latStr = print_latency(ts);
   Log(LGPFX" this took %s\n", latStr);
   free(latStr);

   return res;
}
示例#12
0
文件: txdb.c 项目: haraldh/bitc
static int
txdb_remember_tx(struct txdb   *txdb,
                 bool           alreadySaved,
                 mtime_t        ts,
                 const uint8   *buf,
                 size_t         len,
                 const uint256 *txHash,
                 const uint256 *blkHash,
                 bool          *relevant)
{
    struct tx_entry *txe;
    char hashStr[80];
    int res;

    ASSERT(txHash);
    ASSERT(relevant);

    *relevant = 0;

    /*
     * We always store the tx in the memory pool, that way we know quickly
     * whether we've already seen it.
     */
    res = txdb_add_to_hashtable(txdb, buf, len, txHash, blkHash, ts, &txe);
    if (res) {
        NOT_TESTED();
        return res;
    }

    uint256_snprintf_reverse(hashStr, sizeof hashStr, txHash);
    txdb_process_tx_entry(txdb, txHash, blkHash, &txe->tx, &txe->relevant);
    if (txe->relevant == 0) {
        Warning(LGPFX" tx %s not relevant (%u)\n",
                hashStr, hashtable_getnumentries(txdb->hash_tx));
        return 0;
    }

    if (alreadySaved) {
        return 0;
    }

    /*
     * OK -- this transaction is relevant to our wallet.
     */
    *relevant = 1;
    Warning(LGPFX" tx %s ok (%u)\n", hashStr, hashtable_getnumentries(txdb->hash_tx));

    res = txdb_save_tx(txdb, blkHash, txHash, ts, buf, len);
    if (res == 0) {
        txdb->tx_seq++;
    }

    txdb_export_tx_info(txdb);
    if (bitc_state_ready()) {
        int64 value = txdb_get_tx_credit(&txe->tx) - txdb_get_tx_debit(&txe->tx);

        bitcui_set_status("New payment %s: %.8f BTC",
                          value > 0 ? "received" : "made",
                          1.0 * value / ONE_BTC);
    }

    return res;
}
示例#13
0
文件: txdb.c 项目: haraldh/bitc
void
txdb_confirm_one_tx(struct txdb   *txdb,
                    const uint256 *blkHash,
                    const uint256 *txHash)
{
    leveldb_iterator_t *iter;
    struct tx_entry *txe;
    char bkHashStr[80];
    char txHashStr[80];

    ASSERT(!uint256_iszero(blkHash));
    ASSERT(!uint256_iszero(txHash));

    txe = txdb_get_tx_entry(txdb, txHash);
    if (txe == NULL) {
        return;
    }

    if (txe->relevant == 0) {
        txdb_remove_from_hashtable(txdb, txHash);
        NOT_TESTED();
        return;
    }

    if (!uint256_iszero(&txe->blkHash)) {
        /*
         * It's possible for the ASSERT below to fire if a tx is confirmed in
         * a block that is later orphaned. The tx should then be relayed again
         * until it finds its way in a new block.
         */
        ASSERT(uint256_issame(&txe->blkHash, blkHash));
        return;
    }

    peergroup_stop_broadcast_tx(btc->peerGroup, txHash);
    memcpy(&txe->blkHash, blkHash, sizeof *blkHash);

    uint256_snprintf_reverse(bkHashStr, sizeof bkHashStr, blkHash);
    uint256_snprintf_reverse(txHashStr, sizeof txHashStr, txHash);
    Warning(LGPFX" %s confirmed in %s\n", txHashStr, bkHashStr);

    NOT_TESTED();

    iter = leveldb_create_iterator(txdb->db, txdb->rd_opts);
    leveldb_iter_seek_to_first(iter);

    while (leveldb_iter_valid(iter)) {
        struct tx_ser_key *txkey;
        struct tx_ser_data *txdata;
        struct buff *buf;
        const char *key;
        const char *val;
        size_t klen;
        size_t vlen;
        char *err = NULL;

        key = leveldb_iter_key(iter, &klen);
        txkey = txdb_deserialize_tx_key(key, klen);

        if (txkey == NULL || uint256_issame(txHash, &txkey->txHash) == 0) {
            free(txkey);
            leveldb_iter_next(iter);
            continue;
        }

        NOT_TESTED();

        val = leveldb_iter_value(iter, &vlen);
        txdata = txdb_deserialize_tx_data(val, vlen);
        ASSERT(uint256_iszero(&txdata->blkHash));
        ASSERT(txdata->timestamp != 0);
        memcpy(&txdata->blkHash, blkHash, sizeof *blkHash);

        buf = txdb_serialize_tx_data(txdata);

        leveldb_put(txdb->db, txdb->wr_opts, key, klen,
                    buff_base(buf), buff_curlen(buf), &err);
        buff_free(buf);
        if (err) {
            Warning(LGPFX" failed to write tx entry: %s\n", err);
        }

        txdb_export_tx_info(txdb);

        free(txkey);
        free(txdata->buf);
        free(txdata);
        break;
    }
    leveldb_iter_destroy(iter);
}
示例#14
0
文件: script.c 项目: jma127/bitc-rpc
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;
}