static bool bp_checksig(const struct buffer *vchSigIn, const struct buffer *vchPubKey, const cstring *scriptCode, const struct bp_tx *txTo, unsigned int nIn) { if (!vchSigIn || !vchPubKey || !scriptCode || !txTo || !vchSigIn->len || !vchPubKey->len || !scriptCode->len) return false; // Hash type is one byte tacked on to the end of the signature unsigned char *vch_back = vchSigIn->p + (vchSigIn->len - 1); int nHashType = *vch_back; struct buffer vchSig = { vchSigIn->p, vchSigIn->len - 1 }; /* calculate signature hash of transaction */ bu256_t sighash; bp_tx_sighash(&sighash, scriptCode, txTo, nIn, nHashType); /* verify signature hash */ struct bp_key pubkey; bp_key_init(&pubkey); bool rc = false; if (!bp_pubkey_set(&pubkey, vchPubKey->p, vchPubKey->len)) goto out; if (!bp_verify(&pubkey, &sighash, sizeof(sighash), vchSig.p, vchSig.len)) goto out; rc = true; out: bp_key_free(&pubkey); return rc; }
static bool bp_checksig(const struct buffer *vchSigHT, const struct buffer *vchPubKey, const GString *scriptCode, const struct bp_tx *txTo, unsigned int nIn, int nHashType) { if (!vchSigHT || !vchPubKey || !scriptCode || !txTo || !vchSigHT->len || !vchPubKey->len || !scriptCode->len) return false; /* examine hashtype at end of string, then remove it */ unsigned char *vch_back = vchSigHT->p + (vchSigHT->len - 1); if (nHashType == 0) nHashType = *vch_back; else if (nHashType != *vch_back) return false; struct buffer vchSig = { vchSigHT->p, vchSigHT->len - 1 }; /* calculate signature hash of transaction */ bu256_t sighash; bp_tx_sighash(&sighash, scriptCode, txTo, nIn, nHashType); /* verify signature hash */ struct bp_key key; bp_key_init(&key); bool rc = false; if (!bp_pubkey_set(&key, vchPubKey->p, vchPubKey->len)) goto out; if (!bp_verify(&key, &sighash, sizeof(sighash), vchSig.p, vchSig.len)) goto out; rc = true; out: bp_key_free(&key); return rc; }
bool bp_script_sign(struct bp_keystore *ks, const cstring *fromPubKey, const struct bp_tx *txTo, unsigned int nIn, int nHashType) { if (!txTo || !txTo->vin || nIn >= txTo->vin->len) return false; struct bp_txin *txin = parr_idx(txTo->vin, nIn); /* get signature hash */ bu256_t hash; bp_tx_sighash(&hash, fromPubKey, txTo, nIn, nHashType); /* match fromPubKey against templates, to find what pubkey[hashes] * are required for signing */ struct bscript_addr addrs; if (!bsp_addr_parse(&addrs, fromPubKey->str, fromPubKey->len)) return false; cstring *scriptSig = cstr_new_sz(64); bool rc = false; bu160_t key_id; struct buffer *kbuf; /* sign, based on script template matched above */ switch (addrs.txtype) { case TX_PUBKEY: kbuf = addrs.pub->data; bu_Hash160((unsigned char *)&key_id, kbuf->p, kbuf->len); if (!sign1(&key_id, ks, &hash, nHashType, scriptSig)) goto out; break; case TX_PUBKEYHASH: kbuf = addrs.pubhash->data; memcpy(&key_id, kbuf->p, kbuf->len); if (!sign1(&key_id, ks, &hash, nHashType, scriptSig)) goto out; if (!bkeys_pubkey_append(ks, &key_id, scriptSig)) goto out; break; case TX_SCRIPTHASH: /* TODO; not supported yet */ case TX_MULTISIG: goto out; case TX_NONSTANDARD: /* unknown script type, cannot sign */ goto out; } if (txin->scriptSig) cstr_free(txin->scriptSig, true); txin->scriptSig = scriptSig; scriptSig = NULL; rc = true; out: if (scriptSig) cstr_free(scriptSig, true); bsp_addr_free(&addrs); return rc; }