diff --git a/.changelog/unreleased/improvements/1093-signable-txs.md b/.changelog/unreleased/improvements/1093-signable-txs.md
new file mode 100644
index 0000000000..e1e244bd0f
--- /dev/null
+++ b/.changelog/unreleased/improvements/1093-signable-txs.md
@@ -0,0 +1,2 @@
+- Make Namada transactions signable on hardware constrained wallets by making
+ them smaller. ([#1093](https://github.com/anoma/namada/pull/1093))
\ No newline at end of file
diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
index 54e19e6a25..ef10550d67 100644
--- a/.github/workflows/build-and-test.yml
+++ b/.github/workflows/build-and-test.yml
@@ -4,13 +4,11 @@ on:
push:
branches:
- main
- - maint-*
- "!eth-bridge-integration"
# Run in PRs with conflicts (https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request)
pull_request_target:
branches:
- main
- - maint-*
- "!eth-bridge-integration"
types: [opened, synchronize, reopened]
workflow_dispatch:
diff --git a/Cargo.lock b/Cargo.lock
index 3a6e374f43..0c80cf7619 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -19,10 +19,11 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aead"
-version = "0.4.3"
+version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877"
+checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
dependencies = [
+ "crypto-common",
"generic-array 0.14.7",
]
@@ -33,7 +34,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
dependencies = [
"cfg-if 1.0.0",
- "cipher",
+ "cipher 0.3.0",
"cpufeatures",
"opaque-debug 0.3.0",
]
@@ -587,25 +588,36 @@ dependencies = [
"blake2s_simd 0.5.11",
"byteorder",
"crossbeam-channel 0.5.8",
- "ff",
- "group",
+ "ff 0.11.1",
+ "group 0.11.0",
"lazy_static",
"log 0.4.17",
"num_cpus",
- "pairing",
+ "pairing 0.21.0",
"rand_core 0.6.4",
"rayon",
"subtle 2.4.1",
]
[[package]]
-name = "bigint"
-version = "4.4.3"
+name = "bellman"
+version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0e8c8a600052b52482eff2cf4d810e462fdff1f656ac1ecb6232132a1ed7def"
+checksum = "a4dd656ef4fdf7debb6d87d4dd92642fcbcdb78cbf6600c13e25c87e4d1a3807"
dependencies = [
+ "bitvec 1.0.1",
+ "blake2s_simd 1.0.1",
"byteorder",
- "crunchy 0.1.6",
+ "crossbeam-channel 0.5.8",
+ "ff 0.12.1",
+ "group 0.12.1",
+ "lazy_static",
+ "log 0.4.17",
+ "num_cpus",
+ "pairing 0.22.0",
+ "rand_core 0.6.4",
+ "rayon",
+ "subtle 2.4.1",
]
[[package]]
@@ -684,7 +696,7 @@ checksum = "0694ea59225b0c5f3cb405ff3f670e4828358ed26aec49dc352f730f0cb1a8a3"
dependencies = [
"bech32 0.9.1",
"bitcoin_hashes",
- "secp256k1 0.24.3",
+ "secp256k1",
"serde 1.0.163",
]
@@ -746,17 +758,6 @@ dependencies = [
"cty",
]
-[[package]]
-name = "blake2b_simd"
-version = "0.5.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587"
-dependencies = [
- "arrayref",
- "arrayvec 0.5.2",
- "constant_time_eq 0.1.5",
-]
-
[[package]]
name = "blake2b_simd"
version = "1.0.1"
@@ -841,7 +842,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cb03d1bed155d89dce0f845b7899b18a9a163e148fd004e1c28421a783e2d8e"
dependencies = [
"block-padding 0.2.1",
- "cipher",
+ "cipher 0.3.0",
]
[[package]]
@@ -880,9 +881,22 @@ version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a829c821999c06be34de314eaeb7dd1b42be38661178bc26ad47a4eacebdb0f9"
dependencies = [
- "ff",
- "group",
- "pairing",
+ "ff 0.11.1",
+ "group 0.11.0",
+ "pairing 0.21.0",
+ "rand_core 0.6.4",
+ "subtle 2.4.1",
+]
+
+[[package]]
+name = "bls12_381"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3c196a77437e7cc2fb515ce413a6401291578b5afc8ecb29a3c7ab957f05941"
+dependencies = [
+ "ff 0.12.1",
+ "group 0.12.1",
+ "pairing 0.22.0",
"rand_core 0.6.4",
"subtle 2.4.1",
]
@@ -1108,20 +1122,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c80e5460aa66fe3b91d40bcbdab953a597b60053e34d684ac6903f863b680a6"
dependencies = [
"cfg-if 1.0.0",
- "cipher",
+ "cipher 0.3.0",
"cpufeatures",
- "zeroize",
]
[[package]]
-name = "chacha20poly1305"
+name = "chacha20"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a18446b09be63d457bbec447509e85f662f32952b035ce892290396bc0b0cff5"
+checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818"
+dependencies = [
+ "cfg-if 1.0.0",
+ "cipher 0.4.4",
+ "cpufeatures",
+]
+
+[[package]]
+name = "chacha20poly1305"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
dependencies = [
"aead",
- "chacha20",
- "cipher",
+ "chacha20 0.9.1",
+ "cipher 0.4.4",
"poly1305",
"zeroize",
]
@@ -1153,6 +1177,17 @@ dependencies = [
"generic-array 0.14.7",
]
+[[package]]
+name = "cipher"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
+dependencies = [
+ "crypto-common",
+ "inout",
+ "zeroize",
+]
+
[[package]]
name = "circular-queue"
version = "0.2.6"
@@ -1471,12 +1506,6 @@ dependencies = [
"cfg-if 1.0.0",
]
-[[package]]
-name = "crunchy"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda"
-
[[package]]
name = "crunchy"
version = "0.2.2"
@@ -1535,21 +1564,6 @@ dependencies = [
"subtle 2.4.1",
]
-[[package]]
-name = "crypto_api"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f855e87e75a4799e18b8529178adcde6fd4f97c1449ff4821e747ff728bb102"
-
-[[package]]
-name = "crypto_api_chachapoly"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d930b6a026ce9d358a17f9c9046c55d90b14bb847f36b6ebb6b19365d4feffb8"
-dependencies = [
- "crypto_api",
-]
-
[[package]]
name = "ct-codecs"
version = "1.1.1"
@@ -1901,9 +1915,9 @@ dependencies = [
"base16ct",
"crypto-bigint",
"der",
- "ff",
+ "ff 0.11.1",
"generic-array 0.14.7",
- "group",
+ "group 0.11.0",
"rand_core 0.6.4",
"sec1",
"subtle 2.4.1",
@@ -1960,15 +1974,6 @@ dependencies = [
"syn 2.0.16",
]
-[[package]]
-name = "equihash"
-version = "0.1.0"
-source = "git+https://github.com/zcash/librustzcash?rev=2425a08#2425a0869098e3b0588ccd73c42716bcf418612c"
-dependencies = [
- "blake2b_simd 1.0.1",
- "byteorder",
-]
-
[[package]]
name = "erased-serde"
version = "0.3.25"
@@ -2084,7 +2089,7 @@ dependencies = [
"ark-std",
"bincode",
"blake2",
- "blake2b_simd 1.0.1",
+ "blake2b_simd",
"borsh",
"digest 0.10.6",
"ed25519-dalek",
@@ -2130,6 +2135,17 @@ dependencies = [
"subtle 2.4.1",
]
+[[package]]
+name = "ff"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160"
+dependencies = [
+ "bitvec 1.0.1",
+ "rand_core 0.6.4",
+ "subtle 2.4.1",
+]
+
[[package]]
name = "file-lock"
version = "2.1.9"
@@ -2238,7 +2254,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd910db5f9ca4dc3116f8c46367825807aa2b942f72565f16b4be0b208a00a9e"
dependencies = [
"block-modes",
- "cipher",
+ "cipher 0.3.0",
"libm",
"num-bigint",
"num-integer",
@@ -2433,8 +2449,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
dependencies = [
"cfg-if 1.0.0",
+ "js-sys",
"libc",
"wasi 0.11.0+wasi-snapshot-preview1",
+ "wasm-bindgen",
]
[[package]]
@@ -2494,7 +2512,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89"
dependencies = [
"byteorder",
- "ff",
+ "ff 0.11.1",
+ "rand_core 0.6.4",
+ "subtle 2.4.1",
+]
+
+[[package]]
+name = "group"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7"
+dependencies = [
+ "ff 0.12.1",
+ "memuse",
"rand_core 0.6.4",
"subtle 2.4.1",
]
@@ -2511,8 +2541,8 @@ dependencies = [
"ark-poly",
"ark-serialize",
"ark-std",
- "blake2b_simd 1.0.1",
- "chacha20",
+ "blake2b_simd",
+ "chacha20 0.8.2",
"hex",
"itertools",
"miracl_core",
@@ -2568,20 +2598,6 @@ version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
-[[package]]
-name = "halo2"
-version = "0.1.0-beta.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f186b85ed81082fb1cf59d52b0111f02915e89a4ac61d292b38d075e570f3a9"
-dependencies = [
- "blake2b_simd 0.5.11",
- "ff",
- "group",
- "pasta_curves",
- "rand 0.8.5",
- "rayon",
-]
-
[[package]]
name = "hashbrown"
version = "0.11.2"
@@ -3007,7 +3023,7 @@ dependencies = [
"regex",
"retry",
"ripemd",
- "secp256k1 0.24.3",
+ "secp256k1",
"semver 1.0.17",
"serde 1.0.163",
"serde_derive",
@@ -3134,9 +3150,9 @@ dependencies = [
[[package]]
name = "incrementalmerkletree"
-version = "0.2.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "186fd3ab92aeac865d4b80b410de9a7b341d31ba8281373caed0b6d17b2b5e96"
+checksum = "d5ad43a3f5795945459d577f6589cf62a476e92c79b75e70cd954364e14ce17b"
dependencies = [
"serde 1.0.163",
]
@@ -3167,6 +3183,15 @@ dependencies = [
"serde 1.0.163",
]
+[[package]]
+name = "inout"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
+dependencies = [
+ "generic-array 0.14.7",
+]
+
[[package]]
name = "input_buffer"
version = "0.4.0"
@@ -3249,14 +3274,14 @@ dependencies = [
[[package]]
name = "jubjub"
-version = "0.8.0"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2e7baec19d4e83f9145d4891178101a604565edff9645770fc979804138b04c"
+checksum = "a575df5f985fe1cd5b2b05664ff6accfc46559032b954529fd225a2168d27b0f"
dependencies = [
- "bitvec 0.22.3",
- "bls12_381",
- "ff",
- "group",
+ "bitvec 1.0.1",
+ "bls12_381 0.7.1",
+ "ff 0.12.1",
+ "group 0.12.1",
"rand_core 0.6.4",
"subtle 2.4.1",
]
@@ -3398,7 +3423,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fc1e2c808481a63dc6da2074752fdd4336a3c8fcc68b83db6f1fd5224ae7962"
dependencies = [
"arrayref",
- "crunchy 0.2.2",
+ "crunchy",
"digest 0.8.1",
"hmac-drbg 0.2.0",
"rand 0.7.3",
@@ -3430,7 +3455,7 @@ name = "libsecp256k1-core"
version = "0.3.0"
source = "git+https://github.com/heliaxdev/libsecp256k1?rev=bbb3bd44a49db361f21d9db80f9a087c194c0ae9#bbb3bd44a49db361f21d9db80f9a087c194c0ae9"
dependencies = [
- "crunchy 0.2.2",
+ "crunchy",
"digest 0.9.0",
"subtle 2.4.1",
]
@@ -3574,60 +3599,69 @@ dependencies = [
"serde_yaml",
]
+[[package]]
+name = "masp_note_encryption"
+version = "0.2.0"
+source = "git+https://github.com/anoma/masp?rev=cfea8c95d3f73077ca3e25380fd27e5b46e828fd#cfea8c95d3f73077ca3e25380fd27e5b46e828fd"
+dependencies = [
+ "borsh",
+ "chacha20 0.9.1",
+ "chacha20poly1305",
+ "cipher 0.4.4",
+ "rand_core 0.6.4",
+ "subtle 2.4.1",
+]
+
[[package]]
name = "masp_primitives"
-version = "0.5.0"
-source = "git+https://github.com/anoma/masp?rev=4274fc0bf300bcdae4f186fba134bab8af83ae93#4274fc0bf300bcdae4f186fba134bab8af83ae93"
+version = "0.9.0"
+source = "git+https://github.com/anoma/masp?rev=cfea8c95d3f73077ca3e25380fd27e5b46e828fd#cfea8c95d3f73077ca3e25380fd27e5b46e828fd"
dependencies = [
"aes",
"bip0039",
- "bitvec 0.22.3",
- "blake2b_simd 1.0.1",
+ "bitvec 1.0.1",
+ "blake2b_simd",
"blake2s_simd 1.0.1",
- "bls12_381",
+ "bls12_381 0.7.1",
"borsh",
"byteorder",
- "chacha20poly1305",
- "crypto_api_chachapoly",
- "ff",
+ "ff 0.12.1",
"fpe",
- "group",
+ "group 0.12.1",
"hex",
"incrementalmerkletree",
"jubjub",
"lazy_static",
+ "masp_note_encryption",
+ "memuse",
+ "nonempty",
"rand 0.8.5",
"rand_core 0.6.4",
- "ripemd160",
- "secp256k1 0.20.3",
- "serde 1.0.163",
"sha2 0.9.9",
"subtle 2.4.1",
"zcash_encoding",
- "zcash_primitives",
]
[[package]]
name = "masp_proofs"
-version = "0.5.0"
-source = "git+https://github.com/anoma/masp?rev=4274fc0bf300bcdae4f186fba134bab8af83ae93#4274fc0bf300bcdae4f186fba134bab8af83ae93"
+version = "0.9.0"
+source = "git+https://github.com/anoma/masp?rev=cfea8c95d3f73077ca3e25380fd27e5b46e828fd#cfea8c95d3f73077ca3e25380fd27e5b46e828fd"
dependencies = [
- "bellman",
- "blake2b_simd 1.0.1",
- "bls12_381",
- "byteorder",
+ "bellman 0.13.1",
+ "blake2b_simd",
+ "bls12_381 0.7.1",
"directories",
- "ff",
- "group",
+ "getrandom 0.2.9",
+ "group 0.12.1",
"itertools",
"jubjub",
"lazy_static",
"masp_primitives",
"minreq",
"rand_core 0.6.4",
+ "redjubjub",
+ "tracing 0.1.37",
"wagyu-zcash-parameters",
- "zcash_primitives",
- "zcash_proofs",
]
[[package]]
@@ -3714,9 +3748,6 @@ name = "memuse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2145869435ace5ea6ea3d35f59be559317ec9a0d04e1812d5f185a87b6d36f1a"
-dependencies = [
- "nonempty",
-]
[[package]]
name = "memzero"
@@ -3890,9 +3921,9 @@ dependencies = [
"async-std",
"async-trait",
"base58 0.2.0",
- "bellman",
+ "bellman 0.11.2",
"bimap",
- "bls12_381",
+ "bls12_381 0.6.1",
"borsh",
"byte-unit",
"circular-queue",
@@ -3921,6 +3952,7 @@ dependencies = [
"rand 0.8.5",
"rand_core 0.6.4",
"rayon",
+ "ripemd",
"rust_decimal",
"rust_decimal_macros",
"serde 1.0.163",
@@ -4001,6 +4033,7 @@ dependencies = [
"rayon",
"regex",
"reqwest",
+ "ripemd",
"rlimit",
"rocksdb",
"rpassword",
@@ -4044,7 +4077,7 @@ dependencies = [
"ark-serialize",
"assert_matches",
"bech32 0.8.1",
- "bellman",
+ "bellman 0.11.2",
"borsh",
"chrono",
"data-encoding",
@@ -4201,7 +4234,6 @@ dependencies = [
"borsh",
"hex",
"masp_primitives",
- "masp_proofs",
"namada_core",
]
@@ -4499,33 +4531,6 @@ dependencies = [
"vcpkg",
]
-[[package]]
-name = "orchard"
-version = "0.1.0-beta.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e31f03b6d0aee6d993cac35388b818e04f076ded0ab284979e4d7cd5a8b3c2be"
-dependencies = [
- "aes",
- "arrayvec 0.7.2",
- "bigint",
- "bitvec 0.22.3",
- "blake2b_simd 1.0.1",
- "ff",
- "fpe",
- "group",
- "halo2",
- "incrementalmerkletree",
- "lazy_static",
- "memuse",
- "nonempty",
- "pasta_curves",
- "rand 0.8.5",
- "reddsa",
- "serde 1.0.163",
- "subtle 2.4.1",
- "zcash_note_encryption 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "orion"
version = "0.16.1"
@@ -4571,7 +4576,16 @@ version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2e415e349a3006dd7d9482cdab1c980a845bed1377777d768cb693a44540b42"
dependencies = [
- "group",
+ "group 0.11.0",
+]
+
+[[package]]
+name = "pairing"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "135590d8bdba2b31346f9cd1fb2a912329f5135e832a4f422942eb6ead8b6b3b"
+dependencies = [
+ "group 0.12.1",
]
[[package]]
@@ -4672,21 +4686,6 @@ dependencies = [
"subtle 2.4.1",
]
-[[package]]
-name = "pasta_curves"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d647d91972bad78120fd61e06b225fcda117805c9bbf17676b51bd03a251278b"
-dependencies = [
- "blake2b_simd 0.5.11",
- "ff",
- "group",
- "lazy_static",
- "rand 0.8.5",
- "static_assertions",
- "subtle 2.4.1",
-]
-
[[package]]
name = "paste"
version = "1.0.12"
@@ -4840,9 +4839,9 @@ dependencies = [
[[package]]
name = "poly1305"
-version = "0.7.2"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede"
+checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
dependencies = [
"cpufeatures",
"opaque-debug 0.3.0",
@@ -5373,17 +5372,15 @@ dependencies = [
]
[[package]]
-name = "reddsa"
-version = "0.1.0"
+name = "redjubjub"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a90e2c94bca3445cae0d55dff7370e29c24885d2403a1665ce19c106c79455e6"
+checksum = "6039ff156887caf92df308cbaccdc058c9d3155a913da046add6e48c4cdbd91d"
dependencies = [
- "blake2b_simd 0.5.11",
+ "blake2b_simd",
"byteorder",
"digest 0.9.0",
- "group",
"jubjub",
- "pasta_curves",
"rand_core 0.6.4",
"serde 1.0.163",
"thiserror",
@@ -5928,15 +5925,6 @@ dependencies = [
"zeroize",
]
-[[package]]
-name = "secp256k1"
-version = "0.20.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97d03ceae636d0fed5bae6a7f4f664354c5f4fcedf6eef053fef17e49f837d0a"
-dependencies = [
- "secp256k1-sys 0.4.2",
-]
-
[[package]]
name = "secp256k1"
version = "0.24.3"
@@ -5945,19 +5933,10 @@ checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62"
dependencies = [
"bitcoin_hashes",
"rand 0.8.5",
- "secp256k1-sys 0.6.1",
+ "secp256k1-sys",
"serde 1.0.163",
]
-[[package]]
-name = "secp256k1-sys"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "957da2573cde917463ece3570eab4a0b3f19de6f1646cde62e6fd3868f566036"
-dependencies = [
- "cc",
-]
-
[[package]]
name = "secp256k1-sys"
version = "0.6.1"
@@ -6821,7 +6800,7 @@ version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
dependencies = [
- "crunchy 0.2.2",
+ "crunchy",
]
[[package]]
@@ -7416,7 +7395,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52"
dependencies = [
"byteorder",
- "crunchy 0.2.2",
+ "crunchy",
"hex",
"static_assertions",
]
@@ -7480,11 +7459,11 @@ checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "universal-hash"
-version = "0.4.1"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05"
+checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5"
dependencies = [
- "generic-array 0.14.7",
+ "crypto-common",
"subtle 2.4.1",
]
@@ -8402,83 +8381,10 @@ dependencies = [
[[package]]
name = "zcash_encoding"
version = "0.0.0"
-source = "git+https://github.com/zcash/librustzcash?rev=2425a08#2425a0869098e3b0588ccd73c42716bcf418612c"
-dependencies = [
- "byteorder",
- "nonempty",
-]
-
-[[package]]
-name = "zcash_note_encryption"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33f84ae538f05a8ac74c82527f06b77045ed9553a0871d9db036166a4c344e3a"
-dependencies = [
- "chacha20",
- "chacha20poly1305",
- "rand_core 0.6.4",
- "subtle 2.4.1",
-]
-
-[[package]]
-name = "zcash_note_encryption"
-version = "0.1.0"
-source = "git+https://github.com/zcash/librustzcash?rev=2425a08#2425a0869098e3b0588ccd73c42716bcf418612c"
-dependencies = [
- "chacha20",
- "chacha20poly1305",
- "rand_core 0.6.4",
- "subtle 2.4.1",
-]
-
-[[package]]
-name = "zcash_primitives"
-version = "0.5.0"
-source = "git+https://github.com/zcash/librustzcash?rev=2425a08#2425a0869098e3b0588ccd73c42716bcf418612c"
+source = "git+https://github.com/zcash/librustzcash?rev=43c18d0#43c18d000fcbe45363b2d53585d5102841eff99e"
dependencies = [
- "aes",
- "bip0039",
- "bitvec 0.22.3",
- "blake2b_simd 1.0.1",
- "blake2s_simd 1.0.1",
- "bls12_381",
"byteorder",
- "chacha20poly1305",
- "equihash",
- "ff",
- "fpe",
- "group",
- "hex",
- "incrementalmerkletree",
- "jubjub",
- "lazy_static",
- "memuse",
"nonempty",
- "orchard",
- "rand 0.8.5",
- "rand_core 0.6.4",
- "sha2 0.9.9",
- "subtle 2.4.1",
- "zcash_encoding",
- "zcash_note_encryption 0.1.0 (git+https://github.com/zcash/librustzcash?rev=2425a08)",
-]
-
-[[package]]
-name = "zcash_proofs"
-version = "0.5.0"
-source = "git+https://github.com/zcash/librustzcash?rev=2425a08#2425a0869098e3b0588ccd73c42716bcf418612c"
-dependencies = [
- "bellman",
- "blake2b_simd 1.0.1",
- "bls12_381",
- "byteorder",
- "directories",
- "ff",
- "group",
- "jubjub",
- "lazy_static",
- "rand_core 0.6.4",
- "zcash_primitives",
]
[[package]]
diff --git a/apps/Cargo.toml b/apps/Cargo.toml
index 7bc04afea5..710d02daf3 100644
--- a/apps/Cargo.toml
+++ b/apps/Cargo.toml
@@ -45,7 +45,7 @@ mainnet = [
"namada/mainnet",
]
dev = ["namada/dev"]
-std = ["ed25519-consensus/std", "rand/std", "rand_core/std"]
+std = ["ed25519-consensus/std", "rand/std", "rand_core/std", "namada/std"]
# for integration tests and test utilies
testing = ["dev"]
@@ -104,6 +104,7 @@ rand_core = {version = "0.6", default-features = false}
rayon = "=1.5.3"
regex = "1.4.5"
reqwest = "0.11.4"
+ripemd = "0.1"
rlimit = "0.5.4"
rocksdb = {version = "0.21.0", features = ['zstd', 'jemalloc'], default-features = false}
rpassword = "5.0.1"
@@ -133,9 +134,9 @@ tracing-log = "0.1.2"
tracing-subscriber = {version = "0.3.7", features = ["env-filter", "json"]}
websocket = "0.26.2"
winapi = "0.3.9"
-#libmasp = { git = "https://github.com/anoma/masp", branch = "murisi/masp-incentive" }
-masp_primitives = { git = "https://github.com/anoma/masp", rev = "4274fc0bf300bcdae4f186fba134bab8af83ae93", features = ["transparent-inputs"] }
-masp_proofs = { git = "https://github.com/anoma/masp", rev = "4274fc0bf300bcdae4f186fba134bab8af83ae93", features = ["bundled-prover", "download-params"] }
+# branch = "murisi/namada-integration"
+masp_primitives = { git = "https://github.com/anoma/masp", rev = "cfea8c95d3f73077ca3e25380fd27e5b46e828fd", features = ["transparent-inputs"] }
+masp_proofs = { git = "https://github.com/anoma/masp", rev = "cfea8c95d3f73077ca3e25380fd27e5b46e828fd", features = ["bundled-prover", "download-params"] }
bimap = {version = "0.6.2", features = ["serde"]}
rust_decimal = "=1.26.1"
rust_decimal_macros = "=1.26.1"
diff --git a/apps/src/lib/cli/context.rs b/apps/src/lib/cli/context.rs
index 42c1bb6c94..630d329515 100644
--- a/apps/src/lib/cli/context.rs
+++ b/apps/src/lib/cli/context.rs
@@ -1,6 +1,6 @@
//! CLI input types can be used for command arguments
-use std::collections::HashSet;
+use std::collections::{HashMap, HashSet};
use std::env;
use std::marker::PhantomData;
use std::path::{Path, PathBuf};
@@ -194,10 +194,31 @@ impl Context {
wasm_loader::read_wasm_or_exit(self.wasm_dir(), file_name)
}
- /// Get address with vp type
+ /// Try to find an alias for a given address from the wallet. If not found,
+ /// formats the address into a string.
+ pub fn lookup_alias(&self, addr: &Address) -> String {
+ match self.wallet.find_alias(addr) {
+ Some(alias) => alias.to_string(),
+ None => addr.to_string(),
+ }
+ }
+
+ /// Get addresses with tokens VP type.
pub fn tokens(&self) -> HashSet
{
self.wallet.get_addresses_with_vp_type(AddressVpType::Token)
}
+
+ /// Get addresses with tokens VP type associated with their aliases.
+ pub fn tokens_with_aliases(&self) -> HashMap {
+ self.wallet
+ .get_addresses_with_vp_type(AddressVpType::Token)
+ .into_iter()
+ .map(|addr| {
+ let alias = self.lookup_alias(&addr);
+ (addr, alias)
+ })
+ .collect()
+ }
}
/// Load global config from expected path in the `base_dir` or try to generate a
diff --git a/apps/src/lib/client/rpc.rs b/apps/src/lib/client/rpc.rs
index ce5eb1bbc3..70167f59e2 100644
--- a/apps/src/lib/client/rpc.rs
+++ b/apps/src/lib/client/rpc.rs
@@ -16,8 +16,7 @@ use data_encoding::HEXLOWER;
use itertools::Either;
use masp_primitives::asset_type::AssetType;
use masp_primitives::merkle_tree::MerklePath;
-use masp_primitives::primitives::ViewingKey;
-use masp_primitives::sapling::Node;
+use masp_primitives::sapling::{Node, ViewingKey};
use masp_primitives::transaction::components::Amount;
use masp_primitives::zip32::ExtendedFullViewingKey;
use namada::core::types::transaction::governance::ProposalType;
diff --git a/apps/src/lib/client/signing.rs b/apps/src/lib/client/signing.rs
index eec89b4f80..c44da88f9b 100644
--- a/apps/src/lib/client/signing.rs
+++ b/apps/src/lib/client/signing.rs
@@ -5,10 +5,10 @@ use namada::ledger::rpc::TxBroadcastData;
use namada::ledger::signing::TxSigningKey;
use namada::ledger::tx;
use namada::ledger::wallet::{Wallet, WalletUtils};
+use namada::proof_of_stake::Epoch;
use namada::proto::Tx;
use namada::types::address::Address;
use namada::types::key::*;
-use namada::types::storage::Epoch;
use crate::cli::args;
@@ -77,8 +77,12 @@ pub async fn sign_tx<
/// Create a wrapper tx from a normal tx. Get the hash of the
/// wrapper and its payload which is needed for monitoring its
/// progress on chain.
-pub async fn sign_wrapper(
+pub async fn sign_wrapper<
+ C: namada::ledger::queries::Client + Sync,
+ U: WalletUtils,
+>(
client: &C,
+ wallet: &mut Wallet,
args: &args::Tx,
epoch: Epoch,
tx: Tx,
@@ -87,6 +91,7 @@ pub async fn sign_wrapper(
) -> TxBroadcastData {
namada::ledger::signing::sign_wrapper(
client,
+ wallet,
args,
epoch,
tx,
diff --git a/apps/src/lib/client/tx.rs b/apps/src/lib/client/tx.rs
index 66310c1495..76f39b9046 100644
--- a/apps/src/lib/client/tx.rs
+++ b/apps/src/lib/client/tx.rs
@@ -16,19 +16,21 @@ use namada::ledger::rpc::{TxBroadcastData, TxResponse};
use namada::ledger::signing::TxSigningKey;
use namada::ledger::wallet::{Wallet, WalletUtils};
use namada::ledger::{masp, tx};
-use namada::proto::Tx;
+use namada::proto::{Code, Data, Section, Tx};
use namada::types::address::Address;
use namada::types::governance::{
OfflineProposal, OfflineVote, Proposal, ProposalVote, VoteType,
};
+use namada::types::hash::Hash;
use namada::types::key::*;
use namada::types::storage::{Epoch, Key};
use namada::types::token;
use namada::types::transaction::governance::{
InitProposalData, ProposalType, VoteProposalData,
};
-use namada::types::transaction::InitValidator;
+use namada::types::transaction::{InitValidator, TxType};
use rust_decimal::Decimal;
+use sha2::{Digest as Sha2Digest, Sha256};
use tendermint_rpc::HttpClient;
use super::rpc;
@@ -36,6 +38,7 @@ use crate::cli::context::WalletAddress;
use crate::cli::{args, safe_exit, Context};
use crate::client::rpc::query_wasm_code_hash;
use crate::client::signing::find_keypair;
+use crate::client::tx::tx::ProcessTxResponse;
use crate::facade::tendermint_rpc::endpoint::broadcast::tx_sync::Response;
use crate::node::ledger::tendermint_node;
use crate::wallet::{
@@ -201,6 +204,12 @@ pub async fn submit_init_validator<
.await
.unwrap();
+ let mut tx = Tx::new(TxType::Raw);
+ let extra = tx.add_section(Section::ExtraData(Code::from_hash(
+ validator_vp_code_hash,
+ )));
+ let extra_hash =
+ Hash(extra.hash(&mut Sha256::new()).finalize_reset().into());
let data = InitValidator {
account_key,
consensus_key: consensus_key.ref_to(),
@@ -208,15 +217,14 @@ pub async fn submit_init_validator<
dkg_key,
commission_rate,
max_commission_rate_change,
- validator_vp_code_hash,
+ validator_vp_code_hash: extra_hash,
};
let data = data.try_to_vec().expect("Encoding tx data shouldn't fail");
- let tx = Tx::new(
- tx_code_hash.to_vec(),
- Some(data),
- tx_args.chain_id.clone().unwrap(),
- tx_args.expiration,
- );
+ tx.header.chain_id = tx_args.chain_id.clone().unwrap();
+ tx.header.expiration = tx_args.expiration;
+ tx.set_data(Data::new(data));
+ tx.set_code(Code::from_hash(tx_code_hash));
+
let (mut ctx, result) = process_tx(
client,
ctx,
@@ -324,7 +332,7 @@ impl CLIShieldedUtils {
&& output_path.exists())
{
println!("MASP parameters not present, downloading...");
- masp_proofs::download_parameters()
+ masp_proofs::download_masp_parameters(None)
.expect("MASP parameters not present or downloadable");
println!("MASP parameter download complete, resuming execution...");
}
@@ -447,9 +455,9 @@ pub async fn submit_init_proposal(
serde_json::from_reader(file).expect("JSON was not well-formatted");
let signer = WalletAddress::new(proposal.clone().author.to_string());
- let governance_parameters = rpc::get_governance_parameters(client).await;
let current_epoch = rpc::query_and_print_epoch(client).await;
+ let governance_parameters = rpc::get_governance_parameters(client).await;
if proposal.voting_start_epoch <= current_epoch
|| proposal.voting_start_epoch.0
% governance_parameters.min_proposal_period
@@ -540,13 +548,10 @@ pub async fn submit_init_proposal(
safe_exit(1)
};
- let balance = rpc::get_token_balance(
- client,
- &args.native_token,
- &proposal.author,
- )
- .await
- .unwrap_or_default();
+ let balance =
+ rpc::get_token_balance(client, &ctx.native_token, &proposal.author)
+ .await
+ .unwrap_or_default();
if balance
< token::Amount::from(governance_parameters.min_proposal_fund)
{
@@ -564,18 +569,17 @@ pub async fn submit_init_proposal(
safe_exit(1);
}
+ let mut tx = Tx::new(TxType::Raw);
let data = init_proposal_data
.try_to_vec()
.expect("Encoding proposal data shouldn't fail");
let tx_code_hash = query_wasm_code_hash(client, args::TX_INIT_PROPOSAL)
.await
.unwrap();
- let tx = Tx::new(
- tx_code_hash.to_vec(),
- Some(data),
- ctx.config.ledger.chain_id.clone(),
- args.tx.expiration,
- );
+ tx.header.chain_id = ctx.config.ledger.chain_id.clone();
+ tx.header.expiration = args.tx.expiration;
+ tx.set_data(Data::new(data));
+ tx.set_code(Code::from_hash(tx_code_hash));
process_tx::(
client,
@@ -819,8 +823,13 @@ pub async fn submit_vote_proposal(
let data = tx_data
.try_to_vec()
.expect("Encoding proposal data shouldn't fail");
+
let tx_code = args.tx_code_path;
- let tx = Tx::new(tx_code, Some(data), chain_id, expiration);
+ let mut tx = Tx::new(TxType::Raw);
+ tx.header.chain_id = chain_id;
+ tx.header.expiration = expiration;
+ tx.set_data(Data::new(data));
+ tx.set_code(Code::new(tx_code));
process_tx::(
client,
@@ -886,7 +895,7 @@ pub async fn submit_reveal_pk_aux(
ctx: &mut Context,
public_key: &common::PublicKey,
args: &args::Tx,
-) -> Result<(), tx::Error> {
+) -> Result {
let args = args::Tx {
chain_id: args
.clone()
@@ -1014,7 +1023,10 @@ async fn process_tx(
#[cfg(not(feature = "mainnet"))] requires_pow: bool,
) -> Result<(Context, Vec), tx::Error> {
let args = args::Tx {
- chain_id: args.clone().chain_id.or_else(|| Some(tx.chain_id.clone())),
+ chain_id: args
+ .clone()
+ .chain_id
+ .or_else(|| Some(tx.header.chain_id.clone())),
..args.clone()
};
let res: Vec = tx::process_tx::(
@@ -1026,7 +1038,8 @@ async fn process_tx(
#[cfg(not(feature = "mainnet"))]
requires_pow,
)
- .await?;
+ .await?
+ .initialized_accounts();
Ok((ctx, res))
}
diff --git a/apps/src/lib/node/ledger/shell/finalize_block.rs b/apps/src/lib/node/ledger/shell/finalize_block.rs
index 84a8bd6efd..3b22975d1e 100644
--- a/apps/src/lib/node/ledger/shell/finalize_block.rs
+++ b/apps/src/lib/node/ledger/shell/finalize_block.rs
@@ -127,26 +127,19 @@ where
if ErrorCodes::from_u32(processed_tx.result.code).unwrap()
== ErrorCodes::InvalidSig
{
- let mut tx_event = match process_tx(tx.clone()) {
- Ok(tx @ TxType::Wrapper(_))
- | Ok(tx @ TxType::Protocol(_)) => {
+ let mut tx_event = match tx.header().tx_type {
+ TxType::Wrapper(_) | TxType::Protocol(_) => {
Event::new_tx_event(&tx, height.0)
}
- _ => match TxType::try_from(tx) {
- Ok(tx @ TxType::Wrapper(_))
- | Ok(tx @ TxType::Protocol(_)) => {
- Event::new_tx_event(&tx, height.0)
- }
- _ => {
- tracing::error!(
- "Internal logic error: FinalizeBlock received \
- a tx with an invalid signature error code \
- that could not be deserialized to a \
- WrapperTx / ProtocolTx type"
- );
- continue;
- }
- },
+ _ => {
+ tracing::error!(
+ "Internal logic error: FinalizeBlock received a \
+ tx with an invalid signature error code that \
+ could not be deserialized to a WrapperTx / \
+ ProtocolTx type"
+ );
+ continue;
+ }
};
tx_event["code"] = processed_tx.result.code.to_string();
tx_event["info"] =
@@ -156,8 +149,8 @@ where
continue;
}
- let tx_type = if let Ok(tx_type) = process_tx(tx) {
- tx_type
+ let tx = if let Ok(()) = tx.validate_header() {
+ tx
} else {
tracing::error!(
"Internal logic error: FinalizeBlock received tx that \
@@ -165,12 +158,13 @@ where
);
continue;
};
+ let tx_type = tx.header();
// If [`process_proposal`] rejected a Tx, emit an event here and
// move on to next tx
if ErrorCodes::from_u32(processed_tx.result.code).unwrap()
!= ErrorCodes::Ok
{
- let mut tx_event = Event::new_tx_event(&tx_type, height.0);
+ let mut tx_event = Event::new_tx_event(&tx, height.0);
tx_event["code"] = processed_tx.result.code.to_string();
tx_event["info"] =
format!("Tx rejected: {}", &processed_tx.result.info);
@@ -179,7 +173,7 @@ where
// if the rejected tx was decrypted, remove it
// from the queue of txs to be processed and remove the hash
// from storage
- if let TxType::Decrypted(_) = &tx_type {
+ if let TxType::Decrypted(_) = &tx_type.tx_type {
let tx_hash = self
.wl_storage
.storage
@@ -187,7 +181,9 @@ where
.pop()
.expect("Missing wrapper tx in queue")
.tx
- .tx_hash;
+ .clone()
+ .update_header(TxType::Raw)
+ .header_hash();
let tx_hash_key =
replay_protection::get_tx_hash_key(&tx_hash);
self.wl_storage
@@ -198,24 +194,26 @@ where
continue;
}
- let (mut tx_event, tx_unsigned_hash) = match &tx_type {
+ let (mut tx_event, tx_unsigned_hash) = match &tx_type.tx_type {
TxType::Wrapper(wrapper) => {
stats.increment_wrapper_txs();
- let mut tx_event = Event::new_tx_event(&tx_type, height.0);
+ let mut tx_event = Event::new_tx_event(&tx, height.0);
// Writes both txs hash to storage
- let tx = Tx::try_from(processed_tx.tx.as_ref()).unwrap();
+ let processed_tx =
+ Tx::try_from(processed_tx.tx.as_ref()).unwrap();
let wrapper_tx_hash_key =
replay_protection::get_tx_hash_key(&hash::Hash(
- tx.unsigned_hash(),
+ processed_tx.header_hash().0,
));
self.wl_storage
.storage
.write(&wrapper_tx_hash_key, vec![])
.expect("Error while writing tx hash to storage");
- let inner_tx_hash_key =
- replay_protection::get_tx_hash_key(&wrapper.tx_hash);
+ let inner_tx_hash_key = replay_protection::get_tx_hash_key(
+ &tx.clone().update_header(TxType::Raw).header_hash(),
+ );
self.wl_storage
.storage
.write(&inner_tx_hash_key, vec![])
@@ -276,8 +274,8 @@ where
}
}
- self.wl_storage.storage.tx_queue.push(WrapperTxInQueue {
- tx: wrapper.clone(),
+ self.wl_storage.storage.tx_queue.push(TxInQueue {
+ tx: processed_tx.clone(),
#[cfg(not(feature = "mainnet"))]
has_valid_pow,
});
@@ -292,20 +290,23 @@ where
.pop()
.expect("Missing wrapper tx in queue")
.tx
- .tx_hash;
- let mut event = Event::new_tx_event(&tx_type, height.0);
+ .clone()
+ .update_header(TxType::Raw)
+ .header_hash();
+ let mut event = Event::new_tx_event(&tx, height.0);
match inner {
- DecryptedTx::Decrypted {
- tx,
- has_valid_pow: _,
- } => {
- stats.increment_tx_type(
- namada::core::types::hash::Hash(tx.code_hash())
- .to_string(),
- );
+ DecryptedTx::Decrypted { has_valid_pow: _ } => {
+ if let Some(code_sec) = tx
+ .get_section(tx.code_sechash())
+ .and_then(Section::code_sec)
+ {
+ stats.increment_tx_type(
+ code_sec.code.hash().to_string(),
+ );
+ }
}
- DecryptedTx::Undecryptable(_) => {
+ DecryptedTx::Undecryptable => {
event["log"] =
"Transaction could not be decrypted.".into();
event["code"] = ErrorCodes::Undecryptable.into();
@@ -313,7 +314,7 @@ where
}
(event, Some(wrapper_hash))
}
- TxType::Raw(_) => {
+ TxType::Raw => {
tracing::error!(
"Internal logic error: FinalizeBlock received a \
TxType::Raw transaction"
@@ -330,7 +331,7 @@ where
};
match protocol::apply_tx(
- tx_type,
+ tx.clone(),
tx_length,
TxIndex(
tx_index
@@ -418,8 +419,8 @@ where
.storage
.delete(&tx_hash_key)
.expect(
- "Error while deleting tx hash key from storage",
- );
+ "Error while deleting tx hash key from storage",
+ );
}
}
@@ -898,6 +899,7 @@ mod test_finalize_block {
rewards_accumulator_handle, validator_consensus_key_handle,
validator_rewards_products_handle,
};
+ use namada::proto::{Code, Data, Section, Signature};
use namada::types::governance::ProposalVote;
use namada::types::key::tm_consensus_key_raw_hash;
use namada::types::storage::Epoch;
@@ -905,7 +907,7 @@ mod test_finalize_block {
use namada::types::transaction::governance::{
InitProposalData, ProposalType, VoteProposalData,
};
- use namada::types::transaction::{EncryptionKey, Fee, WrapperTx, MIN_FEE};
+ use namada::types::transaction::{Fee, WrapperTx, MIN_FEE};
use namada_test_utils::TestWasms;
use rust_decimal_macros::dec;
use test_log::test;
@@ -940,31 +942,31 @@ mod test_finalize_block {
// create some wrapper txs
for i in 1u64..5 {
- let raw_tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some(format!("transaction data: {}", i).as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let wrapper = WrapperTx::new(
- Fee {
- amount: MIN_FEE.into(),
- token: shell.wl_storage.storage.native_token.clone(),
- },
+ let mut wrapper =
+ Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
+ Fee {
+ amount: MIN_FEE.into(),
+ token: shell.wl_storage.storage.native_token.clone(),
+ },
+ &keypair,
+ Epoch(0),
+ 0.into(),
+ #[cfg(not(feature = "mainnet"))]
+ None,
+ ))));
+ wrapper.header.chain_id = shell.chain_id.clone();
+ wrapper.set_data(Data::new("wasm_code".as_bytes().to_owned()));
+ wrapper.set_code(Code::new(
+ format!("transaction data: {}", i).as_bytes().to_owned(),
+ ));
+ wrapper.add_section(Section::Signature(Signature::new(
+ &wrapper.header_hash(),
&keypair,
- Epoch(0),
- 0.into(),
- raw_tx.clone(),
- Default::default(),
- #[cfg(not(feature = "mainnet"))]
- None,
- );
- let tx = wrapper
- .sign(&keypair, shell.chain_id.clone(), None)
- .expect("Test failed");
+ )));
+ wrapper.encrypt(&Default::default());
if i > 1 {
processed_txs.push(ProcessedTx {
- tx: tx.to_bytes(),
+ tx: wrapper.to_bytes(),
result: TxResult {
code: u32::try_from(i.rem_euclid(2))
.expect("Test failed"),
@@ -1000,10 +1002,9 @@ mod test_finalize_block {
for wrapper in shell.iter_tx_queue() {
// we cannot easily implement the PartialEq trait for WrapperTx
// so we check the hashes of the inner txs for equality
- assert_eq!(
- wrapper.tx.tx_hash,
- valid_tx.next().expect("Test failed").tx_hash
- );
+ let valid_tx = valid_tx.next().expect("Test failed");
+ assert_eq!(wrapper.tx.header.code_hash, *valid_tx.code_sechash());
+ assert_eq!(wrapper.tx.header.data_hash, *valid_tx.data_sechash());
counter += 1;
}
assert_eq!(counter, 3);
@@ -1017,13 +1018,7 @@ mod test_finalize_block {
fn test_process_proposal_rejected_decrypted_tx() {
let (mut shell, _) = setup(1);
let keypair = gen_keypair();
- let raw_tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some(String::from("transaction data").as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let wrapper = WrapperTx::new(
+ let mut outer_tx = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: 0.into(),
token: shell.wl_storage.storage.native_token.clone(),
@@ -1031,25 +1026,28 @@ mod test_finalize_block {
&keypair,
Epoch(0),
0.into(),
- raw_tx.clone(),
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- );
-
+ ))));
+ outer_tx.header.chain_id = shell.chain_id.clone();
+ outer_tx.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ outer_tx.set_data(Data::new(
+ String::from("transaction data").as_bytes().to_owned(),
+ ));
+ outer_tx.encrypt(&Default::default());
+ shell.enqueue_tx(outer_tx.clone());
+
+ outer_tx.update_header(TxType::Decrypted(DecryptedTx::Decrypted {
+ #[cfg(not(feature = "mainnet"))]
+ has_valid_pow: false,
+ }));
let processed_tx = ProcessedTx {
- tx: Tx::from(TxType::Decrypted(DecryptedTx::Decrypted {
- tx: raw_tx,
- #[cfg(not(feature = "mainnet"))]
- has_valid_pow: false,
- }))
- .to_bytes(),
+ tx: outer_tx.to_bytes(),
result: TxResult {
code: ErrorCodes::InvalidTx.into(),
info: "".into(),
},
};
- shell.enqueue_tx(wrapper);
// check that the decrypted tx was not applied
for event in shell
@@ -1074,13 +1072,7 @@ mod test_finalize_block {
let (mut shell, _) = setup(1);
let keypair = crate::wallet::defaults::daewon_keypair();
- let pubkey = EncryptionKey::default();
// not valid tx bytes
- let tx = "garbage data".as_bytes().to_owned();
- let inner_tx =
- namada::types::transaction::encrypted::EncryptedTx::encrypt(
- &tx, pubkey,
- );
let wrapper = WrapperTx {
fee: Fee {
amount: 0.into(),
@@ -1089,23 +1081,20 @@ mod test_finalize_block {
pk: keypair.ref_to(),
epoch: Epoch(0),
gas_limit: 0.into(),
- inner_tx,
- tx_hash: hash_tx(&tx),
#[cfg(not(feature = "mainnet"))]
pow_solution: None,
};
let processed_tx = ProcessedTx {
- tx: Tx::from(TxType::Decrypted(DecryptedTx::Undecryptable(
- wrapper.clone(),
- )))
- .to_bytes(),
+ tx: Tx::new(TxType::Decrypted(DecryptedTx::Undecryptable))
+ .to_bytes(),
result: TxResult {
code: ErrorCodes::Ok.into(),
info: "".into(),
},
};
- shell.enqueue_tx(wrapper);
+ let tx = Tx::new(TxType::Wrapper(Box::new(wrapper)));
+ shell.enqueue_tx(tx);
// check that correct error message is returned
for event in shell
@@ -1149,37 +1138,35 @@ mod test_finalize_block {
// create two decrypted txs
let tx_code = TestWasms::TxNoOp.read_bytes();
for i in 0..2 {
- let raw_tx = Tx::new(
- tx_code.clone(),
- Some(
- format!("Decrypted transaction data: {}", i)
- .as_bytes()
- .to_owned(),
- ),
- shell.chain_id.clone(),
- None,
- );
- let wrapper_tx = WrapperTx::new(
- Fee {
- amount: MIN_FEE.into(),
- token: shell.wl_storage.storage.native_token.clone(),
- },
- &keypair,
- Epoch(0),
- 0.into(),
- raw_tx.clone(),
- Default::default(),
+ let mut outer_tx =
+ Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
+ Fee {
+ amount: MIN_FEE.into(),
+ token: shell.wl_storage.storage.native_token.clone(),
+ },
+ &keypair,
+ Epoch(0),
+ 0.into(),
+ #[cfg(not(feature = "mainnet"))]
+ None,
+ ))));
+ outer_tx.header.chain_id = shell.chain_id.clone();
+ outer_tx.set_code(Code::new(tx_code.clone()));
+ outer_tx.set_data(Data::new(
+ format!("Decrypted transaction data: {}", i)
+ .as_bytes()
+ .to_owned(),
+ ));
+ outer_tx.encrypt(&Default::default());
+ shell.enqueue_tx(outer_tx.clone());
+ outer_tx.update_header(TxType::Decrypted(DecryptedTx::Decrypted {
#[cfg(not(feature = "mainnet"))]
- None,
- );
- shell.enqueue_tx(wrapper_tx);
+ has_valid_pow: false,
+ }));
+ outer_tx.decrypt(::G2Affine::prime_subgroup_generator())
+ .expect("Test failed");
processed_txs.push(ProcessedTx {
- tx: Tx::from(TxType::Decrypted(DecryptedTx::Decrypted {
- tx: raw_tx,
- #[cfg(not(feature = "mainnet"))]
- has_valid_pow: false,
- }))
- .to_bytes(),
+ tx: outer_tx.to_bytes(),
result: TxResult {
code: ErrorCodes::Ok.into(),
info: "".into(),
@@ -1188,35 +1175,33 @@ mod test_finalize_block {
}
// create two wrapper txs
for i in 0..2 {
- let raw_tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some(
- format!("Encrypted transaction data: {}", i)
- .as_bytes()
- .to_owned(),
- ),
- shell.chain_id.clone(),
- None,
- );
- let wrapper_tx = WrapperTx::new(
- Fee {
- amount: MIN_FEE.into(),
- token: shell.wl_storage.storage.native_token.clone(),
- },
+ let mut wrapper_tx =
+ Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
+ Fee {
+ amount: MIN_FEE.into(),
+ token: shell.wl_storage.storage.native_token.clone(),
+ },
+ &keypair,
+ Epoch(0),
+ 0.into(),
+ #[cfg(not(feature = "mainnet"))]
+ None,
+ ))));
+ wrapper_tx.header.chain_id = shell.chain_id.clone();
+ wrapper_tx.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ wrapper_tx.set_data(Data::new(
+ format!("Encrypted transaction data: {}", i)
+ .as_bytes()
+ .to_owned(),
+ ));
+ wrapper_tx.add_section(Section::Signature(Signature::new(
+ &wrapper_tx.header_hash(),
&keypair,
- Epoch(0),
- 0.into(),
- raw_tx.clone(),
- Default::default(),
- #[cfg(not(feature = "mainnet"))]
- None,
- );
- let wrapper = wrapper_tx
- .sign(&keypair, shell.chain_id.clone(), None)
- .expect("Test failed");
- valid_txs.push(wrapper_tx);
+ )));
+ wrapper_tx.encrypt(&Default::default());
+ valid_txs.push(wrapper_tx.clone());
processed_txs.push(ProcessedTx {
- tx: wrapper.to_bytes(),
+ tx: wrapper_tx.to_bytes(),
result: TxResult {
code: ErrorCodes::Ok.into(),
info: "".into(),
@@ -1262,10 +1247,9 @@ mod test_finalize_block {
let mut counter = 0;
for wrapper in shell.iter_tx_queue() {
- assert_eq!(
- wrapper.tx.tx_hash,
- txs.next().expect("Test failed").tx_hash
- );
+ let next = txs.next().expect("Test failed");
+ assert_eq!(wrapper.tx.header.code_hash, *next.code_sechash());
+ assert_eq!(wrapper.tx.header.data_hash, *next.data_sechash());
counter += 1;
}
assert_eq!(counter, 2);
@@ -1701,29 +1685,35 @@ mod test_finalize_block {
wasm_path.push("wasm_for_tests/tx_no_op.wasm");
let tx_code = std::fs::read(wasm_path)
.expect("Expected a file at given code path");
- let raw_tx = Tx::new(
- tx_code,
- Some("Encrypted transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let wrapper_tx = WrapperTx::new(
- Fee {
- amount: 0.into(),
- token: shell.wl_storage.storage.native_token.clone(),
- },
- &keypair,
- Epoch(0),
- 0.into(),
- raw_tx.clone(),
- Default::default(),
+ let mut wrapper_tx =
+ Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
+ Fee {
+ amount: 0.into(),
+ token: shell.wl_storage.storage.native_token.clone(),
+ },
+ &keypair,
+ Epoch(0),
+ 0.into(),
+ #[cfg(not(feature = "mainnet"))]
+ None,
+ ))));
+ wrapper_tx.header.chain_id = shell.chain_id.clone();
+ wrapper_tx.set_code(Code::new(tx_code));
+ wrapper_tx.set_data(Data::new(
+ "Encrypted transaction data".as_bytes().to_owned(),
+ ));
+ let mut decrypted_tx = wrapper_tx.clone();
+ wrapper_tx.encrypt(&Default::default());
+
+ decrypted_tx.update_header(TxType::Decrypted(DecryptedTx::Decrypted {
#[cfg(not(feature = "mainnet"))]
- None,
- );
+ has_valid_pow: false,
+ }));
// Write inner hash in storage
- let inner_hash_key =
- replay_protection::get_tx_hash_key(&wrapper_tx.tx_hash);
+ let inner_hash_key = replay_protection::get_tx_hash_key(
+ &wrapper_tx.clone().update_header(TxType::Raw).header_hash(),
+ );
shell
.wl_storage
.storage
@@ -1731,12 +1721,7 @@ mod test_finalize_block {
.expect("Test failed");
let processed_tx = ProcessedTx {
- tx: Tx::from(TxType::Decrypted(DecryptedTx::Decrypted {
- tx: raw_tx,
- #[cfg(not(feature = "mainnet"))]
- has_valid_pow: false,
- }))
- .to_bytes(),
+ tx: decrypted_tx.to_bytes(),
result: TxResult {
code: ErrorCodes::Ok.into(),
info: "".into(),
diff --git a/apps/src/lib/node/ledger/shell/governance.rs b/apps/src/lib/node/ledger/shell/governance.rs
index dfdae4d04e..9ff5ebc279 100644
--- a/apps/src/lib/node/ledger/shell/governance.rs
+++ b/apps/src/lib/node/ledger/shell/governance.rs
@@ -12,6 +12,7 @@ use namada::ledger::storage::types::encode;
use namada::ledger::storage::{DBIter, StorageHasher, DB};
use namada::ledger::storage_api::{token, StorageWrite};
use namada::proof_of_stake::read_total_stake;
+use namada::proto::{Code, Data};
use namada::types::address::Address;
use namada::types::governance::{Council, Tally, TallyResult, VotePower};
use namada::types::storage::Epoch;
@@ -147,17 +148,13 @@ where
let proposal_code = shell.read_storage_key_bytes(&proposal_code_key);
match proposal_code {
Some(proposal_code) => {
- let tx = Tx::new(
- proposal_code,
- Some(encode(&id)),
- shell.chain_id.clone(),
- None,
- );
- let tx_type = TxType::Decrypted(DecryptedTx::Decrypted {
- tx,
+ let mut tx = Tx::new(TxType::Decrypted(DecryptedTx::Decrypted {
#[cfg(not(feature = "mainnet"))]
has_valid_pow: false,
- });
+ }));
+ tx.header.chain_id = shell.chain_id.clone();
+ tx.set_data(Data::new(encode(&id)));
+ tx.set_code(Code::new(proposal_code));
let pending_execution_key =
gov_storage::get_proposal_execution_key(id);
shell
@@ -165,7 +162,7 @@ where
.write(&pending_execution_key, ())
.expect("Should be able to write to storage.");
let tx_result = protocol::apply_tx(
- tx_type,
+ tx,
0, /* this is used to compute the fee
* based on the code size. We dont
* need it here. */
diff --git a/apps/src/lib/node/ledger/shell/mod.rs b/apps/src/lib/node/ledger/shell/mod.rs
index acf2e103a0..144be51299 100644
--- a/apps/src/lib/node/ledger/shell/mod.rs
+++ b/apps/src/lib/node/ledger/shell/mod.rs
@@ -22,7 +22,6 @@ use std::path::{Path, PathBuf};
use std::rc::Rc;
use borsh::{BorshDeserialize, BorshSerialize};
-use namada::core::types::hash::Hash;
use namada::ledger::events::log::EventLog;
use namada::ledger::events::Event;
use namada::ledger::gas::BlockGasMeter;
@@ -36,10 +35,10 @@ use namada::ledger::storage::{
use namada::ledger::storage_api::{self, StorageRead, StorageWrite};
use namada::ledger::{ibc, pos, protocol, replay_protection};
use namada::proof_of_stake::{self, read_pos_params, slash};
-use namada::proto::{self, Tx};
+use namada::proto::{self, Section, Tx};
use namada::types::address::{masp, masp_tx_key, Address};
use namada::types::chain::ChainId;
-use namada::types::internal::WrapperTxInQueue;
+use namada::types::internal::TxInQueue;
use namada::types::key::*;
use namada::types::storage::{BlockHeight, Key, TxIndex};
use namada::types::time::{DateTimeUtc, TimeZone, Utc};
@@ -47,8 +46,8 @@ use namada::types::token::{self};
#[cfg(not(feature = "mainnet"))]
use namada::types::transaction::MIN_FEE;
use namada::types::transaction::{
- hash_tx, process_tx, verify_decrypted_correctly, AffineCurve, DecryptedTx,
- EllipticCurve, PairingEngine, TxType, WrapperTx,
+ hash_tx, verify_decrypted_correctly, AffineCurve, DecryptedTx,
+ EllipticCurve, PairingEngine, TxType,
};
use namada::types::{address, hash};
use namada::vm::wasm::{TxCache, VpCache};
@@ -414,7 +413,7 @@ where
/// Iterate over the wrapper txs in order
#[allow(dead_code)]
- fn iter_tx_queue(&mut self) -> impl Iterator- {
+ fn iter_tx_queue(&mut self) -> impl Iterator
- {
self.wl_storage.storage.tx_queue.iter()
}
@@ -656,19 +655,20 @@ where
/// block construction and validation
pub fn replay_protection_checks(
&self,
- wrapper: &WrapperTx,
+ wrapper: &Tx,
tx_bytes: &[u8],
temp_wl_storage: &mut TempWlStorage,
) -> Result<()> {
- let inner_hash_key =
- replay_protection::get_tx_hash_key(&wrapper.tx_hash);
+ let inner_tx_hash =
+ wrapper.clone().update_header(TxType::Raw).header_hash();
+ let inner_hash_key = replay_protection::get_tx_hash_key(&inner_tx_hash);
if temp_wl_storage
.has_key(&inner_hash_key)
.expect("Error while checking inner tx hash key in storage")
{
return Err(Error::ReplayAttempt(format!(
"Inner transaction hash {} already in storage",
- &wrapper.tx_hash
+ &inner_tx_hash,
)));
}
@@ -679,7 +679,7 @@ where
let tx =
Tx::try_from(tx_bytes).expect("Deserialization shouldn't fail");
- let wrapper_hash = Hash(tx.unsigned_hash());
+ let wrapper_hash = tx.header_hash();
let wrapper_hash_key =
replay_protection::get_tx_hash_key(&wrapper_hash);
if temp_wl_storage
@@ -728,17 +728,17 @@ where
};
// Tx chain id
- if tx.chain_id != self.chain_id {
+ if tx.header.chain_id != self.chain_id {
response.code = ErrorCodes::InvalidChainId.into();
response.log = format!(
"Tx carries a wrong chain id: expected {}, found {}",
- self.chain_id, tx.chain_id
+ self.chain_id, tx.header.chain_id
);
return response;
}
// Tx expiration
- if let Some(exp) = tx.expiration {
+ if let Some(exp) = tx.header.expiration {
let last_block_timestamp = self.get_block_timestamp(None);
if last_block_timestamp > exp {
@@ -752,8 +752,8 @@ where
}
// Tx signature check
- let tx_type = match process_tx(tx) {
- Ok(ty) => ty,
+ let tx_type = match tx.validate_header() {
+ Ok(()) => tx.header(),
Err(msg) => {
response.code = ErrorCodes::InvalidSig.into();
response.log = msg.to_string();
@@ -762,10 +762,13 @@ where
};
// Tx type check
- if let TxType::Wrapper(wrapper) = tx_type {
+ if let TxType::Wrapper(wrapper) = tx_type.tx_type {
// Replay protection check
+ let mut inner_tx = tx;
+ inner_tx.update_header(TxType::Raw);
+ let inner_tx_hash = &inner_tx.header_hash();
let inner_hash_key =
- replay_protection::get_tx_hash_key(&wrapper.tx_hash);
+ replay_protection::get_tx_hash_key(inner_tx_hash);
if self
.wl_storage
.storage
@@ -777,14 +780,14 @@ where
response.log = format!(
"Inner transaction hash {} already in storage, replay \
attempt",
- wrapper.tx_hash
+ inner_tx_hash
);
return response;
}
let tx =
Tx::try_from(tx_bytes).expect("Deserialization shouldn't fail");
- let wrapper_hash = hash::Hash(tx.unsigned_hash());
+ let wrapper_hash = hash::Hash(tx.header_hash().0);
let wrapper_hash_key =
replay_protection::get_tx_hash_key(&wrapper_hash);
if self
@@ -848,13 +851,6 @@ where
let mut tx_wasm_cache = self.tx_wasm_cache.read_only();
match Tx::try_from(tx_bytes) {
Ok(tx) => {
- let tx = TxType::Decrypted(DecryptedTx::Decrypted {
- tx,
- #[cfg(not(feature = "mainnet"))]
- // To be able to dry-run testnet faucet withdrawal, pretend
- // that we got a valid PoW
- has_valid_pow: true,
- });
match protocol::apply_tx(
tx,
tx_bytes.len(),
@@ -985,6 +981,7 @@ mod test_utils {
use namada::ledger::storage::mockdb::MockDB;
use namada::ledger::storage::{update_allowed_conversions, Sha256Hasher};
+ use namada::proto::{Code, Data};
use namada::types::chain::ChainId;
use namada::types::hash::Hash;
use namada::types::key::*;
@@ -1141,16 +1138,12 @@ mod test_utils {
/// Add a wrapper tx to the queue of txs to be decrypted
/// in the current block proposal
#[cfg(test)]
- pub fn enqueue_tx(&mut self, wrapper: WrapperTx) {
- self.shell
- .wl_storage
- .storage
- .tx_queue
- .push(WrapperTxInQueue {
- tx: wrapper,
- #[cfg(not(feature = "mainnet"))]
- has_valid_pow: false,
- });
+ pub fn enqueue_tx(&mut self, tx: Tx) {
+ self.shell.wl_storage.storage.tx_queue.push(TxInQueue {
+ tx,
+ #[cfg(not(feature = "mainnet"))]
+ has_valid_pow: false,
+ });
}
}
@@ -1224,13 +1217,7 @@ mod test_utils {
.expect("begin_block failed");
let keypair = gen_keypair();
// enqueue a wrapper tx
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let wrapper = WrapperTx::new(
+ let mut wrapper = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: 0.into(),
token: native_token,
@@ -1238,12 +1225,15 @@ mod test_utils {
&keypair,
Epoch(0),
0.into(),
- tx,
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- );
- shell.wl_storage.storage.tx_queue.push(WrapperTxInQueue {
+ ))));
+ wrapper.header.chain_id = shell.chain_id.clone();
+ wrapper.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ wrapper.set_data(Data::new("transaction data".as_bytes().to_owned()));
+ wrapper.encrypt(&Default::default());
+
+ shell.wl_storage.storage.tx_queue.push(TxInQueue {
tx: wrapper,
#[cfg(not(feature = "mainnet"))]
has_valid_pow: false,
@@ -1281,7 +1271,7 @@ mod test_utils {
#[cfg(test)]
mod test_mempool_validate {
use namada::proof_of_stake::Epoch;
- use namada::proto::SignedTxData;
+ use namada::proto::{Code, Data, Section, Signature, Tx};
use namada::types::transaction::{Fee, WrapperTx};
use super::test_utils::TestShell;
@@ -1294,41 +1284,23 @@ mod test_mempool_validate {
let keypair = super::test_utils::gen_keypair();
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
-
- let mut wrapper = WrapperTx::new(
- Fee {
- amount: 100.into(),
- token: shell.wl_storage.storage.native_token.clone(),
- },
- &keypair,
- Epoch(0),
- 0.into(),
- tx,
- Default::default(),
- #[cfg(not(feature = "mainnet"))]
- None,
- )
- .sign(&keypair, shell.chain_id.clone(), None)
- .expect("Wrapper signing failed");
-
- let unsigned_wrapper = if let Some(Ok(SignedTxData {
- data: Some(data),
- sig: _,
- })) = wrapper
- .data
- .take()
- .map(|data| SignedTxData::try_from_slice(&data[..]))
- {
- Tx::new(vec![], Some(data), shell.chain_id.clone(), None)
- } else {
- panic!("Test failed")
- };
+ let mut unsigned_wrapper =
+ Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
+ Fee {
+ amount: 100.into(),
+ token: shell.wl_storage.storage.native_token.clone(),
+ },
+ &keypair,
+ Epoch(0),
+ 0.into(),
+ #[cfg(not(feature = "mainnet"))]
+ None,
+ ))));
+ unsigned_wrapper.header.chain_id = shell.chain_id.clone();
+ unsigned_wrapper.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ unsigned_wrapper
+ .set_data(Data::new("transaction data".as_bytes().to_owned()));
+ unsigned_wrapper.encrypt(&Default::default());
let mut result = shell.mempool_validate(
unsigned_wrapper.to_bytes().as_ref(),
@@ -1349,67 +1321,33 @@ mod test_mempool_validate {
let keypair = super::test_utils::gen_keypair();
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
-
- let mut wrapper = WrapperTx::new(
- Fee {
- amount: 100.into(),
- token: shell.wl_storage.storage.native_token.clone(),
- },
+ let mut invalid_wrapper =
+ Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
+ Fee {
+ amount: 100.into(),
+ token: shell.wl_storage.storage.native_token.clone(),
+ },
+ &keypair,
+ Epoch(0),
+ 0.into(),
+ #[cfg(not(feature = "mainnet"))]
+ None,
+ ))));
+ invalid_wrapper.header.chain_id = shell.chain_id.clone();
+ invalid_wrapper.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ invalid_wrapper
+ .set_data(Data::new("transaction data".as_bytes().to_owned()));
+ invalid_wrapper.add_section(Section::Signature(Signature::new(
+ &invalid_wrapper.header_hash(),
&keypair,
- Epoch(0),
- 0.into(),
- tx,
- Default::default(),
- #[cfg(not(feature = "mainnet"))]
- None,
- )
- .sign(&keypair, shell.chain_id.clone(), None)
- .expect("Wrapper signing failed");
-
- let invalid_wrapper = if let Some(Ok(SignedTxData {
- data: Some(data),
- sig,
- })) = wrapper
- .data
- .take()
- .map(|data| SignedTxData::try_from_slice(&data[..]))
- {
- let mut new_wrapper = if let TxType::Wrapper(wrapper) =
- ::deserialize(&mut data.as_ref())
- .expect("Test failed")
- {
- wrapper
- } else {
- panic!("Test failed")
- };
+ )));
+ invalid_wrapper.encrypt(&Default::default());
- // we mount a malleability attack to try and remove the fee
- new_wrapper.fee.amount = 0.into();
- let new_data = TxType::Wrapper(new_wrapper)
- .try_to_vec()
- .expect("Test failed");
- Tx::new(
- vec![],
- Some(
- SignedTxData {
- sig,
- data: Some(new_data),
- }
- .try_to_vec()
- .expect("Test failed"),
- ),
- shell.chain_id.clone(),
- None,
- )
- } else {
- panic!("Test failed");
- };
+ // we mount a malleability attack to try and remove the fee
+ let mut new_wrapper =
+ invalid_wrapper.header().wrapper().expect("Test failed");
+ new_wrapper.fee.amount = 0.into();
+ invalid_wrapper.update_header(TxType::Wrapper(Box::new(new_wrapper)));
let mut result = shell.mempool_validate(
invalid_wrapper.to_bytes().as_ref(),
@@ -1429,12 +1367,9 @@ mod test_mempool_validate {
let (shell, _) = TestShell::new();
// Test Raw TxType
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- None,
- shell.chain_id.clone(),
- None,
- );
+ let mut tx = Tx::new(TxType::Raw);
+ tx.header.chain_id = shell.chain_id.clone();
+ tx.set_code(Code::new("wasm_code".as_bytes().to_owned()));
let result = shell.mempool_validate(
tx.to_bytes().as_ref(),
@@ -1452,14 +1387,7 @@ mod test_mempool_validate {
let keypair = super::test_utils::gen_keypair();
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
-
- let wrapper = WrapperTx::new(
+ let mut wrapper = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: 100.into(),
token: shell.wl_storage.storage.native_token.clone(),
@@ -1467,27 +1395,26 @@ mod test_mempool_validate {
&keypair,
Epoch(0),
0.into(),
- tx,
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- )
- .sign(&keypair, shell.chain_id.clone(), None)
- .expect("Wrapper signing failed");
-
- let tx_type = match process_tx(wrapper.clone()).expect("Test failed") {
- TxType::Wrapper(t) => t,
- _ => panic!("Test failed"),
- };
+ ))));
+ wrapper.header.chain_id = shell.chain_id.clone();
+ wrapper.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ wrapper.set_data(Data::new("transaction data".as_bytes().to_owned()));
+ wrapper.add_section(Section::Signature(Signature::new(
+ &wrapper.header_hash(),
+ &keypair,
+ )));
+ wrapper.encrypt(&Default::default());
// Write wrapper hash to storage
- let wrapper_hash = hash::Hash(wrapper.unsigned_hash());
+ let wrapper_hash = wrapper.header_hash();
let wrapper_hash_key =
replay_protection::get_tx_hash_key(&wrapper_hash);
shell
.wl_storage
.storage
- .write(&wrapper_hash_key, &wrapper_hash)
+ .write(&wrapper_hash_key, wrapper_hash)
.expect("Test failed");
// Try wrapper tx replay attack
@@ -1519,13 +1446,14 @@ mod test_mempool_validate {
)
);
+ let inner_tx_hash =
+ wrapper.clone().update_header(TxType::Raw).header_hash();
// Write inner hash in storage
- let inner_hash_key =
- replay_protection::get_tx_hash_key(&tx_type.tx_hash);
+ let inner_hash_key = replay_protection::get_tx_hash_key(&inner_tx_hash);
shell
.wl_storage
.storage
- .write(&inner_hash_key, &tx_type.tx_hash)
+ .write(&inner_hash_key, inner_tx_hash)
.expect("Test failed");
// Try inner tx replay attack
@@ -1538,7 +1466,7 @@ mod test_mempool_validate {
result.log,
format!(
"Inner transaction hash {} already in storage, replay attempt",
- tx_type.tx_hash
+ inner_tx_hash
)
);
@@ -1551,7 +1479,7 @@ mod test_mempool_validate {
result.log,
format!(
"Inner transaction hash {} already in storage, replay attempt",
- tx_type.tx_hash
+ inner_tx_hash
)
)
}
@@ -1564,13 +1492,14 @@ mod test_mempool_validate {
let keypair = super::test_utils::gen_keypair();
let wrong_chain_id = ChainId("Wrong chain id".to_string());
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- wrong_chain_id.clone(),
- None,
- )
- .sign(&keypair);
+ let mut tx = Tx::new(TxType::Raw);
+ tx.header.chain_id = wrong_chain_id.clone();
+ tx.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ tx.set_data(Data::new("transaction data".as_bytes().to_owned()));
+ tx.add_section(Section::Signature(Signature::new(
+ &tx.header_hash(),
+ &keypair,
+ )));
let result = shell.mempool_validate(
tx.to_bytes().as_ref(),
@@ -1593,13 +1522,15 @@ mod test_mempool_validate {
let keypair = super::test_utils::gen_keypair();
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- Some(DateTimeUtc::now()),
- )
- .sign(&keypair);
+ let mut tx = Tx::new(TxType::Raw);
+ tx.header.expiration = Some(DateTimeUtc::now());
+ tx.header.chain_id = shell.chain_id.clone();
+ tx.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ tx.set_data(Data::new("transaction data".as_bytes().to_owned()));
+ tx.add_section(Section::Signature(Signature::new(
+ &tx.header_hash(),
+ &keypair,
+ )));
let result = shell.mempool_validate(
tx.to_bytes().as_ref(),
diff --git a/apps/src/lib/node/ledger/shell/prepare_proposal.rs b/apps/src/lib/node/ledger/shell/prepare_proposal.rs
index 41d05fea5d..7d126a5218 100644
--- a/apps/src/lib/node/ledger/shell/prepare_proposal.rs
+++ b/apps/src/lib/node/ledger/shell/prepare_proposal.rs
@@ -4,11 +4,12 @@ use namada::core::hints;
use namada::ledger::storage::{DBIter, StorageHasher, TempWlStorage, DB};
use namada::proof_of_stake::pos_queries::PosQueries;
use namada::proto::Tx;
-use namada::types::internal::WrapperTxInQueue;
+use namada::types::internal::TxInQueue;
use namada::types::time::DateTimeUtc;
-use namada::types::transaction::tx_types::TxType;
use namada::types::transaction::wrapper::wrapper_tx::PairingEngine;
-use namada::types::transaction::{AffineCurve, DecryptedTx, EllipticCurve};
+use namada::types::transaction::{
+ AffineCurve, DecryptedTx, EllipticCurve, TxType,
+};
use super::super::*;
#[allow(unused_imports)]
@@ -21,8 +22,10 @@ use super::block_space_alloc::{AllocFailure, BlockSpaceAllocator};
#[cfg(feature = "abcipp")]
use crate::facade::tendermint_proto::abci::ExtendedCommitInfo;
use crate::facade::tendermint_proto::abci::RequestPrepareProposal;
+#[cfg(feature = "abcipp")]
+use crate::facade::tendermint_proto::abci::{tx_record::TxAction, TxRecord};
use crate::facade::tendermint_proto::google::protobuf::Timestamp;
-use crate::node::ledger::shell::{process_tx, ShellMode};
+use crate::node::ledger::shell::ShellMode;
use crate::node::ledger::shims::abcipp_shim_types::shim::{response, TxBytes};
impl Shell
@@ -45,7 +48,6 @@ where
let txs = if let ShellMode::Validator { .. } = self.mode {
// start counting allotted space for txs
let alloc = self.get_encrypted_txs_allocator();
-
// add encrypted txs
let (encrypted_txs, alloc) = self.build_encrypted_txs(
alloc,
@@ -140,13 +142,11 @@ where
// If tx doesn't have an expiration it is valid. If time cannot be
// retrieved from block default to last block datetime which has
// already been checked by mempool_validate, so it's valid
- if let (Some(block_time), Some(exp)) = (block_time.as_ref(), &tx.expiration) {
+ if let (Some(block_time), Some(exp)) = (block_time.as_ref(), &tx.header.expiration) {
if block_time > exp { return None }
}
- if let Ok(TxType::Wrapper(ref wrapper)) = process_tx(tx) {
- if self.replay_protection_checks(wrapper, tx_bytes.as_slice(), &mut temp_wl_storage).is_ok() {
- return Some(tx_bytes.clone())
- }
+ if tx.validate_header().is_ok() && tx.header().wrapper().is_some() && self.replay_protection_checks(&tx, tx_bytes.as_slice(), &mut temp_wl_storage).is_ok() {
+ return Some(tx_bytes.clone());
}
}
None
@@ -202,7 +202,6 @@ where
// TODO: This should not be hardcoded
let privkey =
::G2Affine::prime_subgroup_generator();
-
let pos_queries = self.wl_storage.pos_queries();
let txs = self
.wl_storage
@@ -210,20 +209,30 @@ where
.tx_queue
.iter()
.map(
- |WrapperTxInQueue {
+ |TxInQueue {
tx,
#[cfg(not(feature = "mainnet"))]
has_valid_pow,
- }| {
- Tx::from(match tx.decrypt(privkey) {
- Ok(tx) => DecryptedTx::Decrypted {
- tx,
- #[cfg(not(feature = "mainnet"))]
- has_valid_pow: *has_valid_pow,
+ }| {
+ let mut tx = tx.clone();
+ match tx.decrypt(privkey).ok()
+ {
+ Some(()) => {
+ tx.update_header(TxType::Decrypted(DecryptedTx::Decrypted {
+ #[cfg(not(feature = "mainnet"))]
+ has_valid_pow: *has_valid_pow,
+ }));
+ tx
+ },
+ // An absent or undecryptable inner_tx are both
+ // treated as undecryptable
+ None => {
+ tx.update_header(TxType::Decrypted(
+ DecryptedTx::Undecryptable
+ ));
+ tx
},
- _ => DecryptedTx::Undecryptable(tx.clone()),
- })
- .to_bytes()
+ }.to_bytes()
},
)
// TODO: make sure all decrypted txs are accepted
@@ -280,7 +289,7 @@ mod test_prepare_proposal {
use borsh::BorshSerialize;
use namada::ledger::replay_protection;
use namada::proof_of_stake::Epoch;
- use namada::types::hash::Hash;
+ use namada::proto::{Code, Data, Header, Section, Signature};
use namada::types::transaction::{Fee, WrapperTx};
use super::*;
@@ -292,12 +301,10 @@ mod test_prepare_proposal {
#[test]
fn test_prepare_proposal_rejects_non_wrapper_tx() {
let (shell, _) = test_utils::setup(1);
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction_data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
+ let mut tx = Tx::new(TxType::Decrypted(DecryptedTx::Decrypted {
+ has_valid_pow: true,
+ }));
+ tx.header.chain_id = shell.chain_id.clone();
let req = RequestPrepareProposal {
txs: vec![tx.to_bytes()],
..Default::default()
@@ -312,36 +319,23 @@ mod test_prepare_proposal {
fn test_error_in_processing_tx() {
let (shell, _) = test_utils::setup(1);
let keypair = gen_keypair();
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction_data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
// an unsigned wrapper will cause an error in processing
- let wrapper = Tx::new(
- "".as_bytes().to_owned(),
- Some(
- WrapperTx::new(
- Fee {
- amount: 0.into(),
- token: shell.wl_storage.storage.native_token.clone(),
- },
- &keypair,
- Epoch(0),
- 0.into(),
- tx,
- Default::default(),
- #[cfg(not(feature = "mainnet"))]
- None,
- )
- .try_to_vec()
- .expect("Test failed"),
- ),
- shell.chain_id.clone(),
+ let mut wrapper = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
+ Fee {
+ amount: 0.into(),
+ token: shell.wl_storage.storage.native_token.clone(),
+ },
+ &keypair,
+ Epoch(0),
+ 0.into(),
+ #[cfg(not(feature = "mainnet"))]
None,
- )
- .to_bytes();
+ ))));
+ wrapper.header.chain_id = shell.chain_id.clone();
+ wrapper.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ wrapper.set_data(Data::new("transaction_data".as_bytes().to_owned()));
+ wrapper.encrypt(&Default::default());
+ let wrapper = wrapper.to_bytes();
#[allow(clippy::redundant_clone)]
let req = RequestPrepareProposal {
txs: vec![wrapper.clone()],
@@ -367,18 +361,7 @@ mod test_prepare_proposal {
// create a request with two new wrappers from mempool and
// two wrappers from the previous block to be decrypted
for i in 0..2 {
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some(format!("transaction data: {}", i).as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- expected_decrypted.push(Tx::from(DecryptedTx::Decrypted {
- tx: tx.clone(),
- #[cfg(not(feature = "mainnet"))]
- has_valid_pow: false,
- }));
- let wrapper_tx = WrapperTx::new(
+ let mut tx = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: 0.into(),
token: shell.wl_storage.storage.native_token.clone(),
@@ -386,39 +369,58 @@ mod test_prepare_proposal {
&keypair,
Epoch(0),
0.into(),
- tx,
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- );
- let wrapper = wrapper_tx
- .sign(&keypair, shell.chain_id.clone(), None)
- .expect("Test failed");
- shell.enqueue_tx(wrapper_tx);
- expected_wrapper.push(wrapper.clone());
- req.txs.push(wrapper.to_bytes());
+ ))));
+ tx.header.chain_id = shell.chain_id.clone();
+ tx.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ tx.set_data(Data::new(
+ format!("transaction data: {}", i).as_bytes().to_owned(),
+ ));
+ tx.add_section(Section::Signature(Signature::new(
+ &tx.header_hash(),
+ &keypair,
+ )));
+ tx.encrypt(&Default::default());
+
+ shell.enqueue_tx(tx.clone());
+ expected_wrapper.push(tx.clone());
+ req.txs.push(tx.to_bytes());
+ tx.update_header(TxType::Decrypted(DecryptedTx::Decrypted {
+ #[cfg(not(feature = "mainnet"))]
+ has_valid_pow: false,
+ }));
+ expected_decrypted.push(tx.clone());
}
- let expected_txs: Vec = expected_wrapper
+ // we extract the inner data from the txs for testing
+ // equality since otherwise changes in timestamps would
+ // fail the test
+ let expected_txs: Vec = expected_wrapper
.into_iter()
.chain(expected_decrypted.into_iter())
- // we extract the inner data from the txs for testing
- // equality since otherwise changes in timestamps would
- // fail the test
- .map(|tx| tx.data.expect("Test failed"))
+ .map(|tx| tx.header)
.collect();
- let received: Vec = shell
+ let received: Vec = shell
.prepare_proposal(req)
.txs
.into_iter()
.map(|tx_bytes| {
Tx::try_from(tx_bytes.as_slice())
.expect("Test failed")
- .data
- .expect("Test failed")
+ .header
})
.collect();
// check that the order of the txs is correct
- assert_eq!(received, expected_txs);
+ assert_eq!(
+ received
+ .iter()
+ .map(|x| x.try_to_vec().unwrap())
+ .collect::>(),
+ expected_txs
+ .iter()
+ .map(|x| x.try_to_vec().unwrap())
+ .collect::>(),
+ );
}
/// Test that if the unsigned wrapper tx hash is known (replay attack), the
@@ -428,14 +430,7 @@ mod test_prepare_proposal {
let (mut shell, _) = test_utils::setup(1);
let keypair = crate::wallet::defaults::daewon_keypair();
-
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let wrapper = WrapperTx::new(
+ let mut wrapper = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: 0.into(),
token: shell.wl_storage.storage.native_token.clone(),
@@ -443,17 +438,20 @@ mod test_prepare_proposal {
&keypair,
Epoch(0),
0.into(),
- tx,
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- );
- let signed = wrapper
- .sign(&keypair, shell.chain_id.clone(), None)
- .expect("Test failed");
+ ))));
+ wrapper.header.chain_id = shell.chain_id.clone();
+ wrapper.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ wrapper.set_data(Data::new("transaction data".as_bytes().to_owned()));
+ wrapper.add_section(Section::Signature(Signature::new(
+ &wrapper.header_hash(),
+ &keypair,
+ )));
+ wrapper.encrypt(&Default::default());
// Write wrapper hash to storage
- let wrapper_unsigned_hash = Hash(signed.unsigned_hash());
+ let wrapper_unsigned_hash = wrapper.header_hash();
let hash_key =
replay_protection::get_tx_hash_key(&wrapper_unsigned_hash);
shell
@@ -463,7 +461,7 @@ mod test_prepare_proposal {
.expect("Test failed");
let req = RequestPrepareProposal {
- txs: vec![signed.to_bytes()],
+ txs: vec![wrapper.to_bytes()],
..Default::default()
};
@@ -471,7 +469,7 @@ mod test_prepare_proposal {
shell.prepare_proposal(req).txs.into_iter().map(|tx_bytes| {
Tx::try_from(tx_bytes.as_slice())
.expect("Test failed")
- .data
+ .data()
.expect("Test failed")
});
assert_eq!(received.len(), 0);
@@ -484,14 +482,7 @@ mod test_prepare_proposal {
let (shell, _) = test_utils::setup(1);
let keypair = crate::wallet::defaults::daewon_keypair();
-
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let wrapper = WrapperTx::new(
+ let mut wrapper = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: 0.into(),
token: shell.wl_storage.storage.native_token.clone(),
@@ -499,23 +490,27 @@ mod test_prepare_proposal {
&keypair,
Epoch(0),
0.into(),
- tx,
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- );
- let signed = wrapper
- .sign(&keypair, shell.chain_id.clone(), None)
- .expect("Test failed");
+ ))));
+ wrapper.header.chain_id = shell.chain_id.clone();
+ wrapper.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ wrapper.set_data(Data::new("transaction data".as_bytes().to_owned()));
+ wrapper.add_section(Section::Signature(Signature::new(
+ &wrapper.header_hash(),
+ &keypair,
+ )));
+ wrapper.encrypt(&Default::default());
+
let req = RequestPrepareProposal {
- txs: vec![signed.to_bytes(); 2],
+ txs: vec![wrapper.to_bytes(); 2],
..Default::default()
};
let received =
shell.prepare_proposal(req).txs.into_iter().map(|tx_bytes| {
Tx::try_from(tx_bytes.as_slice())
.expect("Test failed")
- .data
+ .data()
.expect("Test failed")
});
assert_eq!(received.len(), 1);
@@ -528,14 +523,7 @@ mod test_prepare_proposal {
let (mut shell, _) = test_utils::setup(1);
let keypair = crate::wallet::defaults::daewon_keypair();
-
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let wrapper = WrapperTx::new(
+ let mut wrapper = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: 0.into(),
token: shell.wl_storage.storage.native_token.clone(),
@@ -543,15 +531,19 @@ mod test_prepare_proposal {
&keypair,
Epoch(0),
0.into(),
- tx,
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- );
- let inner_unsigned_hash = wrapper.tx_hash.clone();
- let signed = wrapper
- .sign(&keypair, shell.chain_id.clone(), None)
- .expect("Test failed");
+ ))));
+ wrapper.header.chain_id = shell.chain_id.clone();
+ wrapper.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ wrapper.set_data(Data::new("transaction data".as_bytes().to_owned()));
+ wrapper.add_section(Section::Signature(Signature::new(
+ &wrapper.header_hash(),
+ &keypair,
+ )));
+ wrapper.encrypt(&Default::default());
+ let inner_unsigned_hash =
+ wrapper.clone().update_header(TxType::Raw).header_hash();
// Write inner hash to storage
let hash_key = replay_protection::get_tx_hash_key(&inner_unsigned_hash);
@@ -562,7 +554,7 @@ mod test_prepare_proposal {
.expect("Test failed");
let req = RequestPrepareProposal {
- txs: vec![signed.to_bytes()],
+ txs: vec![wrapper.to_bytes()],
..Default::default()
};
@@ -570,7 +562,7 @@ mod test_prepare_proposal {
shell.prepare_proposal(req).txs.into_iter().map(|tx_bytes| {
Tx::try_from(tx_bytes.as_slice())
.expect("Test failed")
- .data
+ .data()
.expect("Test failed")
});
assert_eq!(received.len(), 0);
@@ -584,14 +576,7 @@ mod test_prepare_proposal {
let keypair = crate::wallet::defaults::daewon_keypair();
let keypair_2 = crate::wallet::defaults::daewon_keypair();
-
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let wrapper = WrapperTx::new(
+ let mut wrapper = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: 0.into(),
token: shell.wl_storage.storage.native_token.clone(),
@@ -599,41 +584,51 @@ mod test_prepare_proposal {
&keypair,
Epoch(0),
0.into(),
- tx.clone(),
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- );
- let signed = wrapper
- .sign(&keypair, shell.chain_id.clone(), None)
- .expect("Test failed");
+ ))));
+ wrapper.header.chain_id = shell.chain_id.clone();
+ let tx_code = Code::new("wasm_code".as_bytes().to_owned());
+ wrapper.set_code(tx_code.clone());
+ let tx_data = Data::new("transaction data".as_bytes().to_owned());
+ wrapper.set_data(tx_data.clone());
+ wrapper.add_section(Section::Signature(Signature::new(
+ &wrapper.header_hash(),
+ &keypair,
+ )));
+ wrapper.encrypt(&Default::default());
- let new_wrapper = WrapperTx::new(
- Fee {
- amount: 0.into(),
- token: shell.wl_storage.storage.native_token.clone(),
- },
- &keypair_2,
- Epoch(0),
- 0.into(),
- tx,
- Default::default(),
- #[cfg(not(feature = "mainnet"))]
- None,
- );
- let new_signed = new_wrapper
- .sign(&keypair, shell.chain_id.clone(), None)
- .expect("Test failed");
+ let mut new_wrapper =
+ Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
+ Fee {
+ amount: 0.into(),
+ token: shell.wl_storage.storage.native_token.clone(),
+ },
+ &keypair_2,
+ Epoch(0),
+ 0.into(),
+ #[cfg(not(feature = "mainnet"))]
+ None,
+ ))));
+ new_wrapper.header.chain_id = shell.chain_id.clone();
+ new_wrapper.header.timestamp = wrapper.header.timestamp;
+ new_wrapper.set_code(tx_code);
+ new_wrapper.set_data(tx_data);
+ new_wrapper.add_section(Section::Signature(Signature::new(
+ &new_wrapper.header_hash(),
+ &keypair,
+ )));
+ new_wrapper.encrypt(&Default::default());
let req = RequestPrepareProposal {
- txs: vec![signed.to_bytes(), new_signed.to_bytes()],
+ txs: vec![wrapper.to_bytes(), new_wrapper.to_bytes()],
..Default::default()
};
let received =
shell.prepare_proposal(req).txs.into_iter().map(|tx_bytes| {
Tx::try_from(tx_bytes.as_slice())
.expect("Test failed")
- .data
+ .data()
.expect("Test failed")
});
assert_eq!(received.len(), 1);
@@ -645,28 +640,28 @@ mod test_prepare_proposal {
let (shell, _) = test_utils::setup(1);
let keypair = gen_keypair();
let tx_time = DateTimeUtc::now();
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let wrapper_tx = WrapperTx::new(
- Fee {
- amount: 0.into(),
- token: shell.wl_storage.storage.native_token.clone(),
- },
+ let mut wrapper_tx =
+ Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
+ Fee {
+ amount: 0.into(),
+ token: shell.wl_storage.storage.native_token.clone(),
+ },
+ &keypair,
+ Epoch(0),
+ 0.into(),
+ #[cfg(not(feature = "mainnet"))]
+ None,
+ ))));
+ wrapper_tx.header.chain_id = shell.chain_id.clone();
+ wrapper_tx.header.expiration = Some(tx_time);
+ wrapper_tx.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ wrapper_tx
+ .set_data(Data::new("transaction data".as_bytes().to_owned()));
+ wrapper_tx.add_section(Section::Signature(Signature::new(
+ &wrapper_tx.header_hash(),
&keypair,
- Epoch(0),
- 0.into(),
- tx,
- Default::default(),
- #[cfg(not(feature = "mainnet"))]
- None,
- );
- let wrapper = wrapper_tx
- .sign(&keypair, shell.chain_id.clone(), Some(tx_time))
- .expect("Test failed");
+ )));
+ wrapper_tx.encrypt(&Default::default());
let time = DateTimeUtc::now();
let block_time =
@@ -675,7 +670,7 @@ mod test_prepare_proposal {
nanos: time.0.timestamp_subsec_nanos() as i32,
};
let req = RequestPrepareProposal {
- txs: vec![wrapper.to_bytes()],
+ txs: vec![wrapper_tx.to_bytes()],
max_tx_bytes: 0,
time: Some(block_time),
..Default::default()
diff --git a/apps/src/lib/node/ledger/shell/process_proposal.rs b/apps/src/lib/node/ledger/shell/process_proposal.rs
index 6ad5a71048..2837ac6600 100644
--- a/apps/src/lib/node/ledger/shell/process_proposal.rs
+++ b/apps/src/lib/node/ledger/shell/process_proposal.rs
@@ -6,7 +6,7 @@ use namada::core::hints;
use namada::core::ledger::storage::WlStorage;
use namada::ledger::storage::TempWlStorage;
use namada::proof_of_stake::pos_queries::PosQueries;
-use namada::types::internal::WrapperTxInQueue;
+use namada::types::internal::TxInQueue;
use super::*;
use crate::facade::tendermint_proto::abci::response_process_proposal::ProposalStatus;
@@ -193,7 +193,7 @@ where
pub(crate) fn process_single_tx<'a>(
&self,
tx_bytes: &[u8],
- tx_queue_iter: &mut impl Iterator
- ,
+ tx_queue_iter: &mut impl Iterator
- ,
metadata: &mut ValidationMeta,
temp_wl_storage: &mut TempWlStorage,
block_time: DateTimeUtc,
@@ -229,17 +229,17 @@ where
})
},
|tx| {
- let tx_chain_id = tx.chain_id.clone();
- let tx_expiration = tx.expiration;
- let tx_type = process_tx(tx).map_err(|err| {
+ let tx_chain_id = tx.header.chain_id.clone();
+ let tx_expiration = tx.header.expiration;
+ if let Err(err) = tx.validate_header() {
// This occurs if the wrapper / protocol tx signature is
// invalid
- TxResult {
+ return Err(TxResult {
code: ErrorCodes::InvalidSig.into(),
info: err.to_string(),
- }
- })?;
- Ok((tx_chain_id, tx_expiration, tx_type))
+ });
+ }
+ Ok((tx_chain_id, tx_expiration, tx))
},
);
let (tx_chain_id, tx_expiration, tx) = match maybe_tx {
@@ -250,9 +250,15 @@ where
// TODO: This should not be hardcoded
let privkey = ::G2Affine::prime_subgroup_generator();
- match tx {
+ if let Err(err) = tx.validate_header() {
+ return TxResult {
+ code: ErrorCodes::InvalidSig.into(),
+ info: err.to_string(),
+ };
+ }
+ match tx.header().tx_type {
// If it is a raw transaction, we do no further validation
- TxType::Raw(_) => TxResult {
+ TxType::Raw => TxResult {
code: ErrorCodes::InvalidTx.into(),
info: "Transaction rejected: Non-encrypted transactions are \
not supported"
@@ -290,11 +296,19 @@ where
.into(),
}
}
- TxType::Decrypted(tx) => {
+ TxType::Decrypted(tx_header) => {
metadata.has_decrypted_txs = true;
match tx_queue_iter.next() {
Some(wrapper) => {
- if wrapper.tx.tx_hash != tx.hash_commitment() {
+ let mut inner_tx = tx;
+ inner_tx.update_header(TxType::Raw);
+ if wrapper
+ .tx
+ .clone()
+ .update_header(TxType::Raw)
+ .header_hash()
+ != inner_tx.header_hash()
+ {
TxResult {
code: ErrorCodes::InvalidOrder.into(),
info: "Process proposal rejected a decrypted \
@@ -302,41 +316,38 @@ where
determined in the previous block"
.into(),
}
- } else if verify_decrypted_correctly(&tx, privkey) {
- if let DecryptedTx::Decrypted {
- tx,
- has_valid_pow: _,
- } = tx
- {
- // Tx chain id
- if tx.chain_id != self.chain_id {
+ } else if verify_decrypted_correctly(
+ &tx_header,
+ wrapper.tx.clone(),
+ privkey,
+ ) {
+ // Tx chain id
+ if wrapper.tx.header.chain_id != self.chain_id {
+ return TxResult {
+ code: ErrorCodes::InvalidDecryptedChainId
+ .into(),
+ info: format!(
+ "Decrypted tx carries a wrong chain \
+ id: expected {}, found {}",
+ self.chain_id,
+ wrapper.tx.header.chain_id
+ ),
+ };
+ }
+
+ // Tx expiration
+ if let Some(exp) = wrapper.tx.header.expiration {
+ if block_time > exp {
return TxResult {
- code:
- ErrorCodes::InvalidDecryptedChainId
- .into(),
+ code: ErrorCodes::ExpiredDecryptedTx
+ .into(),
info: format!(
- "Decrypted tx carries a wrong \
- chain id: expected {}, found {}",
- self.chain_id, tx.chain_id
+ "Decrypted tx expired at {:#?}, \
+ block time: {:#?}",
+ exp, block_time
),
};
}
-
- // Tx expiration
- if let Some(exp) = tx.expiration {
- if block_time > exp {
- return TxResult {
- code:
- ErrorCodes::ExpiredDecryptedTx
- .into(),
- info: format!(
- "Decrypted tx expired at \
- {:#?}, block time: {:#?}",
- exp, block_time
- ),
- };
- }
- }
}
TxResult {
code: ErrorCodes::Ok.into(),
@@ -423,7 +434,7 @@ where
}
// validate the ciphertext via Ferveo
- if !wrapper.validate_ciphertext() {
+ if !tx.validate_ciphertext() {
TxResult {
code: ErrorCodes::InvalidTx.into(),
info: format!(
@@ -434,7 +445,7 @@ where
} else {
// Replay protection checks
if let Err(e) = self.replay_protection_checks(
- &wrapper,
+ &tx,
tx_bytes,
temp_wl_storage,
) {
@@ -504,16 +515,14 @@ where
/// are covered by the e2e tests.
#[cfg(test)]
mod test_process_proposal {
- use borsh::BorshDeserialize;
use namada::ledger::parameters::storage::get_wrapper_tx_fees_key;
- use namada::proto::SignedTxData;
+ use namada::proto::{Code, Data, Section, Signature};
use namada::types::hash::Hash;
use namada::types::key::*;
use namada::types::storage::Epoch;
use namada::types::token::Amount;
- use namada::types::transaction::encrypted::EncryptedTx;
- use namada::types::transaction::protocol::ProtocolTxType;
- use namada::types::transaction::{EncryptionKey, Fee, WrapperTx, MIN_FEE};
+ use namada::types::transaction::protocol::{ProtocolTx, ProtocolTxType};
+ use namada::types::transaction::{Fee, WrapperTx, MIN_FEE};
use super::*;
use crate::node::ledger::shell::test_utils::{
@@ -526,13 +535,7 @@ mod test_process_proposal {
fn test_unsigned_wrapper_rejected() {
let (mut shell, _) = test_utils::setup(1);
let keypair = gen_keypair();
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let wrapper = WrapperTx::new(
+ let mut outer_tx = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: 0.into(),
token: shell.wl_storage.storage.native_token.clone(),
@@ -540,18 +543,14 @@ mod test_process_proposal {
&keypair,
Epoch(0),
0.into(),
- tx,
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- );
- let tx = Tx::new(
- vec![],
- Some(TxType::Wrapper(wrapper).try_to_vec().expect("Test failed")),
- shell.chain_id.clone(),
- None,
- )
- .to_bytes();
+ ))));
+ outer_tx.header.chain_id = shell.chain_id.clone();
+ outer_tx.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ outer_tx.set_data(Data::new("transaction data".as_bytes().to_owned()));
+ outer_tx.encrypt(&Default::default());
+ let tx = outer_tx.to_bytes();
#[allow(clippy::redundant_clone)]
let request = ProcessProposal {
txs: vec![tx.clone()],
@@ -566,7 +565,10 @@ mod test_process_proposal {
);
assert_eq!(
response[0].result.info,
- String::from("Wrapper transactions must be signed")
+ String::from(
+ "WrapperTx signature verification failed: Transaction \
+ doesn't have any data with a signature."
+ )
);
}
}
@@ -578,14 +580,7 @@ mod test_process_proposal {
fn test_wrapper_bad_signature_rejected() {
let (mut shell, _) = test_utils::setup(1);
let keypair = gen_keypair();
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let timestamp = tx.timestamp;
- let mut wrapper = WrapperTx::new(
+ let mut outer_tx = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: 100.into(),
token: shell.wl_storage.storage.native_token.clone(),
@@ -593,51 +588,23 @@ mod test_process_proposal {
&keypair,
Epoch(0),
0.into(),
- tx,
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- )
- .sign(&keypair, shell.chain_id.clone(), None)
- .expect("Test failed");
- let new_tx = if let Some(Ok(SignedTxData {
- data: Some(data),
- sig,
- })) = wrapper
- .data
- .take()
- .map(|data| SignedTxData::try_from_slice(&data[..]))
- {
- let mut new_wrapper = if let TxType::Wrapper(wrapper) =
- ::deserialize(&mut data.as_ref())
- .expect("Test failed")
- {
- wrapper
- } else {
- panic!("Test failed")
- };
-
+ ))));
+ outer_tx.header.chain_id = shell.chain_id.clone();
+ outer_tx.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ outer_tx.set_data(Data::new("transaction data".as_bytes().to_owned()));
+ outer_tx.add_section(Section::Signature(Signature::new(
+ &outer_tx.header_hash(),
+ &keypair,
+ )));
+ outer_tx.encrypt(&Default::default());
+ let mut new_tx = outer_tx.clone();
+ if let TxType::Wrapper(wrapper) = &mut new_tx.header.tx_type {
// we mount a malleability attack to try and remove the fee
- new_wrapper.fee.amount = 0.into();
- let new_data = TxType::Wrapper(new_wrapper)
- .try_to_vec()
- .expect("Test failed");
- Tx {
- code_or_hash: vec![],
- data: Some(
- SignedTxData {
- sig,
- data: Some(new_data),
- }
- .try_to_vec()
- .expect("Test failed"),
- ),
- timestamp,
- chain_id: shell.chain_id.clone(),
- expiration: None,
- }
+ wrapper.fee.amount = 0.into();
} else {
- panic!("Test failed");
+ panic!("Test failed")
};
let request = ProcessProposal {
txs: vec![new_tx.to_bytes()],
@@ -646,8 +613,9 @@ mod test_process_proposal {
match shell.process_proposal(request) {
Ok(_) => panic!("Test failed"),
Err(TestError::RejectProposal(response)) => {
- let expected_error =
- "Signature verification failed: Invalid signature";
+ let expected_error = "WrapperTx signature verification \
+ failed: Transaction doesn't have any \
+ data with a signature.";
assert_eq!(
response[0].result.code,
u32::from(ErrorCodes::InvalidSig)
@@ -676,13 +644,7 @@ mod test_process_proposal {
)
.unwrap();
let keypair = gen_keypair();
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let wrapper = WrapperTx::new(
+ let mut outer_tx = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: 1.into(),
token: shell.wl_storage.storage.native_token.clone(),
@@ -690,15 +652,20 @@ mod test_process_proposal {
&keypair,
Epoch(0),
0.into(),
- tx,
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- )
- .sign(&keypair, shell.chain_id.clone(), None)
- .expect("Test failed");
+ ))));
+ outer_tx.header.chain_id = shell.chain_id.clone();
+ outer_tx.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ outer_tx.set_data(Data::new("transaction data".as_bytes().to_owned()));
+ outer_tx.add_section(Section::Signature(Signature::new(
+ &outer_tx.header_hash(),
+ &keypair,
+ )));
+ outer_tx.encrypt(&Default::default());
+
let request = ProcessProposal {
- txs: vec![wrapper.to_bytes()],
+ txs: vec![outer_tx.to_bytes()],
};
match shell.process_proposal(request) {
@@ -744,13 +711,7 @@ mod test_process_proposal {
)
.unwrap();
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let wrapper = WrapperTx::new(
+ let mut outer_tx = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: Amount::whole(1_000_100),
token: shell.wl_storage.storage.native_token.clone(),
@@ -758,16 +719,20 @@ mod test_process_proposal {
&keypair,
Epoch(0),
0.into(),
- tx,
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- )
- .sign(&keypair, shell.chain_id.clone(), None)
- .expect("Test failed");
+ ))));
+ outer_tx.header.chain_id = shell.chain_id.clone();
+ outer_tx.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ outer_tx.set_data(Data::new("transaction data".as_bytes().to_owned()));
+ outer_tx.add_section(Section::Signature(Signature::new(
+ &outer_tx.header_hash(),
+ &keypair,
+ )));
+ outer_tx.encrypt(&Default::default());
let request = ProcessProposal {
- txs: vec![wrapper.to_bytes()],
+ txs: vec![outer_tx.to_bytes()],
};
match shell.process_proposal(request) {
@@ -796,34 +761,31 @@ mod test_process_proposal {
let keypair = gen_keypair();
let mut txs = vec![];
for i in 0..3 {
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some(format!("transaction data: {}", i).as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let wrapper = WrapperTx::new(
- Fee {
- amount: i.into(),
- token: shell.wl_storage.storage.native_token.clone(),
- },
- &keypair,
- Epoch(0),
- 0.into(),
- tx.clone(),
- Default::default(),
- #[cfg(not(feature = "mainnet"))]
- None,
- );
- shell.enqueue_tx(wrapper);
- let mut decrypted_tx =
- Tx::from(TxType::Decrypted(DecryptedTx::Decrypted {
- tx,
+ let mut outer_tx =
+ Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
+ Fee {
+ amount: i.into(),
+ token: shell.wl_storage.storage.native_token.clone(),
+ },
+ &keypair,
+ Epoch(0),
+ 0.into(),
#[cfg(not(feature = "mainnet"))]
- has_valid_pow: false,
- }));
- decrypted_tx.chain_id = shell.chain_id.clone();
- txs.push(decrypted_tx);
+ None,
+ ))));
+ outer_tx.header.chain_id = shell.chain_id.clone();
+ outer_tx.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ outer_tx.set_data(Data::new(
+ format!("transaction data: {}", i).as_bytes().to_owned(),
+ ));
+ outer_tx.encrypt(&Default::default());
+ shell.enqueue_tx(outer_tx.clone());
+
+ outer_tx.update_header(TxType::Decrypted(DecryptedTx::Decrypted {
+ #[cfg(not(feature = "mainnet"))]
+ has_valid_pow: false,
+ }));
+ txs.push(outer_tx);
}
let response = {
let request = ProcessProposal {
@@ -859,13 +821,7 @@ mod test_process_proposal {
let (mut shell, _) = test_utils::setup(1);
let keypair = gen_keypair();
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let wrapper = WrapperTx::new(
+ let mut tx = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: 0.into(),
token: shell.wl_storage.storage.native_token.clone(),
@@ -873,17 +829,16 @@ mod test_process_proposal {
&keypair,
Epoch(0),
0.into(),
- tx,
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- );
- shell.enqueue_tx(wrapper.clone());
-
- let mut tx =
- Tx::from(TxType::Decrypted(DecryptedTx::Undecryptable(wrapper)));
- tx.chain_id = shell.chain_id.clone();
-
+ ))));
+ tx.header.chain_id = shell.chain_id.clone();
+ tx.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ tx.set_data(Data::new("transaction data".as_bytes().to_owned()));
+ tx.encrypt(&Default::default());
+ shell.enqueue_tx(tx.clone());
+
+ tx.header.tx_type = TxType::Decrypted(DecryptedTx::Undecryptable);
let request = ProcessProposal {
txs: vec![tx.to_bytes()],
};
@@ -914,13 +869,7 @@ mod test_process_proposal {
let (mut shell, _) = test_utils::setup(1);
let keypair = crate::wallet::defaults::daewon_keypair();
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let mut wrapper = WrapperTx::new(
+ let mut tx = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: 0.into(),
token: shell.wl_storage.storage.native_token.clone(),
@@ -928,20 +877,19 @@ mod test_process_proposal {
&keypair,
Epoch(0),
0.into(),
- tx,
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- );
- wrapper.tx_hash = Hash([0; 32]);
+ ))));
+ tx.header.chain_id = shell.chain_id.clone();
+ tx.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ tx.set_data(Data::new("transaction data".as_bytes().to_owned()));
+ tx.set_code_sechash(Hash([0u8; 32]));
+ tx.set_data_sechash(Hash([0u8; 32]));
+ tx.encrypt(&Default::default());
- shell.enqueue_tx(wrapper.clone());
- let mut tx = Tx::from(TxType::Decrypted(DecryptedTx::Undecryptable(
- #[allow(clippy::redundant_clone)]
- wrapper.clone(),
- )));
- tx.chain_id = shell.chain_id.clone();
+ shell.enqueue_tx(tx.clone());
+ tx.header.tx_type = TxType::Decrypted(DecryptedTx::Undecryptable);
let request = ProcessProposal {
txs: vec![tx.to_bytes()],
};
@@ -964,10 +912,7 @@ mod test_process_proposal {
fn test_undecryptable() {
let (mut shell, _) = test_utils::setup(1);
let keypair = crate::wallet::defaults::daewon_keypair();
- let pubkey = EncryptionKey::default();
// not valid tx bytes
- let tx = "garbage data".as_bytes().to_owned();
- let inner_tx = EncryptedTx::encrypt(&tx, pubkey);
let wrapper = WrapperTx {
fee: Fee {
amount: 0.into(),
@@ -976,21 +921,18 @@ mod test_process_proposal {
pk: keypair.ref_to(),
epoch: Epoch(0),
gas_limit: 0.into(),
- inner_tx,
- tx_hash: hash_tx(&tx),
#[cfg(not(feature = "mainnet"))]
pow_solution: None,
};
- shell.enqueue_tx(wrapper.clone());
- let mut signed =
- Tx::from(TxType::Decrypted(DecryptedTx::Undecryptable(
- #[allow(clippy::redundant_clone)]
- wrapper.clone(),
- )));
- signed.chain_id = shell.chain_id.clone();
+ let tx = Tx::new(TxType::Wrapper(Box::new(wrapper)));
+ let mut decrypted = tx.clone();
+ decrypted.update_header(TxType::Decrypted(DecryptedTx::Undecryptable));
+
+ shell.enqueue_tx(tx);
+
let request = ProcessProposal {
- txs: vec![signed.to_bytes()],
+ txs: vec![decrypted.to_bytes()],
};
let response = if let [resp] = shell
.process_proposal(request)
@@ -1009,20 +951,13 @@ mod test_process_proposal {
#[test]
fn test_too_many_decrypted_txs() {
let (mut shell, _) = test_utils::setup(1);
-
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
-
- let mut tx = Tx::from(TxType::Decrypted(DecryptedTx::Decrypted {
- tx,
+ let mut tx = Tx::new(TxType::Decrypted(DecryptedTx::Decrypted {
#[cfg(not(feature = "mainnet"))]
has_valid_pow: false,
}));
- tx.chain_id = shell.chain_id.clone();
+ tx.header.chain_id = shell.chain_id.clone();
+ tx.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ tx.set_data(Data::new("transaction data".as_bytes().to_owned()));
let request = ProcessProposal {
txs: vec![tx.to_bytes()],
@@ -1050,14 +985,11 @@ mod test_process_proposal {
fn test_raw_tx_rejected() {
let (mut shell, _) = test_utils::setup(1);
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let mut tx = Tx::from(TxType::Raw(tx));
- tx.chain_id = shell.chain_id.clone();
+ let mut tx = Tx::new(TxType::Raw);
+ tx.header.chain_id = shell.chain_id.clone();
+ tx.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ tx.set_data(Data::new("transaction data".as_bytes().to_owned()));
+
let request = ProcessProposal {
txs: vec![tx.to_bytes()],
};
@@ -1088,13 +1020,7 @@ mod test_process_proposal {
let keypair = crate::wallet::defaults::daewon_keypair();
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let wrapper = WrapperTx::new(
+ let mut wrapper = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: 0.into(),
token: shell.wl_storage.storage.native_token.clone(),
@@ -1102,17 +1028,20 @@ mod test_process_proposal {
&keypair,
Epoch(0),
0.into(),
- tx,
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- );
- let signed = wrapper
- .sign(&keypair, shell.chain_id.clone(), None)
- .expect("Test failed");
+ ))));
+ wrapper.header.chain_id = shell.chain_id.clone();
+ wrapper.set_data(Data::new("transaction data".as_bytes().to_owned()));
+ wrapper.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ wrapper.add_section(Section::Signature(Signature::new(
+ &wrapper.header_hash(),
+ &keypair,
+ )));
+ wrapper.encrypt(&Default::default());
// Write wrapper hash to storage
- let wrapper_unsigned_hash = Hash(signed.unsigned_hash());
+ let wrapper_unsigned_hash = wrapper.header_hash();
let hash_key =
replay_protection::get_tx_hash_key(&wrapper_unsigned_hash);
shell
@@ -1123,8 +1052,9 @@ mod test_process_proposal {
// Run validation
let request = ProcessProposal {
- txs: vec![signed.to_bytes()],
+ txs: vec![wrapper.to_bytes()],
};
+
match shell.process_proposal(request) {
Ok(_) => panic!("Test failed"),
Err(TestError::RejectProposal(response)) => {
@@ -1162,13 +1092,7 @@ mod test_process_proposal {
.write(&balance_key, Amount::whole(1000).try_to_vec().unwrap())
.unwrap();
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let wrapper = WrapperTx::new(
+ let mut wrapper = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: 0.into(),
token: shell.wl_storage.storage.native_token.clone(),
@@ -1176,18 +1100,21 @@ mod test_process_proposal {
&keypair,
Epoch(0),
0.into(),
- tx,
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- );
- let signed = wrapper
- .sign(&keypair, shell.chain_id.clone(), None)
- .expect("Test failed");
+ ))));
+ wrapper.header.chain_id = shell.chain_id.clone();
+ wrapper.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ wrapper.set_data(Data::new("transaction data".as_bytes().to_owned()));
+ wrapper.add_section(Section::Signature(Signature::new(
+ &wrapper.header_hash(),
+ &keypair,
+ )));
+ wrapper.encrypt(&Default::default());
// Run validation
let request = ProcessProposal {
- txs: vec![signed.to_bytes(); 2],
+ txs: vec![wrapper.to_bytes(); 2],
};
match shell.process_proposal(request) {
Ok(_) => panic!("Test failed"),
@@ -1205,7 +1132,10 @@ mod test_process_proposal {
format!(
"Transaction replay attempt: Inner transaction hash \
{} already in storage",
- wrapper.tx_hash
+ wrapper
+ .clone()
+ .update_header(TxType::Raw)
+ .header_hash(),
)
);
}
@@ -1220,13 +1150,7 @@ mod test_process_proposal {
let keypair = crate::wallet::defaults::daewon_keypair();
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let wrapper = WrapperTx::new(
+ let mut wrapper = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: 0.into(),
token: shell.wl_storage.storage.native_token.clone(),
@@ -1234,15 +1158,19 @@ mod test_process_proposal {
&keypair,
Epoch(0),
0.into(),
- tx,
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- );
- let inner_unsigned_hash = wrapper.tx_hash.clone();
- let signed = wrapper
- .sign(&keypair, shell.chain_id.clone(), None)
- .expect("Test failed");
+ ))));
+ wrapper.header.chain_id = shell.chain_id.clone();
+ wrapper.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ wrapper.set_data(Data::new("transaction data".as_bytes().to_owned()));
+ wrapper.add_section(Section::Signature(Signature::new(
+ &wrapper.header_hash(),
+ &keypair,
+ )));
+ wrapper.encrypt(&Default::default());
+ let inner_unsigned_hash =
+ wrapper.clone().update_header(TxType::Raw).header_hash();
// Write inner hash to storage
let hash_key = replay_protection::get_tx_hash_key(&inner_unsigned_hash);
@@ -1254,7 +1182,7 @@ mod test_process_proposal {
// Run validation
let request = ProcessProposal {
- txs: vec![signed.to_bytes()],
+ txs: vec![wrapper.to_bytes()],
};
match shell.process_proposal(request) {
Ok(_) => panic!("Test failed"),
@@ -1306,13 +1234,7 @@ mod test_process_proposal {
.write(&balance_key, Amount::whole(1000).try_to_vec().unwrap())
.unwrap();
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let wrapper = WrapperTx::new(
+ let mut wrapper = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: 0.into(),
token: shell.wl_storage.storage.native_token.clone(),
@@ -1320,17 +1242,22 @@ mod test_process_proposal {
&keypair,
Epoch(0),
0.into(),
- tx.clone(),
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- );
- let inner_unsigned_hash = wrapper.tx_hash.clone();
- let signed = wrapper
- .sign(&keypair, shell.chain_id.clone(), None)
- .expect("Test failed");
+ ))));
+ wrapper.header.chain_id = shell.chain_id.clone();
+ wrapper.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ wrapper.set_data(Data::new("transaction data".as_bytes().to_owned()));
+ let mut new_wrapper = wrapper.clone();
+ wrapper.add_section(Section::Signature(Signature::new(
+ &wrapper.header_hash(),
+ &keypair,
+ )));
+ wrapper.encrypt(&Default::default());
+ let inner_unsigned_hash =
+ wrapper.clone().update_header(TxType::Raw).header_hash();
- let new_wrapper = WrapperTx::new(
+ new_wrapper.update_header(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: 0.into(),
token: shell.wl_storage.storage.native_token.clone(),
@@ -1338,18 +1265,18 @@ mod test_process_proposal {
&keypair_2,
Epoch(0),
0.into(),
- tx,
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- );
- let new_signed = new_wrapper
- .sign(&keypair, shell.chain_id.clone(), None)
- .expect("Test failed");
+ ))));
+ new_wrapper.add_section(Section::Signature(Signature::new(
+ &new_wrapper.header_hash(),
+ &keypair,
+ )));
+ new_wrapper.encrypt(&Default::default());
// Run validation
let request = ProcessProposal {
- txs: vec![signed.to_bytes(), new_signed.to_bytes()],
+ txs: vec![wrapper.to_bytes(), new_wrapper.to_bytes()],
};
match shell.process_proposal(request) {
Ok(_) => panic!("Test failed"),
@@ -1378,13 +1305,7 @@ mod test_process_proposal {
let (mut shell, _) = test_utils::setup(1);
let keypair = crate::wallet::defaults::daewon_keypair();
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let wrapper = WrapperTx::new(
+ let mut wrapper = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: 0.into(),
token: shell.wl_storage.storage.native_token.clone(),
@@ -1392,25 +1313,32 @@ mod test_process_proposal {
&keypair,
Epoch(0),
0.into(),
- tx.clone(),
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- );
+ ))));
let wrong_chain_id = ChainId("Wrong chain id".to_string());
- let signed = wrapper
- .sign(&keypair, wrong_chain_id.clone(), None)
- .expect("Test failed");
+ wrapper.header.chain_id = wrong_chain_id.clone();
+ wrapper.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ wrapper.set_data(Data::new("transaction data".as_bytes().to_owned()));
+ let mut protocol_tx = wrapper.clone();
+ wrapper.add_section(Section::Signature(Signature::new(
+ &wrapper.header_hash(),
+ &keypair,
+ )));
+ wrapper.encrypt(&Default::default());
- let protocol_tx = ProtocolTxType::EthereumStateUpdate(tx).sign(
- &keypair.ref_to(),
+ protocol_tx.update_header(TxType::Protocol(Box::new(ProtocolTx {
+ pk: keypair.ref_to(),
+ tx: ProtocolTxType::EthereumStateUpdate,
+ })));
+ protocol_tx.add_section(Section::Signature(Signature::new(
+ &protocol_tx.header_hash(),
&keypair,
- wrong_chain_id.clone(),
- );
+ )));
// Run validation
let request = ProcessProposal {
- txs: vec![signed.to_bytes(), protocol_tx.to_bytes()],
+ txs: vec![wrapper.to_bytes(), protocol_tx.to_bytes()],
};
match shell.process_proposal(request) {
Ok(_) => panic!("Test failed"),
@@ -1441,19 +1369,7 @@ mod test_process_proposal {
let keypair = crate::wallet::defaults::daewon_keypair();
let wrong_chain_id = ChainId("Wrong chain id".to_string());
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("new transaction data".as_bytes().to_owned()),
- wrong_chain_id.clone(),
- None,
- );
- let decrypted: Tx = DecryptedTx::Decrypted {
- tx: tx.clone(),
- has_valid_pow: false,
- }
- .into();
- let signed_decrypted = decrypted.sign(&keypair);
- let wrapper = WrapperTx::new(
+ let mut wrapper = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: 0.into(),
token: shell.wl_storage.storage.native_token.clone(),
@@ -1461,12 +1377,24 @@ mod test_process_proposal {
&keypair,
Epoch(0),
0.into(),
- tx,
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- );
- let wrapper_in_queue = WrapperTxInQueue {
+ ))));
+ wrapper.header.chain_id = wrong_chain_id.clone();
+ wrapper.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ wrapper
+ .set_data(Data::new("new transaction data".as_bytes().to_owned()));
+ let mut decrypted = wrapper.clone();
+ wrapper.encrypt(&Default::default());
+
+ decrypted.update_header(TxType::Decrypted(DecryptedTx::Decrypted {
+ has_valid_pow: false,
+ }));
+ decrypted.add_section(Section::Signature(Signature::new(
+ &decrypted.header_hash(),
+ &keypair,
+ )));
+ let wrapper_in_queue = TxInQueue {
tx: wrapper,
has_valid_pow: false,
};
@@ -1474,7 +1402,7 @@ mod test_process_proposal {
// Run validation
let request = ProcessProposal {
- txs: vec![signed_decrypted.to_bytes()],
+ txs: vec![decrypted.to_bytes()],
};
match shell.process_proposal(request) {
@@ -1502,13 +1430,7 @@ mod test_process_proposal {
let (mut shell, _) = test_utils::setup(1);
let keypair = crate::wallet::defaults::daewon_keypair();
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- None,
- );
- let wrapper = WrapperTx::new(
+ let mut wrapper = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: 0.into(),
token: shell.wl_storage.storage.native_token.clone(),
@@ -1516,18 +1438,22 @@ mod test_process_proposal {
&keypair,
Epoch(0),
0.into(),
- tx,
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- );
- let signed = wrapper
- .sign(&keypair, shell.chain_id.clone(), Some(DateTimeUtc::now()))
- .expect("Test failed");
+ ))));
+ wrapper.header.chain_id = shell.chain_id.clone();
+ wrapper.header.expiration = Some(DateTimeUtc::now());
+ wrapper.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ wrapper.set_data(Data::new("transaction data".as_bytes().to_owned()));
+ wrapper.add_section(Section::Signature(Signature::new(
+ &wrapper.header_hash(),
+ &keypair,
+ )));
+ wrapper.encrypt(&Default::default());
// Run validation
let request = ProcessProposal {
- txs: vec![signed.to_bytes()],
+ txs: vec![wrapper.to_bytes()],
};
match shell.process_proposal(request) {
Ok(_) => panic!("Test failed"),
@@ -1547,19 +1473,7 @@ mod test_process_proposal {
let (mut shell, _) = test_utils::setup(1);
let keypair = crate::wallet::defaults::daewon_keypair();
- let tx = Tx::new(
- "wasm_code".as_bytes().to_owned(),
- Some("new transaction data".as_bytes().to_owned()),
- shell.chain_id.clone(),
- Some(DateTimeUtc::now()),
- );
- let decrypted: Tx = DecryptedTx::Decrypted {
- tx: tx.clone(),
- has_valid_pow: false,
- }
- .into();
- let signed_decrypted = decrypted.sign(&keypair);
- let wrapper = WrapperTx::new(
+ let mut wrapper = Tx::new(TxType::Wrapper(Box::new(WrapperTx::new(
Fee {
amount: 0.into(),
token: shell.wl_storage.storage.native_token.clone(),
@@ -1567,12 +1481,25 @@ mod test_process_proposal {
&keypair,
Epoch(0),
0.into(),
- tx,
- Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
- );
- let wrapper_in_queue = WrapperTxInQueue {
+ ))));
+ wrapper.header.chain_id = shell.chain_id.clone();
+ wrapper.header.expiration = Some(DateTimeUtc::now());
+ wrapper.set_code(Code::new("wasm_code".as_bytes().to_owned()));
+ wrapper
+ .set_data(Data::new("new transaction data".as_bytes().to_owned()));
+ let mut decrypted = wrapper.clone();
+ wrapper.encrypt(&Default::default());
+
+ decrypted.update_header(TxType::Decrypted(DecryptedTx::Decrypted {
+ has_valid_pow: false,
+ }));
+ decrypted.add_section(Section::Signature(Signature::new(
+ &decrypted.header_hash(),
+ &keypair,
+ )));
+ let wrapper_in_queue = TxInQueue {
tx: wrapper,
has_valid_pow: false,
};
@@ -1580,7 +1507,7 @@ mod test_process_proposal {
// Run validation
let request = ProcessProposal {
- txs: vec![signed_decrypted.to_bytes()],
+ txs: vec![decrypted.to_bytes()],
};
match shell.process_proposal(request) {
Ok(response) => {
diff --git a/apps/src/lib/node/ledger/shims/abcipp_shim.rs b/apps/src/lib/node/ledger/shims/abcipp_shim.rs
index 05ffbf8de0..7bb02a6aef 100644
--- a/apps/src/lib/node/ledger/shims/abcipp_shim.rs
+++ b/apps/src/lib/node/ledger/shims/abcipp_shim.rs
@@ -186,7 +186,7 @@ impl AbcippShim {
let mut end_block_request: FinalizeBlock =
begin_block_request.into();
let hash = self.get_hash();
- end_block_request.hash = BlockHash::from(hash.clone());
+ end_block_request.hash = BlockHash::from(hash);
end_block_request.txs = txs;
self.service
.call(Request::FinalizeBlock(end_block_request))
diff --git a/apps/src/lib/node/ledger/storage/mod.rs b/apps/src/lib/node/ledger/storage/mod.rs
index 73c21ba6ca..e9222ab213 100644
--- a/apps/src/lib/node/ledger/storage/mod.rs
+++ b/apps/src/lib/node/ledger/storage/mod.rs
@@ -246,7 +246,7 @@ mod tests {
// insert
let vp1 = Hash::sha256("vp1".as_bytes());
- storage.write(&key, vp1.clone()).expect("write failed");
+ storage.write(&key, vp1).expect("write failed");
// check
let (vp_code_hash, gas) =
diff --git a/core/Cargo.toml b/core/Cargo.toml
index 4642a9e9ad..8f155db2d5 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -73,7 +73,8 @@ ics23 = "0.9.0"
index-set = {git = "https://github.com/heliaxdev/index-set", tag = "v0.7.1", features = ["serialize-borsh", "serialize-serde"]}
itertools = "0.10.0"
libsecp256k1 = {git = "https://github.com/heliaxdev/libsecp256k1", rev = "bbb3bd44a49db361f21d9db80f9a087c194c0ae9", default-features = false, features = ["std", "static-context"]}
-masp_primitives = { git = "https://github.com/anoma/masp", rev = "4274fc0bf300bcdae4f186fba134bab8af83ae93" }
+# branch = "murisi/namada-integration"
+masp_primitives = { git = "https://github.com/anoma/masp", rev = "cfea8c95d3f73077ca3e25380fd27e5b46e828fd" }
proptest = {git = "https://github.com/heliaxdev/proptest", rev = "8f1b4abe7ebd35c0781bf9a00a4ee59833ffa2a1", optional = true}
prost = "0.11.6"
prost-types = "0.11.6"
diff --git a/core/src/ledger/storage/merkle_tree.rs b/core/src/ledger/storage/merkle_tree.rs
index 31fb40b1eb..046ebca4e6 100644
--- a/core/src/ledger/storage/merkle_tree.rs
+++ b/core/src/ledger/storage/merkle_tree.rs
@@ -723,7 +723,7 @@ mod test {
let stores_write = tree.stores();
let mut stores_read = MerkleTreeStoresRead::default();
for st in StoreType::iter() {
- stores_read.set_root(st, stores_write.root(st).clone());
+ stores_read.set_root(st, *stores_write.root(st));
stores_read.set_store(stores_write.store(st).to_owned());
}
let restored_tree =
diff --git a/core/src/ledger/storage/mod.rs b/core/src/ledger/storage/mod.rs
index cbe4421d88..f3a4afe0a9 100644
--- a/core/src/ledger/storage/mod.rs
+++ b/core/src/ledger/storage/mod.rs
@@ -919,7 +919,6 @@ where
}
}
}
-
Ok(())
}
}
diff --git a/core/src/ledger/storage/write_log.rs b/core/src/ledger/storage/write_log.rs
index bf4881aab0..938e4e8948 100644
--- a/core/src/ledger/storage/write_log.rs
+++ b/core/src/ledger/storage/write_log.rs
@@ -439,11 +439,7 @@ impl WriteLog {
}
StorageModification::InitAccount { vp_code_hash } => {
storage
- .batch_write_subspace_val(
- batch,
- key,
- vp_code_hash.clone(),
- )
+ .batch_write_subspace_val(batch, key, *vp_code_hash)
.map_err(Error::StorageError)?;
}
// temporary value isn't persisted
@@ -609,7 +605,7 @@ mod tests {
// init
let init_vp = "initialized".as_bytes().to_vec();
let vp_hash = Hash::sha256(init_vp);
- let (addr, gas) = write_log.init_account(&address_gen, vp_hash.clone());
+ let (addr, gas) = write_log.init_account(&address_gen, vp_hash);
let vp_key = storage::Key::validity_predicate(&addr);
assert_eq!(gas, (vp_key.len() + vp_hash.len()) as u64);
@@ -693,7 +689,7 @@ mod tests {
// initialize an account
let vp1 = Hash::sha256("vp1".as_bytes());
- let (addr1, _) = write_log.init_account(&address_gen, vp1.clone());
+ let (addr1, _) = write_log.init_account(&address_gen, vp1);
write_log.commit_tx();
// write values
diff --git a/core/src/ledger/vp_env.rs b/core/src/ledger/vp_env.rs
index f1d1210e28..b9ce0caced 100644
--- a/core/src/ledger/vp_env.rs
+++ b/core/src/ledger/vp_env.rs
@@ -4,9 +4,9 @@
use borsh::BorshDeserialize;
use super::storage_api::{self, StorageRead};
+use crate::proto::Tx;
use crate::types::address::Address;
use crate::types::hash::Hash;
-use crate::types::key::common;
use crate::types::storage::{
BlockHash, BlockHeight, Epoch, Header, Key, TxIndex,
};
@@ -91,20 +91,11 @@ where
fn eval(
&self,
vp_code: Hash,
- input_data: Vec,
- ) -> Result;
-
- /// Verify a transaction signature. The signature is expected to have been
- /// produced on the encoded transaction [`crate::proto::Tx`]
- /// using [`crate::proto::Tx::sign`].
- fn verify_tx_signature(
- &self,
- pk: &common::PublicKey,
- sig: &common::Signature,
+ input_data: Tx,
) -> Result;
/// Get a tx hash
- fn get_tx_code_hash(&self) -> Result;
+ fn get_tx_code_hash(&self) -> Result