def test_creation() -> None: psbt_str = "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAAAAAA=" psbt = Psbt.b64decode(psbt_str) assert psbt.b64encode() == psbt_str output_1 = TxOut( 149990000, ScriptPubKey("0014d85c2b71d0060b09c9886aeb815e50991dda124d")) output_2 = TxOut( 100000000, ScriptPubKey("001400aea9a2e5f0f876a588df5546e8742d1d87008f")) input_1 = TxIn( OutPoint( "75ddabb27b8845f5247975c8a5ba7c6f336c4570708ebe230caf6db5217ae858", 0), b"", 0xFFFFFFFF, ) input_2 = TxIn( OutPoint( "1dea7cd05979072a3578cab271c02244ea8a090bbb46aa680a65ecd027048d83", 1), b"", 0xFFFFFFFF, ) transaction = Tx(2, 0, [input_1, input_2], [output_1, output_2]) psbt_from_tx_ = Psbt.from_tx(transaction) assert psbt_from_tx_ == psbt
def test_p2ms_3() -> None: # tx_id 33ac2af1a6f894276713b59ed09ce1a20fed5b36d169f20a3fe831dc45564d57 # output n 0 keys: List[Command] = [ "036D568125A969DC78B963B494FA7ED5F20EE9C2F2FC2C57F86C5DF63089F2ED3A", "03FE4E6231D614D159741DF8371FA3B31AB93B3D28A7495CDAA0CD63A2097015C7", ] cmds: List[Command] = ["OP_1", *keys, "OP_2", "OP_CHECKMULTISIG"] script_pub_key = ScriptPubKey(serialize(cmds)) assert script_pub_key == ScriptPubKey.p2ms(1, keys) pub_keys = script_pub_key.addresses exp_pub_keys = [ "1Ng4YU2e2H3E86syX2qrsmD9opBHZ42vCF", "14XufxyGiY6ZBJsFYHJm6awdzpJdtsP1i3", ] for pub_key, key, exp_pub_key in zip(pub_keys, keys, exp_pub_keys): assert pub_key == b58.p2pkh(key) assert pub_key == exp_pub_key # tx 56214420a7c4dcc4832944298d169a75e93acf9721f00656b2ee0e4d194f9970 # input n 1 cmds_sig: List[Command] = [ "OP_0", "3045022100dba1e9b1c8477fd364edcc1f81845928202daf465a1e2d92904c13c88761cbd002200add6af863dfdb7efb95f334baec041e90811ae9d81624f9f87f33a56761f29401", ] script_sig = Script(serialize(cmds_sig)) script = script_sig + script_pub_key # parse(serialize(*)) is to enforce same string case convention assert script.asm == parse(serialize(cmds_sig + cmds))
def legacy(script_: Octets, tx: Tx, vin_i: int, hash_type: int) -> bytes: script_ = bytes_from_octets(script_) new_tx = deepcopy(tx) for txin in new_tx.vin: txin.script_sig = b"" # TODO: delete sig from script_ (even if non standard) new_tx.vin[vin_i].script_sig = script_ if hash_type & 0x1F == NONE: new_tx.vout = [] for i, txin in enumerate(new_tx.vin): if i != vin_i: txin.sequence = 0 if hash_type & 0x1F == SINGLE: # sig_hash single bug if vin_i >= len(new_tx.vout): return (256**31).to_bytes(32, byteorder="big", signed=False) new_tx.vout = new_tx.vout[:vin_i + 1] for txout in new_tx.vout[:-1]: txout.script_pub_key = ScriptPubKey(b"") txout.value = 0xFFFFFFFFFFFFFFFF for i, txin in enumerate(new_tx.vin): if i != vin_i: txin.sequence = 0 if hash_type & 0x80: new_tx.vin = [new_tx.vin[vin_i]] preimage = new_tx.serialize(include_witness=False, check_validity=False) preimage += hash_type.to_bytes(4, byteorder="little", signed=False) return hash256(preimage)
def from_dict(cls: Type["TxOut"], dict_: Mapping[str, Any], check_validity: bool = True) -> "TxOut": value = sats_from_btc(dict_["value"]) script_bin = dict_["scriptPubKey"] network = dict_.get("network", "mainnet") return cls(value, ScriptPubKey(script_bin, network), check_validity)
def parse(cls: Type["TxOut"], data: BinaryData, check_validity: bool = True) -> "TxOut": stream = bytesio_from_binarydata(data) value = int.from_bytes(stream.read(8), byteorder="little", signed=False) script = var_bytes.parse(stream) return cls(value, ScriptPubKey(script, "mainnet"), check_validity)
def __init__( self, value: int, script_pub_key: Union[ScriptPubKey, Octets], check_validity: bool = True, ) -> None: object.__setattr__(self, "value", value) if not isinstance(script_pub_key, ScriptPubKey): script_bytes = bytes_from_octets(script_pub_key) script_pub_key = ScriptPubKey(script_bytes) object.__setattr__(self, "script_pub_key", script_pub_key) if check_validity: self.assert_valid()
def parse( cls: Type["TxOut"], data: BinaryData, check_validity: bool = True, ) -> "TxOut": stream = bytesio_from_binarydata(data) value = int.from_bytes(stream.read(8), byteorder="little", signed=False) script = var_bytes.parse(stream) return cls( value, ScriptPubKey(script, "mainnet", check_validity=False ), # https://github.com/bitcoin/bitcoin/issues/320 check_validity, )
def test_unknown_network() -> None: with pytest.raises(BTClibValueError, match="unknown network: "): ScriptPubKey(b"", "no_network")