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 bp_tx_sighash(bu256_t *hash, const GString *scriptCode, const struct bp_tx *txTo, unsigned int nIn, int nHashType) { if (nIn >= txTo->vin->len) { bu256_set_u64(hash, 1); goto out; } struct bp_tx txTmp; bp_tx_init(&txTmp); bp_tx_copy(&txTmp, txTo); /* TODO: find-and-delete OP_CODESEPARATOR from scriptCode */ /* Blank out other inputs' signatures */ unsigned int i; struct bp_txin *txin; for (i = 0; i < txTmp.vin->len; i++) { txin = g_ptr_array_index(txTmp.vin, i); g_string_set_size(txin->scriptSig, 0); if (i == nIn) g_string_append_len(txin->scriptSig, scriptCode->str, scriptCode->len); } /* Blank out some of the outputs */ if ((nHashType & 0x1f) == SIGHASH_NONE) { /* Wildcard payee */ bp_tx_free_vout(&txTmp); txTmp.vout = g_ptr_array_new_full(1, g_free); /* Let the others update at will */ for (i = 0; i < txTmp.vin->len; i++) { txin = g_ptr_array_index(txTmp.vin, i); if (i != nIn) txin->nSequence = 0; } } else if ((nHashType & 0x1f) == SIGHASH_SINGLE) { /* Only lock-in the txout payee at same index as txin */ unsigned int nOut = nIn; if (nOut >= txTmp.vout->len) { bu256_set_u64(hash, 1); goto out; } g_ptr_array_set_size(txTmp.vout, nOut + 1); for (i = 0; i < nOut; i++) { struct bp_txout *txout; txout = g_ptr_array_index(txTmp.vout, i); bp_txout_set_null(txout); } /* Let the others update at will */ for (i = 0; i < txTmp.vin->len; i++) { txin = g_ptr_array_index(txTmp.vin, i); if (i != nIn) txin->nSequence = 0; } } /* Blank out other inputs completely; not recommended for open transactions */ if (nHashType & SIGHASH_ANYONECANPAY) { if (nIn > 0) g_ptr_array_remove_range(txTmp.vin, 0, nIn); g_ptr_array_set_size(txTmp.vin, 1); } /* Serialize and hash */ bp_tx_calc_sighash(hash, &txTmp, nHashType); out: bp_tx_free(&txTmp); }