예제 #1
0
    def test_eight_bytes(self):
        res = tx.VarInt(0xffffffffffffffff)
        self.assertEqual(res, b'\xff' + (b'\xff' * 8))
        self.assertIsInstance(res, tx.VarInt)

        res = tx.VarInt(0x0123456789abcdef)
        self.assertEqual(res, b'\xff' + b'\xef\xcd\xab\x89\x67\x45\x23\x01')

        res = tx.VarInt(0x234000000000)  # 6 bytes to test padding
        self.assertEqual(res, b'\xff' + b'\x00\x00\x00\x00\x40\x23\x00\x00')
예제 #2
0
def signed_refund_htlc_transaction(secret_hash: bytes,
                                   redeemer_pkh: bytes,
                                   timeout: int,
                                   funder_pkh: bytes,
                                   tx_id: str,
                                   index: int,
                                   prevout_value: int,
                                   address: str,
                                   privkey: bytes,
                                   fee: int = 0) -> tx.Tx:
    '''
    Builds an entire Refund HTLC spend from scratch.
    '''
    # build the unsigned version of the transaction
    t = spend_htlc_transaction(tx_id, index, prevout_value - fee, address,
                               timeout)

    # Prep the witness program
    s = build_htlc_script(secret_hash, redeemer_pkh, timeout, funder_pkh)
    serialized_script = script.serialize(s)
    script_len = len(serialized_script)
    prepended_script = tx.VarInt(script_len).to_bytes() + serialized_script

    # calculate sighash using the witness program
    sighash = t.sighash_all(index=index,
                            script=prepended_script,
                            prevout_value=rutils.i2le_padded(prevout_value, 8))

    # sign it and make the witness
    signature = crypto.sign_digest(sighash, privkey)
    witness = htlc_refund_witness(s, signature, crypto.priv_to_pub(privkey))

    # insert the witness into the tx
    return t.copy(tx_witnesses=[witness])
예제 #3
0
def _packetize_input_for_signing(tx_in: tx.TxIn,
                                 prevout_info: PrevoutInfo) -> List[bytes]:
    '''Turn an input into a set of packets for the last step of signing'''
    chunks = []
    if prevout_info['witness_script'] is None:
        raise ValueError('Packet for signing must have a script')
    script = cast(bytes, prevout_info['witness_script'])
    le_value = rutils.i2le_padded(prevout_info['value'], 8)

    script_len_bytes = tx.VarInt(len(script)).to_bytes()

    # the first packt is the outpoint and value
    chunks.append(b'\x02'  # 02 is ledger-speak for segwit input
                  + tx_in.outpoint.to_bytes() + le_value + script_len_bytes)

    # Chunk into 50-byte chunks
    chunks.extend([script[i:i + 50] for i in range(0, len(script), 50)])

    # append the sequence to the last one
    chunks[-1] = chunks[-1] + tx_in.sequence

    return [_transaction_continue_packet(chunk) for chunk in chunks]
예제 #4
0
def _packetize_vout(tx_outs: Tuple[tx.TxOut]) -> List[bytes]:
    '''Converts the output vector into adpu packets'''
    # first get the whole length-prefixed vector
    data_to_be_chunked = bytearray()
    data_to_be_chunked.extend(tx.VarInt(len(tx_outs)).to_bytes())
    for tx_out in tx_outs:
        data_to_be_chunked.extend(tx_out.to_bytes())

    # chunk it into 50 byte chunks
    chunks = [
        data_to_be_chunked[i:i + 50]  # chunk the data
        for i in range(0, len(data_to_be_chunked), 50)
    ]

    # make continue packets for all but the last one
    packets = []
    packets.extend([_output_continue_packet(chunk) for chunk in chunks[:-1]])

    # the last one is a final packet
    packets.append(_output_final_packet(chunks[-1]))

    # return all the adpu packets
    return packets
예제 #5
0
def _packetize_version_and_vin_length(t: tx.Tx) -> bytes:
    '''The first packet sent to UNTRUSTED HASH TRANSACTION INPUT START'''
    # will break on bullshit like non-compact VarInts
    chunk = t.version + tx.VarInt(len(t.tx_ins)).to_bytes()
    return _transaction_start_packet(chunk)
예제 #6
0
def length_prepend(byte_string):
    '''
    bytes -> bytes
    '''
    length = tx.VarInt(len(byte_string))
    return length.to_bytes() + byte_string
예제 #7
0
 def test_four_bytes(self):
     res = tx.VarInt(0xffffffff)
     self.assertEqual(res, b'\xfe' + (b'\xff' * 4))
     self.assertIsInstance(res, tx.VarInt)
예제 #8
0
 def test_two_bytes(self):
     res = tx.VarInt(0xffff)
     self.assertEqual(res, b'\xfd' + (b'\xff' * 2))
     self.assertIsInstance(res, tx.VarInt)
예제 #9
0
 def test_one_byte_boundary(self):
     res = tx.VarInt(0xff)
     self.assertEqual(res, b'\xfd' + b'\xff\x00')
     self.assertIsInstance(res, tx.VarInt)
예제 #10
0
 def test_one_byte(self):
     res = tx.VarInt(0xfb)
     self.assertEqual(res, b'\xfb')
     self.assertIsInstance(res, tx.VarInt)
예제 #11
0
 def test_copy(self):
     res = tx.VarInt(0xffffffffffffffff)
     copy = res.copy()
     self.assertEqual(res, copy)
     self.assertIsNot(res, copy)
예제 #12
0
    def test_too_high(self):
        with self.assertRaises(ValueError) as context:
            tx.VarInt(2**64 + 1)

        self.assertIn('VarInt cannot be greater than (2 ** 64) - 1.',
                      str(context.exception))
예제 #13
0
    def test_negative(self):
        with self.assertRaises(ValueError) as context:
            tx.VarInt(-5)

        self.assertIn('VarInt cannot be less than 0.', str(context.exception))