def from_bytes(VarInt, byte_string): ''' byte-like -> VarInt accepts arbitrary length input, gets a VarInt off the front ''' num = byte_string if num[0] <= 0xfc: num = num[0:1] non_compact = False elif num[0] == 0xfd: num = num[1:3] non_compact = (num[-1:] == b'\x00') elif num[0] == 0xfe: num = num[1:5] non_compact = (num[-2:] == b'\x00\x00') elif num[0] == 0xff: num = num[1:9] non_compact = (num[-4:] == b'\x00\x00\x00\x00') if len(num) not in [1, 2, 4, 8]: raise ValueError('Malformed VarInt. Got: {}'.format( byte_string.hex())) if (non_compact and ('overwinter' in riemann.get_current_network_name() or 'sapling' in riemann.get_current_network_name())): raise ValueError('VarInt must be compact. Got: {}'.format( byte_string.hex())) ret = VarInt(utils.le2i(num), length=len(num) + 1 if non_compact else 0) return ret
def hash256(msg_bytes): ''' byte-like -> bytes ''' if 'decred' in riemann.get_current_network_name(): return blake256(blake256(msg_bytes)) return hashlib.sha256(hashlib.sha256(msg_bytes).digest()).digest()
def make_pkh_output_script(pubkey, witness=False): ''' bytearray -> bytearray ''' if witness and not riemann.network.SEGWIT: raise ValueError( 'Network {} does not support witness scripts.' .format(riemann.get_current_network_name())) output_script = bytearray() if type(pubkey) is not bytearray and type(pubkey) is not bytes: raise ValueError('Unknown pubkey format. ' 'Expected bytes. Got: {}'.format(type(pubkey))) pubkey_hash = utils.hash160(pubkey) if witness: output_script.extend(riemann.network.P2WPKH_PREFIX) output_script.extend(pubkey_hash) else: output_script.extend(b'\x76\xa9\x14') # OP_DUP OP_HASH160 PUSH14 output_script.extend(pubkey_hash) output_script.extend(b'\x88\xac') # OP_EQUALVERIFY OP_CHECKSIG return output_script
def make_pkh_output_script(pubkey: bytes, witness: bool = False) -> bytes: ''' Makes a P2PKH or P2WPKH script pubkey from a raw public key. Does not support Compatibility p2wpkh-via-p2sh output scripts. Args: pubkey: The 33- or 65-byte public key. witness: Pass True to make a P2WSH script pubkey. Returns: The script pubkey containing the hash of the pubkey. ''' if witness and not riemann.network.SEGWIT: raise ValueError('Network {} does not support witness scripts.'.format( riemann.get_current_network_name())) output_script = bytearray() if type(pubkey) is not bytearray and type(pubkey) is not bytes: raise ValueError('Unknown pubkey format. ' 'Expected bytes. Got: {}'.format(type(pubkey))) pubkey_hash = utils.hash160(pubkey) if witness: output_script.extend(riemann.network.P2WPKH_PREFIX) output_script.extend(pubkey_hash) else: output_script.extend(b'\x76\xa9\x14') # OP_DUP OP_HASH160 PUSH14 output_script.extend(pubkey_hash) output_script.extend(b'\x88\xac') # OP_EQUALVERIFY OP_CHECKSIG return bytes(output_script)
def encode(data: bytes) -> str: '''Convert bytes to bech32''' if riemann.network.BECH32_HRP is None: raise ValueError( 'Network ({}) does not support bech32 encoding.'.format( riemann.get_current_network_name())) return segwit_encode(riemann.network.BECH32_HRP, data[0], data[2:])
def _make_output( # noqa: F811 value, output_script, version=None): '''Instantiates a TxOut from value and output script''' if 'decred' in riemann.get_current_network_name(): return decred.DecredTxOut(value=value, version=cast(int, version), output_script=output_script) return tx.TxOut(value=value, output_script=output_script)
def hash160(msg_bytes: bytes) -> bytes: '''rmd160 of sha256 of message''' h = hashlib.new('ripemd160') if 'decred' in riemann.get_current_network_name(): h.update(blake256(msg_bytes)) return h.digest() h.update(sha256(msg_bytes)) return h.digest()
def make_witness_input(outpoint, sequence): # noqa: F811 '''Make a witness input''' if 'decred' in riemann.get_current_network_name(): return decred.DecredTxIn(outpoint=outpoint, sequence=utils.i2le_padded(sequence, 4)) return tx.TxIn(outpoint=outpoint, stack_script=b'', redeem_script=b'', sequence=utils.i2le_padded(sequence, 4))
def make_tx(version, tx_ins, tx_outs, lock_time, expiry=None, value_balance=None, tx_shielded_spends=None, tx_shielded_outputs=None, tx_witnesses=None, tx_joinsplits=None, joinsplit_pubkey=None, joinsplit_sig=None, binding_sig=None): ''' int, list(TxIn), list(TxOut), int, list(InputWitness) -> Tx ''' n = riemann.get_current_network_name() if 'decred' in n: return tx.DecredTx( version=utils.i2le_padded(version, 4), tx_ins=tx_ins, tx_outs=tx_outs, lock_time=utils.i2le_padded(lock_time, 4), expiry=utils.i2le_padded(expiry, 4), tx_witnesses=[tx_witnesses]) if 'sprout' in n and tx_joinsplits is not None: return tx.SproutTx( version=version, tx_ins=tx_ins, tx_outs=tx_outs, lock_time=utils.i2le_padded(lock_time, 4), tx_joinsplits=tx_joinsplits if tx_joinsplits is not None else [], joinsplit_pubkey=joinsplit_pubkey, joinsplit_sig=joinsplit_sig) if 'overwinter' in n: return tx.OverwinterTx( tx_ins=tx_ins, tx_outs=tx_outs, lock_time=utils.i2le_padded(lock_time, 4), expiry_height=utils.i2le_padded(expiry, 4), tx_joinsplits=tx_joinsplits if tx_joinsplits is not None else [], joinsplit_pubkey=joinsplit_pubkey, joinsplit_sig=joinsplit_sig) if 'sapling' in n: return tx.SaplingTx( tx_ins=tx_ins, tx_outs=tx_outs, lock_time=utils.i2le_padded(lock_time, 4), expiry_height=utils.i2le_padded(expiry, 4), value_balance=utils.i2le_padded[value_balance], tx_shielded_spends=(tx_shielded_spends if tx_shielded_spends is not None else []), tx_shielded_outputs=(tx_shielded_outputs if tx_shielded_outputs is not None else []), tx_joinsplits=tx_joinsplits if tx_joinsplits is not None else [], joinsplit_pubkey=joinsplit_pubkey, joinsplit_sig=joinsplit_sig, binding_sig=binding_sig) flag = riemann.network.SEGWIT_TX_FLAG \ if tx_witnesses is not None else None return tx.Tx(version=utils.i2le_padded(version, 4), flag=flag, tx_ins=tx_ins, tx_outs=tx_outs, tx_witnesses=tx_witnesses, lock_time=utils.i2le_padded(lock_time, 4))
def _make_output(value, output_script, version=None): ''' byte-like, byte-like -> TxOut ''' if 'decred' in riemann.get_current_network_name(): return tx.DecredTxOut(value=value, version=version, output_script=output_script) return tx.TxOut(value=value, output_script=output_script)
def make_outpoint(tx_id_le, index, tree=None): ''' byte-like, int, int -> Outpoint ''' if 'decred' in riemann.get_current_network_name(): return tx.DecredOutpoint(tx_id=tx_id_le, index=utils.i2le_padded(index, 4), tree=utils.i2le_padded(tree, 1)) return tx.Outpoint(tx_id=tx_id_le, index=utils.i2le_padded(index, 4))
def make_outpoint(tx_id_le, index, tree=None): # noqa: F811 ''' byte-like, int, int -> Outpoint ''' if 'decred' in riemann.get_current_network_name(): tree_bytes = b'\x00' if tree is None else utils.i2le_padded(tree, 1) return decred.DecredOutpoint(tx_id=tx_id_le, index=utils.i2le_padded(index, 4), tree=tree_bytes) return tx.Outpoint(tx_id=tx_id_le, index=utils.i2le_padded(index, 4))
def make_legacy_input( # noqa: F811 outpoint, stack_script, redeem_script, sequence): '''Make a legacy input''' if 'decred' in riemann.get_current_network_name(): return decred.DecredTxIn(outpoint=outpoint, sequence=utils.i2le_padded(sequence, 4)) return tx.TxIn(outpoint=outpoint, stack_script=stack_script, redeem_script=redeem_script, sequence=utils.i2le_padded(sequence, 4))
def make_sh_output_script(script_string, witness=False): ''' str -> bytearray ''' if witness and not riemann.network.SEGWIT: raise ValueError('Network {} does not support witness scripts.'.format( riemann.get_current_network_name())) script_bytes = serialization.serialize(script_string) return make_sh_script_pubkey(script_bytes=script_bytes, witness=witness)
def make_witness_input(outpoint, sequence): ''' Outpoint, int -> TxIn ''' if 'decred' in riemann.get_current_network_name(): return tx.DecredTxIn(outpoint=outpoint, sequence=sequence) return tx.TxIn(outpoint=outpoint, stack_script=b'', redeem_script=b'', sequence=sequence)
def hash160(msg_bytes): ''' byte-like -> bytes ''' h = hashlib.new('ripemd160') if 'decred' in riemann.get_current_network_name(): h.update(blake256(msg_bytes)) return h.digest() h.update(sha256(msg_bytes)) return h.digest()
def make_legacy_input(outpoint, stack_script, redeem_script, sequence): ''' Outpoint, byte-like, byte-like, int -> TxIn ''' if 'decred' in riemann.get_current_network_name(): return tx.DecredTxIn(outpoint=outpoint, sequence=utils.i2le_padded(sequence, 4)) return tx.TxIn(outpoint=outpoint, stack_script=stack_script, redeem_script=redeem_script, sequence=utils.i2le_padded(sequence, 4))
def make_witness_input_and_witness(outpoint, sequence, stack=None, **kwargs): ''' Outpoint, int, list(bytearray) -> (Input, InputWitness) ''' if 'decred' in riemann.get_current_network_name(): return (make_witness_input(outpoint, sequence), make_decred_witness(value=kwargs['value'], height=kwargs['height'], index=kwargs['index'], stack_script=kwargs['stack_script'], redeem_script=kwargs['redeem_script'])) return (make_witness_input(outpoint, sequence), make_witness(stack))
def decode(bech): if riemann.network.BECH32_HRP is None: raise ValueError( 'Network ({}) does not support bech32 encoding.'.format( riemann.get_current_network_name())) (version_prefix, hash_int_array) = \ segwit_decode(riemann.network.BECH32_HRP, bech) ret = bytearray() ret.extend([version_prefix]) ret.extend([len(hash_int_array)]) ret.extend(hash_int_array) return bytes(ret)
def encode(data: bytes) -> str: '''Convert bytes to cashaddr-bech32''' if riemann.network.CASHADDR_PREFIX is None: raise ValueError('Network {} does not support cashaddresses.'.format( riemann.get_current_network_name())) data = convertbits(data, 8, 5) checksum = calculate_checksum(riemann.network.CASHADDR_PREFIX, data) payload = b32encode(data + checksum) form = '{prefix}:{payload}' return form.format(prefix=riemann.network.CASHADDR_PREFIX, payload=payload)
def guess_version(redeem_script): ''' str -> int Bitcoin uses tx version 2 for nSequence signaling. Zcash uses tx version 2 for joinsplits. We want to signal nSequence if we're using OP_CSV. Unless we're in zcash. ''' if 'zcash' in riemann.get_current_network_name(): return 1 try: script_array = redeem_script.split() script_array.index('OP_CHECKSEQUENCEVERIFY') return 2 except ValueError: return 1 # Enable lock_time, disable RBF
def make_sh_output_script(script_string: str, witness: bool = False) -> bytes: ''' Make a P2SH or P2WSH script pubkey from a human-readable script. Does not support Compatibility p2wsh-via-p2sh output scripts. Args: script_string: The human-readable redeem script or witness script. witness: Pass True to make a P2WSH script pubkey. Returns: The script pubkey containing the hash of the serialized script. ''' if witness and not riemann.network.SEGWIT: raise ValueError('Network {} does not support witness scripts.'.format( riemann.get_current_network_name())) script_bytes = serialization.serialize(script_string) return make_sh_script_pubkey(script_bytes=script_bytes, witness=witness)
def _make_output( # noqa: F811 value, output_script, version=None): ''' Instantiates a TxOut from value and output script. Args: value: The 8-byte LE-encoded integer value of the output. output_script: The non-length-prepended output script. version: Only in Decred transactions, the output version. Returns: The TxOut object. A DecredTxOut if version was passed in. ''' if 'decred' in riemann.get_current_network_name(): return decred.DecredTxOut(value=value, version=cast(int, version), output_script=output_script) return tx.TxOut(value=value, output_script=output_script)
def make_witness_input(outpoint, sequence): # noqa: F811 ''' Make a Segwit input. This is clearly superior to `make_legacy_input` and you should use witness always. Args: outpoint: The Outpoint object sequence: The 4-byte LE-encoded sequence number Returns: A Segwit TxIn object. ''' if 'decred' in riemann.get_current_network_name(): return decred.DecredTxIn(outpoint=outpoint, sequence=utils.i2le_padded(sequence, 4)) return tx.TxIn(outpoint=outpoint, stack_script=b'', redeem_script=b'', sequence=utils.i2le_padded(sequence, 4))
def decode(data: str) -> bytes: '''Convert cashaddr-bech32 to bytes''' if riemann.network.CASHADDR_PREFIX is None: raise ValueError('Network {} does not support cashaddresses.'.format( riemann.get_current_network_name())) if data.find(riemann.network.CASHADDR_PREFIX) != 0: raise ValueError('Malformed cashaddr. Cannot locate prefix: {}'.format( riemann.network.CASHADDR_PREFIX)) # the data is everything after the colon prefix, data = data.split(':') decoded = b32decode(data) if not verify_checksum(prefix, decoded): raise ValueError('Bad cash address checksum') converted = convertbits(decoded, 5, 8) return bytes(converted[:-6]) # remove the checksum from the end
def make_outpoint(tx_id_le, index, tree=None): # noqa: F811 ''' Instantiate an Outpoint object from a transaction id and an index. Args: tx_id_le: The 32-byte LE hash of the transaction that created the prevout being referenced. index: The index of the TxOut that created the prevout in its transaction's output vector tree: Only in Decred transactions. Specifies the commitment tree. Returns: An Outpoint object. If network is set to Decred, a DecredOutpoint ''' if 'decred' in riemann.get_current_network_name(): tree_bytes = b'\x00' if tree is None else utils.i2le_padded(tree, 1) return decred.DecredOutpoint(tx_id=tx_id_le, index=utils.i2le_padded(index, 4), tree=tree_bytes) return tx.Outpoint(tx_id=tx_id_le, index=utils.i2le_padded(index, 4))
def make_legacy_input( # noqa: F811 outpoint, stack_script, redeem_script, sequence): ''' Make a legacy input. This supports creating Compatibility inputs by passing the witness program to `redeem_script` while passing an empty bytestring for `stack_script`. Args: outpoint: The Outpoint object stack_script: A serialized Script program that sets the initial stack redeem_script: A serialized Script program that is run on the stack sequence: The 4-byte LE-encoded sequence number Returns: A Legacy TxIn object. ''' if 'decred' in riemann.get_current_network_name(): return decred.DecredTxIn(outpoint=outpoint, sequence=utils.i2le_padded(sequence, 4)) return tx.TxIn(outpoint=outpoint, stack_script=stack_script, redeem_script=redeem_script, sequence=utils.i2le_padded(sequence, 4))
def make_sh_output_script(script_string, witness=False): ''' str -> bytearray ''' if witness and not riemann.network.SEGWIT: raise ValueError('Network {} does not support witness scripts.'.format( riemann.get_current_network_name())) output_script = bytearray() script_bytes = serialization.serialize(script_string) if witness: script_hash = utils.sha256(script_bytes) output_script.extend(riemann.network.P2WSH_PREFIX) output_script.extend(script_hash) else: script_hash = utils.hash160(script_bytes) output_script.extend(b'\xa9') # OP_HASH160 output_script.extend(script_hash) output_script.extend(b'\x87') # OP_EQUAL return output_script
def make_tx(version, tx_ins, tx_outs, lock_time, expiry=None, tx_witnesses=None): ''' int, list(TxIn), list(TxOut), int, list(InputWitness) -> Tx ''' if 'decred' in riemann.get_current_network_name(): return tx.DecredTx(version=version, tx_ins=tx_ins, tx_outs=tx_outs, lock_time=lock_time, expiry=expiry, tx_witnesses=tx_witnesses) flag = riemann.network.SEGWIT_TX_FLAG \ if tx_witnesses is not None else None return tx.Tx(version=utils.i2le_padded(version, 4), flag=flag, tx_ins=tx_ins, tx_outs=tx_outs, tx_witnesses=tx_witnesses, lock_time=utils.i2le_padded(lock_time, 4))
def __init__(self): if 'decred' not in riemann.get_current_network_name(): raise ValueError('Decred classes not supported by network {}. ' 'How did you get here?'.format( riemann.get_current_network_name())) super().__init__()