def test_get_output_size(self) -> None: pub = CPubKey(x('0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71')) a0 = P2PKHCoinAddress.from_pubkey(pub) self.assertEqual(P2PKHCoinAddress.get_output_size(), 34) self.assertEqual(a0.get_output_size(), 34) a1 = P2WPKHCoinAddress.from_pubkey(pub) self.assertEqual(P2WPKHCoinAddress.get_output_size(), 31) self.assertEqual(a1.get_output_size(), 31) a2 = P2SHCoinAddress.from_redeemScript( CScript(b'\xa9' + Hash160(pub) + b'\x87')) self.assertEqual(P2SHCoinAddress.get_output_size(), 32) self.assertEqual(a2.get_output_size(), 32) a3 = P2WSHCoinAddress.from_redeemScript( CScript(b'\xa9' + Hash160(pub) + b'\x87')) self.assertEqual(P2WSHCoinAddress.get_output_size(), 43) self.assertEqual(a3.get_output_size(), 43)
def pubkey_to_p2wpkh_script(pub): """ Given a pubkey in bytes (compressed), return a CScript representing the corresponding pay-to-witness-pubkey-hash scriptPubKey. """ return P2WPKHCoinAddress.from_pubkey(pub).to_scriptPubKey()
def get_unconfidential_address_samples(pub1, pub2): return AddressSamples( p2pkh=P2PKHCoinAddress.from_pubkey(pub1), p2wpkh=P2WPKHCoinAddress.from_pubkey(pub1), p2sh=P2SHCoinAddress.from_redeemScript( CScript(b'\xa9' + Hash160(pub1) + b'\x87')), p2wsh=P2WSHCoinAddress.from_redeemScript( CScript(b'\xa9' + Hash160(pub1) + b'\x87')), conf_p2pkh=P2PKHCoinConfidentialAddress.from_unconfidential( P2PKHCoinAddress.from_pubkey(pub1), pub2), conf_p2wpkh=P2WPKHCoinConfidentialAddress.from_unconfidential( P2WPKHCoinAddress.from_pubkey(pub1), pub2), conf_p2sh=P2SHCoinConfidentialAddress.from_unconfidential( P2SHCoinAddress.from_redeemScript( CScript(b'\xa9' + Hash160(pub1) + b'\x87')), pub2), conf_p2wsh=P2WSHCoinConfidentialAddress.from_unconfidential( P2WSHCoinAddress.from_redeemScript( CScript(b'\xa9' + Hash160(pub1) + b'\x87')), pub2))
def derive_address(self): bip_keypath = HDKeyPath(self.key_path[:BIP_KEYPATH_INDEX]) if bip_keypath == bip_44_keypath(): self._address = P2PKHAddress.from_pubkey(self.pub_key) elif bip_keypath == bip_84_keypath(): self._address = P2WPKHAddress.from_pubkey(self.pub_key) elif bip_keypath == bip_49_keypath(): self._address = WalletAddress.make_wrapped_segwit_address( self.pub_key) else: raise Exception
def test_sighash(self) -> None: spent_amount = 1100 pub = CKey.from_secret_bytes(os.urandom(32)).pub spk_legacy = P2PKHCoinAddress.from_pubkey(pub).to_scriptPubKey() spk_segwit = P2WPKHCoinAddress.from_pubkey(pub).to_scriptPubKey() tx = CTransaction([ CTxIn( COutPoint(b'\x00' * 32, 0), CScript([]), nSequence=0xFFFFFFFF) ], [CTxOut(1000, spk_legacy)], nLockTime=0, nVersion=1) # no exceptions should be raised with these two calls spk_legacy.sighash(tx, 0, SIGHASH_ALL, amount=spent_amount, sigversion=SIGVERSION_WITNESS_V0) spk_segwit.sighash(tx, 0, SIGHASH_ALL, amount=spent_amount, sigversion=SIGVERSION_WITNESS_V0) with self.assertRaises(ValueError): # unknown sigversion spk_segwit.sighash(tx, 0, SIGHASH_ALL, amount=spent_amount, sigversion=SIGVERSION_WITNESS_V0 + 1) # type: ignore assert spk_segwit.is_witness_scriptpubkey() with self.assertRaises(ValueError): # incorect sigversion for segwit spk_segwit.sighash(tx, 0, SIGHASH_ALL, amount=spent_amount, sigversion=SIGVERSION_BASE) with self.assertRaises(ValueError): # inIdx > len(tx.vin) - non-raw sighash function should raise # ValueError (raw_sighash can return HASH_ONE) spk_legacy.sighash(tx, 10, SIGHASH_ALL, amount=spent_amount, sigversion=SIGVERSION_BASE)
async def async_regtest() -> None: select_chain_params('bitcoin/regtest') a = P2WPKHCoinAddress.from_pubkey(pub) witver, data = bitcointx.segwit_addr.decode( P2WPKHBitcoinRegtestAddress.bech32_hrp, str(a)) assert witver == 0 assert data == Hash160(pub) check_core_modules() ready('regtest') await wait_async('testnet') await wait_async('mainnet') self.assertEqual(get_current_chain_params().NAME, 'bitcoin/regtest') finish('regtest')
def sign(tx, i, priv, hashcode=SIGHASH_ALL, amount=None, native=False): """ Given a transaction tx of type CMutableTransaction, an input index i, and a raw privkey in bytes, updates the CMutableTransaction to contain the newly appended signature. Only four scriptPubKey types supported: p2pkh, p2wpkh, p2sh-p2wpkh, p2wsh. Note that signing multisig must be done outside this function, using the wrapped library. If native is not the default (False), and if native != "p2wpkh", then native must be a CScript object containing the redeemscript needed to sign. Returns: (signature, "signing succeeded") or: (None, errormsg) in case of failure """ # script verification flags flags = set([SCRIPT_VERIFY_STRICTENC]) def return_err(e): return None, "Error in signing: " + repr(e) assert isinstance(tx, CMutableTransaction) pub = privkey_to_pubkey(priv) if not amount: # p2pkh only supported here: input_scriptPubKey = pubkey_to_p2pkh_script(pub) sighash = SignatureHash(input_scriptPubKey, tx, i, hashcode) try: sig = ecdsa_raw_sign(sighash, priv, rawmsg=True) + bytes( [hashcode]) except Exception as e: return return_err(e) tx.vin[i].scriptSig = CScript([sig, pub]) # Verify the signature worked. try: VerifyScript(tx.vin[i].scriptSig, input_scriptPubKey, tx, i, flags=flags) except Exception as e: return return_err(e) return sig, "signing succeeded" else: # segwit case; we currently support p2wpkh native or under p2sh. # https://github.com/Simplexum/python-bitcointx/blob/648ad8f45ff853bf9923c6498bfa0648b3d7bcbd/bitcointx/core/scripteval.py#L1250-L1252 flags.add(SCRIPT_VERIFY_P2SH) if native and native != "p2wpkh": scriptCode = native input_scriptPubKey = redeem_script_to_p2wsh_script(native) else: # this covers both p2wpkh and p2sh-p2wpkh case: input_scriptPubKey = pubkey_to_p2wpkh_script(pub) # only created for convenience access to scriptCode: input_address = P2WPKHCoinAddress.from_scriptPubKey( input_scriptPubKey) # function name is misleading here; redeemScript only applies to p2sh. scriptCode = input_address.to_redeemScript() sighash = SignatureHash(scriptCode, tx, i, hashcode, amount=amount, sigversion=SIGVERSION_WITNESS_V0) try: sig = ecdsa_raw_sign(sighash, priv, rawmsg=True) + bytes( [hashcode]) except Exception as e: return return_err(e) if native: flags.add(SCRIPT_VERIFY_WITNESS) else: tx.vin[i].scriptSig = CScript([input_scriptPubKey]) if native and native != "p2wpkh": witness = [sig, scriptCode] else: witness = [sig, pub] ctxwitness = CTxInWitness(CScriptWitness(witness)) tx.wit.vtxinwit[i] = ctxwitness # Verify the signature worked. try: VerifyScript(tx.vin[i].scriptSig, input_scriptPubKey, tx, i, flags=flags, amount=amount, witness=tx.wit.vtxinwit[i].scriptWitness) except ValidationError as e: return return_err(e) return sig, "signing succeeded"
def make_wrapped_segwit_redeem_script(address_pubkey): return P2WPKHAddress.from_pubkey(address_pubkey).to_scriptPubKey()