Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions keepkeylib/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -1860,17 +1860,18 @@ def zcash_sign_pczt(self, address_n, actions, account=None,
total_amount=0, fee=0, branch_id=0x37519621,
header_digest=None, transparent_digest=None,
sapling_digest=None, orchard_digest=None,
shielded_pool=None, ironwood_digest=None,
orchard_flags=None, orchard_value_balance=None,
orchard_anchor=None, tx_version=None,
version_group_id=None, lock_time=None,
expiry_height=None, transparent_outputs=None,
transparent_inputs=None,
expected_seed_fingerprint=None,
return_transparent_signatures=False):
"""Sign a Zcash Orchard shielded transaction via PCZT protocol.
"""Sign a Zcash Orchard-family shielded transaction via PCZT protocol.

Streams transparent outputs, then transparent inputs, then Orchard
actions in the exact order requested by firmware 7.15. Orchard
Streams transparent outputs, then transparent inputs, then shielded
actions in the exact order requested by firmware 7.15. Shielded
signatures are compact: the response contains one signature for each
action whose explicit ``is_spend`` value is true, in action order.

Expand All @@ -1885,6 +1886,8 @@ def zcash_sign_pczt(self, address_n, actions, account=None,
transparent_digest: 32-byte transparent digest
sapling_digest: 32-byte sapling digest
orchard_digest: 32-byte orchard digest
shielded_pool: ZcashShieldedPool value (Orchard by default)
ironwood_digest: 32-byte Ironwood digest for transaction v6
orchard_flags: bundle flags byte (enables digest verification)
orchard_value_balance: signed i64 value balance
orchard_anchor: 32-byte anchor
Expand Down Expand Up @@ -1938,6 +1941,10 @@ def zcash_sign_pczt(self, address_n, actions, account=None,
kwargs['sapling_digest'] = sapling_digest
if orchard_digest is not None:
kwargs['orchard_digest'] = orchard_digest
if shielded_pool is not None:
kwargs['shielded_pool'] = shielded_pool
if ironwood_digest is not None:
kwargs['ironwood_digest'] = ironwood_digest
if orchard_flags is not None:
kwargs['orchard_flags'] = orchard_flags
if orchard_value_balance is not None:
Expand Down
96 changes: 69 additions & 27 deletions keepkeylib/messages_zcash_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 37 additions & 0 deletions tests/test_msg_zcash_sign_pczt.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,42 @@ def sign_kwargs(actions):
}


def ironwood_sign_kwargs(actions):
kwargs = sign_kwargs(actions)
kwargs.update({
'branch_id': 0x37A5165B,
'orchard_digest': b'\x14' * 32,
'shielded_pool': zcash_proto.ZCASH_SHIELDED_POOL_IRONWOOD,
'ironwood_digest': b'\x15' * 32,
'orchard_value_balance': 0,
'tx_version': 6,
'version_group_id': 0xD884B698,
})
return kwargs


class TestZcashSignPCZTClient(unittest.TestCase):
def test_ironwood_v6_metadata_is_forwarded_exactly(self):
actions = [action(0, False)]
client = ScriptedClient([
zcash_proto.ZcashPCZTActionAck(next_index=0),
zcash_proto.ZcashSignedPCZT(signatures=[]),
])

signed = client.zcash_sign_pczt(**ironwood_sign_kwargs(actions))

self.assertEqual(list(signed.signatures), [])
request = client.sent[0]
self.assertEqual(request.branch_id, 0x37A5165B)
self.assertEqual(request.tx_version, 6)
self.assertEqual(request.version_group_id, 0xD884B698)
self.assertEqual(
request.shielded_pool,
zcash_proto.ZCASH_SHIELDED_POOL_IRONWOOD,
)
self.assertEqual(request.orchard_digest, b'\x14' * 32)
self.assertEqual(request.ironwood_digest, b'\x15' * 32)

def test_all_dummy_shield_streams_outputs_inputs_and_no_orchard_sigs(self):
actions = [action(0, False), action(1, False)]
responses = [
Expand Down Expand Up @@ -125,6 +160,8 @@ def test_all_dummy_shield_streams_outputs_inputs_and_no_orchard_sigs(self):
self.assertEqual(request.tx_version, 5)
self.assertEqual(request.version_group_id, 0x26A7270A)
self.assertFalse(request.HasField('sapling_digest'))
self.assertFalse(request.HasField('shielded_pool'))
self.assertFalse(request.HasField('ironwood_digest'))
self.assertFalse(client.sent[3].is_spend)
self.assertFalse(client.sent[4].is_spend)
self.assertFalse(client.sent[2].HasField('sighash'))
Expand Down