void bp_tx_sighash(bu256_t *hash, const cstring *scriptCode, const struct bp_tx *txTo, unsigned int nIn, int nHashType) { if (nIn >= txTo->vin->len) { // nIn out of range bu256_set_u64(hash, 1); return; } // Check for invalid use of SIGHASH_SINGLE if ((nHashType & 0x1f) == SIGHASH_SINGLE) { if (nIn >= txTo->vout->len) { // nOut out of range bu256_set_u64(hash, 1); return; } } cstring *s = cstr_new_sz(512); // Serialize only the necessary parts of the transaction being signed bp_tx_sigserializer(s, scriptCode, txTo, nIn, nHashType); ser_s32(s, nHashType); bu_Hash((unsigned char *) hash, s->str, s->len); cstr_free(s, true); }
void btc_tx_serialize(cstring* s, const btc_tx* tx) { ser_s32(s, tx->version); ser_varlen(s, tx->vin ? tx->vin->len : 0); unsigned int i; if (tx->vin) { for (i = 0; i < tx->vin->len; i++) { btc_tx_in* tx_in; tx_in = vector_idx(tx->vin, i); btc_tx_in_serialize(s, tx_in); } } ser_varlen(s, tx->vout ? tx->vout->len : 0); if (tx->vout) { for (i = 0; i < tx->vout->len; i++) { btc_tx_out* tx_out; tx_out = vector_idx(tx->vout, i); btc_tx_out_serialize(s, tx_out); } } ser_u32(s, tx->locktime); }
static void bp_tx_calc_sighash(bu256_t *hash, const struct bp_tx *tx, int nHashType) { /* TODO: introduce hashing-only serialization mode */ GString *s = g_string_sized_new(512); ser_bp_tx(s, tx); ser_s32(s, nHashType); bu_Hash((unsigned char *) hash, s->str, s->len); g_string_free(s, TRUE); }
btc_bool btc_tx_sighash(const btc_tx* tx_to, const cstring* fromPubKey, unsigned int in_num, int hashtype, uint8_t* hash) { if (in_num >= tx_to->vin->len) return false; btc_bool ret = true; btc_tx* tx_tmp = btc_tx_new(); btc_tx_copy(tx_tmp, tx_to); cstring* new_script = cstr_new_sz(fromPubKey->len); btc_script_copy_without_op_codeseperator(fromPubKey, new_script); unsigned int i; btc_tx_in* tx_in; for (i = 0; i < tx_tmp->vin->len; i++) { tx_in = vector_idx(tx_tmp->vin, i); cstr_resize(tx_in->script_sig, 0); if (i == in_num) cstr_append_buf(tx_in->script_sig, new_script->str, new_script->len); } cstr_free(new_script, true); /* Blank out some of the outputs */ if ((hashtype & 0x1f) == SIGHASH_NONE) { /* Wildcard payee */ if (tx_tmp->vout) vector_free(tx_tmp->vout, true); tx_tmp->vout = vector_new(1, btc_tx_out_free_cb); /* Let the others update at will */ for (i = 0; i < tx_tmp->vin->len; i++) { tx_in = vector_idx(tx_tmp->vin, i); if (i != in_num) tx_in->sequence = 0; } } else if ((hashtype & 0x1f) == SIGHASH_SINGLE) { /* Only lock-in the txout payee at same index as txin */ unsigned int n_out = in_num; if (n_out >= tx_tmp->vout->len) { //TODO: set error code ret = false; goto out; } vector_resize(tx_tmp->vout, n_out + 1); for (i = 0; i < n_out; i++) { btc_tx_out* tx_out; tx_out = vector_idx(tx_tmp->vout, i); tx_out->value = -1; if (tx_out->script_pubkey) { cstr_free(tx_out->script_pubkey, true); tx_out->script_pubkey = NULL; } } /* Let the others update at will */ for (i = 0; i < tx_tmp->vin->len; i++) { tx_in = vector_idx(tx_tmp->vin, i); if (i != in_num) tx_in->sequence = 0; } } /* Blank out other inputs completely; not recommended for open transactions */ if (hashtype & SIGHASH_ANYONECANPAY) { if (in_num > 0) vector_remove_range(tx_tmp->vin, 0, in_num); vector_resize(tx_tmp->vin, 1); } cstring* s = cstr_new_sz(512); btc_tx_serialize(s, tx_tmp); ser_s32(s, hashtype); sha256_Raw((const uint8_t*)s->str, s->len, hash); sha256_Raw(hash, 32, hash); cstr_free(s, true); out: btc_tx_free(tx_tmp); return ret; }