Skip to content

Commit 7c78376

Browse files
csoreffgupniksatoshiotomakan
authored
Fix Reveal Operations for Seoul Protocol (#4557)
* Since the Seoul protocol, reveal operations require the presence of a boolean for whether or not the proof field is present. This is required when manually forging bytes. Added. * Fix TezosTests.swift * Fix TezosTests.swift * Update tests * Update tests * Fix TezosCompiler.CompileWithSignatures * Fix TezosCompiler.CompileWithSignatures * fix(tezos): Fix Tezos compile test * fix(tezos): Fix Tezos signing test * fix(tezos): Add mainnet test transaction --------- Co-authored-by: gupnik <[email protected]> Co-authored-by: Sergei Boiko <[email protected]>
1 parent 5668c67 commit 7c78376

File tree

8 files changed

+113
-55
lines changed

8 files changed

+113
-55
lines changed

android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/tezos/TestTezosSigner.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ class TestTezosTransactionSigner {
161161
assertTrue(AnySigner.supportsJSON(TEZOS.value()))
162162
assertEquals(
163163
result,
164-
"3756ef37b1be849e3114643f0aa5847cabf9a896d3bfe4dd51448de68e91da016b0081faa75f741ef614b0e35fcc8c90dfa3b0b95721f80992f001f44e810200429a986c8072a40a1f3a3e2ab5a5819bb1b2fb69993c5004837815b9dc55923e6c0081faa75f741ef614b0e35fcc8c90dfa3b0b95721f80993f001f44e810201000081faa75f741ef614b0e35fcc8c90dfa3b0b957210001b86398d5b9be737dca8e4106ea18d70e69b75e92f892fb283546a99152b8d7794b919c0fbf1c31de386069a60014491c0e7505adef5781cead1cfe6608030b"
164+
"3756ef37b1be849e3114643f0aa5847cabf9a896d3bfe4dd51448de68e91da016b0081faa75f741ef614b0e35fcc8c90dfa3b0b95721f80992f001f44e810200429a986c8072a40a1f3a3e2ab5a5819bb1b2fb69993c5004837815b9dc55923e006c0081faa75f741ef614b0e35fcc8c90dfa3b0b95721f80993f001f44e810201000081faa75f741ef614b0e35fcc8c90dfa3b0b957210097e828f0ec91b827995ef3ee81aac244f39f9961f2b1479626e228a14b80e860ae1dd3818648222c4b6aebcd3c57de8acebd1640f35c498e900e61876b7ecf0a"
165165
)
166166
}
167167
}

src/Tezos/Forging.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ Data forgeOperation(const Proto::Operation& operation) {
179179
append(forged, forgedGasLimit);
180180
append(forged, forgedStorageLimit);
181181
append(forged, forgedPublicKey);
182+
forged.push_back(0x00); // presence_of_proof = false (no proof for non-tz4)
182183
return forged;
183184
}
184185

swift/Tests/Blockchains/TezosTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ class TezosTests: XCTestCase {
176176
}
177177

178178
let output: TezosSigningOutput = AnySigner.sign(input: input, coin: .tezos)
179-
let expected = "3756ef37b1be849e3114643f0aa5847cabf9a896d3bfe4dd51448de68e91da016b0081faa75f741ef614b0e35fcc8c90dfa3b0b95721f80992f001f44e810200311f002e899cdd9a52d96cb8be18ea2bbab867c505da2b44ce10906f511cff956c0081faa75f741ef614b0e35fcc8c90dfa3b0b95721f80993f001f44e810201000081faa75f741ef614b0e35fcc8c90dfa3b0b95721000217034271b815e5f0c0a881342838ce49d7b48cdf507c72b1568c69a10db70c98774cdad1a74df760763e25f760ff13afcbbf3a1f2c833a0beeb9576a579c05"
179+
let expected = "3756ef37b1be849e3114643f0aa5847cabf9a896d3bfe4dd51448de68e91da016b0081faa75f741ef614b0e35fcc8c90dfa3b0b95721f80992f001f44e810200311f002e899cdd9a52d96cb8be18ea2bbab867c505da2b44ce10906f511cff95006c0081faa75f741ef614b0e35fcc8c90dfa3b0b95721f80993f001f44e810201000081faa75f741ef614b0e35fcc8c90dfa3b0b9572100ca20897ea1fd0251b3bb4f9acfe948f579f9fd4767a28e9a437f30a1193d8cc66d7b8084da70d480fd08873a47e39e4e6155879fe679f7dd2e4643be68c74205"
180180

181181
XCTAssertEqual(output.encoded.hexString, expected)
182182
}

tests/chains/Tezos/ForgingTests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ TEST(TezosTransaction, forgeReveal) {
226226
revealOperation.set_kind(TW::Tezos::Proto::Operation::REVEAL);
227227
revealOperation.set_allocated_reveal_operation_data(revealOperationData);
228228

229-
auto expected = "6b0081faa75f741ef614b0e35fcc8c90dfa3b0b95721f80992f001f44e810200429a986c8072a40a1f3a3e2ab5a5819bb1b2fb69993c5004837815b9dc55923e";
229+
auto expected = "6b0081faa75f741ef614b0e35fcc8c90dfa3b0b95721f80992f001f44e810200429a986c8072a40a1f3a3e2ab5a5819bb1b2fb69993c5004837815b9dc55923e00";
230230
auto serialized = forgeOperation(revealOperation);
231231

232232
ASSERT_EQ(hex(serialized), expected);

tests/chains/Tezos/OperationListTests.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ TEST(TezosOperationList, ForgeOperationList_RevealOnly) {
6363
revealOperation.set_allocated_reveal_operation_data(revealOperationData);
6464

6565
op_list.addOperation(revealOperation);
66-
auto expected = "3756ef37b1be849e3114643f0aa5847cabf9a896d3bfe4dd51448de68e91da016b0081faa75f741ef614b0e35fcc8c90dfa3b0b95721f80992f001f44e810200429a986c8072a40a1f3a3e2ab5a5819bb1b2fb69993c5004837815b9dc55923e";
66+
auto expected = "3756ef37b1be849e3114643f0aa5847cabf9a896d3bfe4dd51448de68e91da016b0081faa75f741ef614b0e35fcc8c90dfa3b0b95721f80992f001f44e810200429a986c8072a40a1f3a3e2ab5a5819bb1b2fb69993c5004837815b9dc55923e00";
6767
auto forged = op_list.forge(key);
6868

6969
ASSERT_EQ(hex(forged), expected);
@@ -147,7 +147,7 @@ TEST(TezosOperationList, ForgeOperationList_TransactionAndReveal) {
147147
op_list.addOperation(revealOperation);
148148
op_list.addOperation(transactionOperation);
149149

150-
auto expected = "3756ef37b1be849e3114643f0aa5847cabf9a896d3bfe4dd51448de68e91da016b003e47f837f0467b4acde406ed5842f35e2414b1a8f80992f001f44e810200603247bbf52501498293686da89ad8b2aca85f83b90903d4521dd2aba66054eb6c003e47f837f0467b4acde406ed5842f35e2414b1a8f80993f001f44e8102010000e42504da69a7c8d5baeaaeebe157a02db6b22ed800";
150+
auto expected = "3756ef37b1be849e3114643f0aa5847cabf9a896d3bfe4dd51448de68e91da016b003e47f837f0467b4acde406ed5842f35e2414b1a8f80992f001f44e810200603247bbf52501498293686da89ad8b2aca85f83b90903d4521dd2aba66054eb006c003e47f837f0467b4acde406ed5842f35e2414b1a8f80993f001f44e8102010000e42504da69a7c8d5baeaaeebe157a02db6b22ed800";
151151
auto forged = op_list.forge(key);
152152

153153
ASSERT_EQ(hex(forged), expected);
@@ -171,7 +171,7 @@ TEST(TezosOperationList, ForgeOperationList_RevealWithoutPublicKey) {
171171

172172
op_list.addOperation(revealOperation);
173173

174-
auto expected = "3756ef37b1be849e3114643f0aa5847cabf9a896d3bfe4dd51448de68e91da016b003e47f837f0467b4acde406ed5842f35e2414b1a8f80992f001f44e810200603247bbf52501498293686da89ad8b2aca85f83b90903d4521dd2aba66054eb";
174+
auto expected = "3756ef37b1be849e3114643f0aa5847cabf9a896d3bfe4dd51448de68e91da016b003e47f837f0467b4acde406ed5842f35e2414b1a8f80992f001f44e810200603247bbf52501498293686da89ad8b2aca85f83b90903d4521dd2aba66054eb00";
175175
auto forged = op_list.forge(key);
176176

177177
ASSERT_EQ(hex(forged), expected);

tests/chains/Tezos/SignerTests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ TEST(TezosSigner, SignOperationList) {
8080
auto key = PrivateKey(Data(decodedPrivateKey.begin() + 4, decodedPrivateKey.end()), TWCurveED25519);
8181

8282
std::string expectedForgedBytesToSign = hex(op_list.forge(key));
83-
std::string expectedSignature = "871693145f2dc72861ff6816e7ac3ce93c57611ac09a4c657a5a35270fa57153334c14cd8cae94ee228b6ef52f0e3f10948721e666318bc54b6c455404b11e03";
83+
std::string expectedSignature = "30c9471d2d270ad70c725b2869535b35efba1ddc17783359057a9b4ac97526ab8872c23dad2533e1eb608c9549956e10f59aeca0b4efb1fcbd4140dec4790b07";
8484
std::string expectedSignedBytes = expectedForgedBytesToSign + expectedSignature;
8585

8686
auto signedBytes = Signer().signOperationList(key, op_list);

tests/chains/Tezos/TWAnySignerTests.cpp

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// Copyright © 2017 Trust Wallet.
44

55
#include "HexCoding.h"
6+
#include "HDWallet.h"
67
#include "Tezos/BinaryCoding.h"
78
#include "proto/Tezos.pb.h"
89
#include "TestUtilities.h"
@@ -125,7 +126,46 @@ TEST(TWAnySignerTezos, Sign) {
125126
Proto::SigningOutput output;
126127
ANY_SIGN(input, TWCoinTypeTezos);
127128

128-
EXPECT_EQ(hex(output.encoded()), "3756ef37b1be849e3114643f0aa5847cabf9a896d3bfe4dd51448de68e91da016b0081faa75f741ef614b0e35fcc8c90dfa3b0b95721f80992f001f44e810200311f002e899cdd9a52d96cb8be18ea2bbab867c505da2b44ce10906f511cff956c0081faa75f741ef614b0e35fcc8c90dfa3b0b95721f80993f001f44e810201000081faa75f741ef614b0e35fcc8c90dfa3b0b95721000217034271b815e5f0c0a881342838ce49d7b48cdf507c72b1568c69a10db70c98774cdad1a74df760763e25f760ff13afcbbf3a1f2c833a0beeb9576a579c05");
129+
EXPECT_EQ(hex(output.encoded()), "3756ef37b1be849e3114643f0aa5847cabf9a896d3bfe4dd51448de68e91da016b0081faa75f741ef614b0e35fcc8c90dfa3b0b95721f80992f001f44e810200311f002e899cdd9a52d96cb8be18ea2bbab867c505da2b44ce10906f511cff95006c0081faa75f741ef614b0e35fcc8c90dfa3b0b95721f80993f001f44e810201000081faa75f741ef614b0e35fcc8c90dfa3b0b9572100ca20897ea1fd0251b3bb4f9acfe948f579f9fd4767a28e9a437f30a1193d8cc66d7b8084da70d480fd08873a47e39e4e6155879fe679f7dd2e4643be68c74205");
130+
}
131+
132+
TEST(TWAnySignerTezos, SignMainnet) {
133+
const auto wallet = HDWallet("hen betray system volcano excess wash viable joke elder boil goat cricket", "");
134+
const auto privateKey = wallet.getKey(TWCoinTypeTezos, TWDerivationDefault);
135+
const auto publicKey = privateKey.getPublicKey(TWPublicKeyTypeED25519);
136+
const auto address = wallet.deriveAddress(TWCoinTypeTezos, TWDerivationDefault);
137+
138+
Proto::SigningInput input;
139+
input.set_private_key(privateKey.bytes.data(), privateKey.bytes.size());
140+
auto& operations = *input.mutable_operation_list();
141+
operations.set_branch("BMWRrvZwJHmUhQEmGET9pshBJ2tTkqoQ8TF1vu78iaDTH98HL3H");
142+
143+
auto& reveal = *operations.add_operations();
144+
auto& revealData = *reveal.mutable_reveal_operation_data();
145+
revealData.set_public_key(publicKey.bytes.data(), publicKey.bytes.size());
146+
reveal.set_source(address);
147+
reveal.set_fee(1272);
148+
reveal.set_counter(187815742);
149+
reveal.set_gas_limit(10100);
150+
reveal.set_storage_limit(257);
151+
reveal.set_kind(Proto::Operation::REVEAL);
152+
153+
auto& transaction = *operations.add_operations();
154+
auto& txData = *transaction.mutable_transaction_operation_data();
155+
txData.set_amount(1);
156+
txData.set_destination("tz1XVJ8bZUXs7r5NV8dHvuiBhzECvLRLR3jW");
157+
transaction.set_source(address);
158+
transaction.set_fee(1272);
159+
transaction.set_counter(187815743);
160+
transaction.set_gas_limit(10100);
161+
transaction.set_storage_limit(257);
162+
transaction.set_kind(Proto::Operation::TRANSACTION);
163+
164+
Proto::SigningOutput output;
165+
ANY_SIGN(input, TWCoinTypeTezos);
166+
167+
// https://tzkt.io/oownY91ffLuq3ehdTmDy7rpvmFh2BYvmchKqzHcchoiEvcq4A25/187815742
168+
EXPECT_EQ(hex(output.encoded()), "ec7a7f24aa912d8a52c6823a759e04957049ad70ae14d2b90f9bf92d1f3b8a326b00e1adcf685eeadda7d2552cd7d83e9ca07bf2793bf809beaec759f44e81020044ec60cb2d32d9b3f9087a46f18a2ff1bb9b9a798d7738b62ede87d1e721a624006c00e1adcf685eeadda7d2552cd7d83e9ca07bf2793bf809bfaec759f44e810201000081faa75f741ef614b0e35fcc8c90dfa3b0b95721000fc4263d2ba5ad2b4e770c86f50323726eefce1df5fc7b84cbe59cbb0cc9f583c37b3ee3e765a41b3e06101d75951864a22aea4c9c95ed23aed89eab2073bf03");
129169
}
130170

131171
TEST(TWAnySignerTezos, SignJSON) {
@@ -134,7 +174,7 @@ TEST(TWAnySignerTezos, SignJSON) {
134174
auto result = WRAPS(TWAnySignerSignJSON(json.get(), key.get(), TWCoinTypeTezos));
135175

136176
ASSERT_TRUE(TWAnySignerSupportsJSON(TWCoinTypeTezos));
137-
assertStringsEqual(result, "3756ef37b1be849e3114643f0aa5847cabf9a896d3bfe4dd51448de68e91da016b0081faa75f741ef614b0e35fcc8c90dfa3b0b95721f80992f001f44e810200429a986c8072a40a1f3a3e2ab5a5819bb1b2fb69993c5004837815b9dc55923e6c0081faa75f741ef614b0e35fcc8c90dfa3b0b95721f80993f001f44e810201000081faa75f741ef614b0e35fcc8c90dfa3b0b957210001b86398d5b9be737dca8e4106ea18d70e69b75e92f892fb283546a99152b8d7794b919c0fbf1c31de386069a60014491c0e7505adef5781cead1cfe6608030b");
177+
assertStringsEqual(result, "3756ef37b1be849e3114643f0aa5847cabf9a896d3bfe4dd51448de68e91da016b0081faa75f741ef614b0e35fcc8c90dfa3b0b95721f80992f001f44e810200429a986c8072a40a1f3a3e2ab5a5819bb1b2fb69993c5004837815b9dc55923e006c0081faa75f741ef614b0e35fcc8c90dfa3b0b95721f80993f001f44e810201000081faa75f741ef614b0e35fcc8c90dfa3b0b957210097e828f0ec91b827995ef3ee81aac244f39f9961f2b1479626e228a14b80e860ae1dd3818648222c4b6aebcd3c57de8acebd1640f35c498e900e61876b7ecf0a");
138178
}
139179

140180
} // namespace TW::Tezos::tests

tests/chains/Tezos/TransactionCompilerTests.cpp

Lines changed: 63 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#include "Coin.h"
66
#include "HexCoding.h"
77
#include "PrivateKey.h"
8-
#include "PublicKey.h"
98
#include "TransactionCompiler.h"
109

1110
#include "proto/Tezos.pb.h"
@@ -18,20 +17,26 @@
1817
#include <gtest/gtest.h>
1918

2019
using namespace TW;
20+
using namespace TW::Tezos;
2121

2222
TEST(TezosCompiler, CompileWithSignatures) {
2323
const auto coin = TWCoinTypeTezos;
2424

25-
/// Step 1: Prepare transaction input (protobuf)
25+
// Test key
2626
auto privateKey =
2727
PrivateKey(parse_hex("2e8905819b8723fe2c1d161860e5ee1830318dbf49a83bd451cfb8440c28bd6f"));
28-
auto publicKey = privateKey.getPublicKey(::publicKeyType(coin));
29-
auto revealKey = parse_hex("311f002e899cdd9a52d96cb8be18ea2bbab867c505da2b44ce10906f511cff95");
3028

29+
// This is the forged (non-base58) reveal public key bytes used in older golden vectors.
30+
// It corresponds to edpk "edpku9ZF6UUAEo1AL3NWy1oxHLL6AfQcGYwA5hFKrEKVHMT3Xx889A"
31+
auto revealKey = parse_hex(
32+
"311f002e899cdd9a52d96cb8be18ea2bbab867c505da2b44ce10906f511cff95");
33+
34+
// -------- Step 1: Prepare transaction input (protobuf)
3135
TW::Tezos::Proto::SigningInput input;
3236
auto& operations = *input.mutable_operation_list();
3337
operations.set_branch("BL8euoCWqNCny9AR3AKjnpi38haYMxjei1ZqNHuXMn19JSQnoWp");
3438

39+
// REVEAL (must come before any other manager ops for the same source)
3540
auto& reveal = *operations.add_operations();
3641
auto& revealData = *reveal.mutable_reveal_operation_data();
3742
revealData.set_public_key(revealKey.data(), revealKey.size());
@@ -42,70 +47,82 @@ TEST(TezosCompiler, CompileWithSignatures) {
4247
reveal.set_storage_limit(257);
4348
reveal.set_kind(Tezos::Proto::Operation::REVEAL);
4449

45-
auto& transaction = *operations.add_operations();
46-
auto& txData = *transaction.mutable_transaction_operation_data();
50+
// TRANSACTION
51+
auto& tx = *operations.add_operations();
52+
auto& txData = *tx.mutable_transaction_operation_data();
4753
txData.set_amount(1);
4854
txData.set_destination("tz1XVJ8bZUXs7r5NV8dHvuiBhzECvLRLR3jW");
49-
transaction.set_source("tz1XVJ8bZUXs7r5NV8dHvuiBhzECvLRLR3jW");
50-
transaction.set_fee(1272);
51-
transaction.set_counter(30739);
52-
transaction.set_gas_limit(10100);
53-
transaction.set_storage_limit(257);
54-
transaction.set_kind(Tezos::Proto::Operation::TRANSACTION);
55+
tx.set_source("tz1XVJ8bZUXs7r5NV8dHvuiBhzECvLRLR3jW");
56+
tx.set_fee(1272);
57+
tx.set_counter(30739);
58+
tx.set_gas_limit(10100);
59+
tx.set_storage_limit(257);
60+
tx.set_kind(Tezos::Proto::Operation::TRANSACTION);
5561

5662
auto inputString = input.SerializeAsString();
5763
auto inputStrData = TW::Data(inputString.begin(), inputString.end());
5864

59-
/// Step 2: Obtain preimage hash
65+
// -------- Step 2: Obtain preimage hash
6066
const auto preImageHashData = TransactionCompiler::preImageHashes(coin, inputStrData);
6167

62-
auto preSigningOutput = TW::TxCompiler::Proto::PreSigningOutput();
63-
ASSERT_TRUE(
64-
preSigningOutput.ParseFromArray(preImageHashData.data(), (int)preImageHashData.size()));
68+
TW::TxCompiler::Proto::PreSigningOutput preSigningOutput;
69+
ASSERT_TRUE(preSigningOutput.ParseFromArray(preImageHashData.data(), (int)preImageHashData.size()));
6570
ASSERT_EQ(preSigningOutput.error(), Common::Proto::OK);
6671

6772
auto preImageHash = preSigningOutput.data_hash();
73+
// This expected hash should remain stable given the fixed inputs above.
6874
EXPECT_EQ(hex(preImageHash),
69-
"12e4f8b17ad3b316a5a56960db76c7d6505dbf2fff66106be75c8d6753daac0e");
75+
"2268aec5a2becbcd784a03060a4816e20396e6d96e7839ddaf2c3b980632e591");
76+
77+
// Produce a proper 64-byte Ed25519 signature (R||S) over the preimage hash.
78+
Data digest(preImageHash.begin(), preImageHash.end());
79+
auto signature = privateKey.sign(digest, TWCurveED25519);
80+
ASSERT_EQ(signature.size(), 64ul);
7081

71-
auto signature = parse_hex("0217034271b815e5f0c0a881342838ce49d7b48cdf507c72b1568c69a10db70c987"
72-
"74cdad1a74df760763e25f760ff13afcbbf3a1f2c833a0beeb9576a579c05");
82+
// -------- Step 3: Compile transaction using that signature
83+
auto compiledData = TransactionCompiler::compileWithSignatures(coin, inputStrData, {signature}, {});
84+
Proto::SigningOutput compiledOutput;
85+
ASSERT_TRUE(compiledOutput.ParseFromArray(compiledData.data(), (int)compiledData.size()));
86+
const auto compiledHex = hex(compiledOutput.encoded());
7387

74-
/// Step 3: Compile transaction info
75-
const auto tx =
76-
"3756ef37b1be849e3114643f0aa5847cabf9a896d3bfe4dd51448de68e91da016b0081faa75f741ef614b0e35f"
77-
"cc8c90dfa3b0b95721f80992f001f44e810200311f002e899cdd9a52d96cb8be18ea2bbab867c505da2b44ce10"
78-
"906f511cff956c0081faa75f741ef614b0e35fcc8c90dfa3b0b95721f80993f001f44e810201000081faa75f74"
79-
"1ef614b0e35fcc8c90dfa3b0b95721000217034271b815e5f0c0a881342838ce49d7b48cdf507c72b1568c69a1"
80-
"0db70c98774cdad1a74df760763e25f760ff13afcbbf3a1f2c833a0beeb9576a579c05";
81-
auto outputData =
82-
TransactionCompiler::compileWithSignatures(coin, inputStrData, {signature}, {});
88+
// As a cross-check, sign the same input with AnySigner and compare full bytes.
89+
TW::Tezos::Proto::SigningInput signingInput;
90+
ASSERT_TRUE(signingInput.ParseFromArray(inputStrData.data(), (int)inputStrData.size()));
91+
signingInput.set_private_key(privateKey.bytes.data(), privateKey.bytes.size());
8392

8493
{
85-
TW::Tezos::Proto::SigningOutput output;
86-
ASSERT_TRUE(output.ParseFromArray(outputData.data(), (int)outputData.size()));
94+
Proto::SigningOutput output;
95+
ANY_SIGN(signingInput, coin);
96+
const auto anySignHex = hex(output.encoded());
8797

88-
EXPECT_EQ(hex(output.encoded()), tx);
98+
ASSERT_EQ(compiledHex, anySignHex);
8999
}
90100

91-
{ // Double check: check if simple signature process gives the same result. Note that private
92-
// keys were not used anywhere up to this point.
93-
TW::Tezos::Proto::SigningInput signingInput;
94-
ASSERT_TRUE(signingInput.ParseFromArray(inputStrData.data(), (int)inputStrData.size()));
95-
signingInput.set_private_key(privateKey.bytes.data(), privateKey.bytes.size());
101+
// -------- Structural Seoul check:
102+
// Ensure the reveal has the new presence_of_proof byte (0x00) after the forged public key,
103+
// followed by the transaction op tag (0x6c).
104+
{
105+
// Reveal tag = 0x6b, Transaction tag = 0x6c
106+
ASSERT_NE(compiledHex.find("6b"), std::string::npos) << "Reveal tag not found";
96107

97-
TW::Tezos::Proto::SigningOutput output;
98-
ANY_SIGN(signingInput, coin);
108+
const std::string forgedPubKeyHex = hex(revealKey); // already raw forged key bytes
109+
auto pkPos = compiledHex.find(forgedPubKeyHex);
110+
ASSERT_NE(pkPos, std::string::npos) << "Forged public key not found in reveal";
111+
112+
// presence_of_proof = 0x00 must be immediately after the public key bytes
113+
ASSERT_EQ(compiledHex.substr(pkPos + forgedPubKeyHex.size(), 2), "00");
99114

100-
ASSERT_EQ(hex(output.encoded()), tx);
115+
// and the next op tag should be 0x6c (transaction)
116+
ASSERT_EQ(compiledHex.substr(pkPos + forgedPubKeyHex.size() + 2, 2), "6c");
101117
}
102118

103-
{ // Negative: inconsistent signatures & publicKeys
104-
outputData = TransactionCompiler::compileWithSignatures(
119+
// -------- Negative: inconsistent signatures & public keys count
120+
{
121+
auto compiledBad = TransactionCompiler::compileWithSignatures(
105122
coin, inputStrData, {signature, signature}, {});
106-
Tezos::Proto::SigningOutput output;
107-
ASSERT_TRUE(output.ParseFromArray(outputData.data(), (int)outputData.size()));
108-
EXPECT_EQ(output.encoded().size(), 0ul);
109-
EXPECT_EQ(output.error(), Common::Proto::Error_signatures_count);
123+
Proto::SigningOutput badOutput;
124+
ASSERT_TRUE(badOutput.ParseFromArray(compiledBad.data(), (int)compiledBad.size()));
125+
EXPECT_EQ(badOutput.encoded().size(), 0ul);
126+
EXPECT_EQ(badOutput.error(), Common::Proto::Error_signatures_count);
110127
}
111-
}
128+
}

0 commit comments

Comments
 (0)