From be39f271b03fe05fde3862ecfdeebcf1b1fc4fed Mon Sep 17 00:00:00 2001
From: Andrew Kozlik <andrew.kozlik@gmail.com>
Date: Fri, 24 Apr 2020 16:09:41 +0200
Subject: [PATCH] core/sign_tx: Rework transaction footer writing.

---
 core/src/apps/wallet/sign_tx/bitcoin.py | 12 ++++----
 core/src/apps/wallet/sign_tx/decred.py  | 17 +++++------
 core/src/apps/wallet/sign_tx/zcash.py   | 39 +++++++++++++------------
 3 files changed, 36 insertions(+), 32 deletions(-)

diff --git a/core/src/apps/wallet/sign_tx/bitcoin.py b/core/src/apps/wallet/sign_tx/bitcoin.py
index 7df5cc946a..878a444983 100644
--- a/core/src/apps/wallet/sign_tx/bitcoin.py
+++ b/core/src/apps/wallet/sign_tx/bitcoin.py
@@ -187,7 +187,7 @@ class Bitcoin:
                 self.serialized_tx.append(0)
 
     async def step7_finish(self) -> None:
-        self.write_sign_tx_footer(self.serialized_tx)
+        self.write_tx_footer(self.serialized_tx, self.tx)
         await helpers.request_tx_finish(self.tx_req)
 
     async def process_input(self, i: int, txi: TxInputType) -> None:
@@ -433,9 +433,6 @@ class Bitcoin:
     def write_tx_input(self, w: writers.Writer, txi: TxInputType) -> None:
         writers.write_tx_input(w, txi)
 
-    def write_sign_tx_footer(self, w: writers.Writer) -> None:
-        writers.write_uint32(w, self.tx.lock_time)
-
     def write_tx_header(
         self, w: writers.Writer, tx: Union[SignTx, TransactionType], has_segwit: bool
     ) -> None:
@@ -444,10 +441,15 @@ class Bitcoin:
             writers.write_varint(w, 0x00)  # segwit witness marker
             writers.write_varint(w, 0x01)  # segwit witness flag
 
+    def write_tx_footer(
+        self, w: writers.Writer, tx: Union[SignTx, TransactionType]
+    ) -> None:
+        writers.write_uint32(w, tx.lock_time)
+
     async def write_prev_tx_footer(
         self, w: writers.Writer, tx: TransactionType, prev_hash: bytes
     ) -> None:
-        writers.write_uint32(w, tx.lock_time)
+        self.write_tx_footer(w, tx)
 
     def set_serialized_signature(self, index: int, signature: bytes) -> None:
         # Only one signature per TxRequest can be serialized.
diff --git a/core/src/apps/wallet/sign_tx/decred.py b/core/src/apps/wallet/sign_tx/decred.py
index dd412cd022..b39e2a7f95 100644
--- a/core/src/apps/wallet/sign_tx/decred.py
+++ b/core/src/apps/wallet/sign_tx/decred.py
@@ -20,7 +20,7 @@ DECRED_SERIALIZE_FULL = const(0 << 16)
 DECRED_SERIALIZE_NO_WITNESS = const(1 << 16)
 DECRED_SERIALIZE_WITNESS_SIGNING = const(3 << 16)
 
-DECRED_SIGHASHALL = const(1)
+DECRED_SIGHASH_ALL = const(1)
 
 if False:
     from typing import Union
@@ -78,6 +78,7 @@ class Decred(Bitcoin):
         self.hash143.add_output_count(self.tx)
         await super().step2_confirm_outputs()
         self.hash143.add_locktime_expiry(self.tx)
+        self.write_tx_footer(self.serialized_tx, self.tx)
 
     async def process_input(self, i: int, txi: TxInputType) -> None:
         await super().process_input(i, txi)
@@ -99,8 +100,6 @@ class Decred(Bitcoin):
         await super().confirm_output(i, txo, txo_bin)
 
     async def step4_serialize_inputs(self) -> None:
-        writers.write_uint32(self.serialized_tx, self.tx.lock_time)
-        writers.write_uint32(self.serialized_tx, self.tx.expiry)
         writers.write_varint(self.serialized_tx, self.tx.inputs_count)
 
         prefix_hash = self.hash143.get_prefix_hash()
@@ -145,7 +144,7 @@ class Decred(Bitcoin):
             )
 
             h_sign = self.create_hash_writer()
-            writers.write_uint32(h_sign, DECRED_SIGHASHALL)
+            writers.write_uint32(h_sign, DECRED_SIGHASH_ALL)
             writers.write_bytes_fixed(h_sign, prefix_hash, writers.TX_HASH_SIZE)
             writers.write_bytes_fixed(h_sign, witness_hash, writers.TX_HASH_SIZE)
 
@@ -167,6 +166,9 @@ class Decred(Bitcoin):
     async def step6_sign_segwit_inputs(self) -> None:
         pass
 
+    async def step7_finish(self) -> None:
+        await helpers.request_tx_finish(self.tx_req)
+
     def check_prevtx_output(self, txo_bin: TxOutputBinType) -> None:
         if (
             txo_bin.decred_script_version is not None
@@ -190,11 +192,8 @@ class Decred(Bitcoin):
 
         writers.write_uint32(w, version)
 
-    def write_sign_tx_footer(self, w: writers.Writer) -> None:
-        pass
-
-    async def write_prev_tx_footer(
-        self, w: writers.Writer, tx: TransactionType, prev_hash: bytes
+    def write_tx_footer(
+        self, w: writers.Writer, tx: Union[SignTx, TransactionType]
     ) -> None:
         writers.write_uint32(w, tx.lock_time)
         writers.write_uint32(w, tx.expiry)
diff --git a/core/src/apps/wallet/sign_tx/zcash.py b/core/src/apps/wallet/sign_tx/zcash.py
index 80eba73a20..1c8497f834 100644
--- a/core/src/apps/wallet/sign_tx/zcash.py
+++ b/core/src/apps/wallet/sign_tx/zcash.py
@@ -10,6 +10,7 @@ from trezor.utils import HashWriter, ensure
 
 from apps.common.coininfo import CoinInfo
 from apps.common.seed import Keychain
+from apps.wallet.sign_tx import helpers
 from apps.wallet.sign_tx.bitcoinlike import Bitcoinlike
 from apps.wallet.sign_tx.common import SigningError
 from apps.wallet.sign_tx.multisig import multisig_get_pubkeys
@@ -197,6 +198,26 @@ class Overwintered(Bitcoinlike):
                 "Unsupported version for overwintered transaction",
             )
 
+    async def step7_finish(self) -> None:
+        self.write_tx_footer(self.serialized_tx, self.tx)
+
+        if self.tx.version == 3:
+            write_uint32(self.serialized_tx, self.tx.expiry)  # expiryHeight
+            write_varint(self.serialized_tx, 0)  # nJoinSplit
+        elif self.tx.version == 4:
+            write_uint32(self.serialized_tx, self.tx.expiry)  # expiryHeight
+            write_uint64(self.serialized_tx, 0)  # valueBalance
+            write_varint(self.serialized_tx, 0)  # nShieldedSpend
+            write_varint(self.serialized_tx, 0)  # nShieldedOutput
+            write_varint(self.serialized_tx, 0)  # nJoinSplit
+        else:
+            raise SigningError(
+                FailureType.DataError,
+                "Unsupported version for overwintered transaction",
+            )
+
+        await helpers.request_tx_finish(self.tx_req)
+
     async def process_nonsegwit_input(self, i: int, txi: TxInputType) -> None:
         await self.process_bip143_input(i, txi)
 
@@ -209,21 +230,3 @@ class Overwintered(Bitcoinlike):
         # nVersion | fOverwintered
         write_uint32(w, tx.version | OVERWINTERED)
         write_uint32(w, tx.version_group_id)  # nVersionGroupId
-
-    def write_sign_tx_footer(self, w: Writer) -> None:
-        write_uint32(w, self.tx.lock_time)
-
-        if self.tx.version == 3:
-            write_uint32(w, self.tx.expiry)  # expiryHeight
-            write_varint(w, 0)  # nJoinSplit
-        elif self.tx.version == 4:
-            write_uint32(w, self.tx.expiry)  # expiryHeight
-            write_uint64(w, 0)  # valueBalance
-            write_varint(w, 0)  # nShieldedSpend
-            write_varint(w, 0)  # nShieldedOutput
-            write_varint(w, 0)  # nJoinSplit
-        else:
-            raise SigningError(
-                FailureType.DataError,
-                "Unsupported version for overwintered transaction",
-            )