diff --git a/.changelog/unreleased/improvements/2202-combine-user-validator-vp.md b/.changelog/unreleased/improvements/2202-combine-user-validator-vp.md new file mode 100644 index 0000000000..030af2ca17 --- /dev/null +++ b/.changelog/unreleased/improvements/2202-combine-user-validator-vp.md @@ -0,0 +1,2 @@ +- Combined the user and the validator VP into one. + ([\#2202](https://github.com/anoma/namada/pull/2202)) \ No newline at end of file diff --git a/apps/src/lib/bench_utils.rs b/apps/src/lib/bench_utils.rs index 551bf49abd..a718cacbed 100644 --- a/apps/src/lib/bench_utils.rs +++ b/apps/src/lib/bench_utils.rs @@ -90,7 +90,7 @@ pub use namada_sdk::tx::{ TX_RESIGN_STEWARD, TX_REVEAL_PK as TX_REVEAL_PK_WASM, TX_TRANSFER_WASM, TX_UNBOND_WASM, TX_UNJAIL_VALIDATOR_WASM, TX_UPDATE_ACCOUNT_WASM, TX_UPDATE_STEWARD_COMMISSION, TX_VOTE_PROPOSAL as TX_VOTE_PROPOSAL_WASM, - TX_WITHDRAW_WASM, VP_USER_WASM, VP_VALIDATOR_WASM, + TX_WITHDRAW_WASM, VP_USER_WASM, }; use namada_sdk::wallet::Wallet; use namada_sdk::NamadaImpl; diff --git a/apps/src/lib/config/genesis.rs b/apps/src/lib/config/genesis.rs index b1fac85e81..32d2fcf3ae 100644 --- a/apps/src/lib/config/genesis.rs +++ b/apps/src/lib/config/genesis.rs @@ -380,7 +380,7 @@ pub fn make_dev_genesis( address, tx: transactions::ValidatorAccountTx { alias: alias.clone(), - vp: "vp_validator".to_string(), + vp: "vp_user".to_string(), commission_rate: Dec::new(5, 2).expect("This can't fail"), max_commission_rate_change: Dec::new(1, 2) .expect("This can't fail"), diff --git a/apps/src/lib/config/genesis/transactions.rs b/apps/src/lib/config/genesis/transactions.rs index d457ef87f5..b617b5a3bf 100644 --- a/apps/src/lib/config/genesis/transactions.rs +++ b/apps/src/lib/config/genesis/transactions.rs @@ -153,7 +153,7 @@ pub fn init_validator( validator_wallet.eth_cold_key.ref_to(), ), // No custom validator VPs yet - vp: "vp_validator".to_string(), + vp: "vp_user".to_string(), commission_rate, max_commission_rate_change, email, diff --git a/benches/host_env.rs b/benches/host_env.rs index 3b096f11ec..289b0eb564 100644 --- a/benches/host_env.rs +++ b/benches/host_env.rs @@ -9,7 +9,7 @@ use namada::proto::Signature; use namada::vm::wasm::TxCache; use namada_apps::bench_utils::{ BenchShell, TX_INIT_PROPOSAL_WASM, TX_REVEAL_PK_WASM, TX_TRANSFER_WASM, - TX_UPDATE_ACCOUNT_WASM, VP_VALIDATOR_WASM, WASM_DIR, + TX_UPDATE_ACCOUNT_WASM, VP_USER_WASM, WASM_DIR, }; use namada_apps::wallet::defaults; use namada_apps::wasm_loader; @@ -68,7 +68,7 @@ fn compile_wasm(c: &mut Criterion) { TX_INIT_PROPOSAL_WASM, TX_REVEAL_PK_WASM, TX_UPDATE_ACCOUNT_WASM, - VP_VALIDATOR_WASM, + VP_USER_WASM, ] { let wasm_code = wasm_loader::read_wasm_or_exit(WASM_DIR, tx); txs.insert(tx, wasm_code); diff --git a/benches/txs.rs b/benches/txs.rs index 02d6c9c22d..98f4d45a9d 100644 --- a/benches/txs.rs +++ b/benches/txs.rs @@ -51,7 +51,7 @@ use namada_apps::bench_utils::{ TX_REACTIVATE_VALIDATOR_WASM, TX_REDELEGATE_WASM, TX_RESIGN_STEWARD, TX_REVEAL_PK_WASM, TX_UNBOND_WASM, TX_UNJAIL_VALIDATOR_WASM, TX_UPDATE_ACCOUNT_WASM, TX_UPDATE_STEWARD_COMMISSION, - TX_VOTE_PROPOSAL_WASM, TX_WITHDRAW_WASM, VP_VALIDATOR_WASM, + TX_VOTE_PROPOSAL_WASM, TX_WITHDRAW_WASM, VP_USER_WASM, }; use namada_apps::wallet::defaults; use sha2::Digest; @@ -369,11 +369,11 @@ fn reveal_pk(c: &mut Criterion) { fn update_account(c: &mut Criterion) { let shell = BenchShell::default(); let vp_code_hash: Hash = shell - .read_storage_key(&Key::wasm_hash(VP_VALIDATOR_WASM)) + .read_storage_key(&Key::wasm_hash(VP_USER_WASM)) .unwrap(); let extra_section = Section::ExtraData(Code::from_hash( vp_code_hash, - Some(VP_VALIDATOR_WASM.to_string()), + Some(VP_USER_WASM.to_string()), )); let data = UpdateAccount { addr: defaults::albert_address(), @@ -412,11 +412,11 @@ fn init_account(c: &mut Criterion) { let shell = BenchShell::default(); let vp_code_hash: Hash = shell - .read_storage_key(&Key::wasm_hash(VP_VALIDATOR_WASM)) + .read_storage_key(&Key::wasm_hash(VP_USER_WASM)) .unwrap(); let extra_section = Section::ExtraData(Code::from_hash( vp_code_hash, - Some(VP_VALIDATOR_WASM.to_string()), + Some(VP_USER_WASM.to_string()), )); let extra_hash = Hash( extra_section @@ -613,11 +613,11 @@ fn init_validator(c: &mut Criterion) { let shell = BenchShell::default(); let validator_vp_code_hash: Hash = shell - .read_storage_key(&Key::wasm_hash(VP_VALIDATOR_WASM)) + .read_storage_key(&Key::wasm_hash(VP_USER_WASM)) .unwrap(); let extra_section = Section::ExtraData(Code::from_hash( validator_vp_code_hash, - Some(VP_VALIDATOR_WASM.to_string()), + Some(VP_USER_WASM.to_string()), )); let extra_hash = Hash( extra_section diff --git a/benches/vps.rs b/benches/vps.rs index d101b2a4a9..366887d1fa 100644 --- a/benches/vps.rs +++ b/benches/vps.rs @@ -22,7 +22,7 @@ use namada_apps::bench_utils::{ generate_foreign_key_tx, BenchShell, TX_BOND_WASM, TX_CHANGE_VALIDATOR_COMMISSION_WASM, TX_REVEAL_PK_WASM, TX_TRANSFER_WASM, TX_UNBOND_WASM, TX_UPDATE_ACCOUNT_WASM, TX_VOTE_PROPOSAL_WASM, - VP_USER_WASM, VP_VALIDATOR_WASM, + VP_USER_WASM, }; use namada_apps::wallet::defaults; use sha2::Digest; @@ -70,11 +70,11 @@ fn vp_user(c: &mut Criterion) { ); let vp_validator_hash = shell - .read_storage_key(&Key::wasm_hash(VP_VALIDATOR_WASM)) + .read_storage_key(&Key::wasm_hash(VP_USER_WASM)) .unwrap(); let extra_section = Section::ExtraData(Code::from_hash( vp_validator_hash, - Some(VP_VALIDATOR_WASM.to_string()), + Some(VP_USER_WASM.to_string()), )); let data = UpdateAccount { addr: defaults::albert_address(), @@ -322,7 +322,7 @@ fn vp_implicit(c: &mut Criterion) { fn vp_validator(c: &mut Criterion) { let shell = BenchShell::default(); let vp_code_hash: Hash = shell - .read_storage_key(&Key::wasm_hash(VP_VALIDATOR_WASM)) + .read_storage_key(&Key::wasm_hash(VP_USER_WASM)) .unwrap(); let mut group = c.benchmark_group("vp_validator"); @@ -361,7 +361,7 @@ fn vp_validator(c: &mut Criterion) { let extra_section = Section::ExtraData(Code::from_hash( vp_code_hash, - Some(VP_VALIDATOR_WASM.to_string()), + Some(VP_USER_WASM.to_string()), )); let data = UpdateAccount { addr: defaults::validator_address(), diff --git a/genesis/README.md b/genesis/README.md index 894e3d602c..1aec869104 100644 --- a/genesis/README.md +++ b/genesis/README.md @@ -56,7 +56,7 @@ An unsigned `validator_account` tx example: ```toml [[validator_account]] alias = "validator-0" -vp = "vp_validator" +vp = "vp_user" commission_rate = "0.05" max_commission_rate_change = "0.01" net_address = "127.0.0.1:27656" diff --git a/genesis/localnet/src/pre-genesis/validator-0/transactions.toml b/genesis/localnet/src/pre-genesis/validator-0/transactions.toml index bd03907dae..85c174edc2 100644 --- a/genesis/localnet/src/pre-genesis/validator-0/transactions.toml +++ b/genesis/localnet/src/pre-genesis/validator-0/transactions.toml @@ -1,34 +1,34 @@ [[validator_account]] alias = "validator-0" -vp = "vp_validator" +vp = "vp_user" commission_rate = "0.05" max_commission_rate_change = "0.01" email = "null@null.net" net_address = "127.0.0.1:27656" [validator_account.account_key] -pk = "tpknam1qzuaykg8nrmzuaefut39aaxl0gl66y62285cnwe37gq0a96qaf4qgp5yqtw" -authorization = "signam1qpcvzjdqkvhud9lez3exq3vy7dnp4kyjgsk92yx5cslwzjs0q9czx8ajxztx5pftx9hsf9w2shh6rt0uv6xeyu30ljqkrqj6hnrwn5gqfd9pwf" +pk = "tpknam1qpg2tsrplvhu3fd7z7tq5ztc2ne3s7e2ahjl2a2cddufrzdyr752g666ytj" +authorization = "signam1qzyc89wynvm4n7eq7jglv4d8upaxu38mkkktykjjtgqygmk4sq97ffxermz5wpur4rqr8gk6fze5uvc4u7q4qzqsr285gungdyhv2acgna2ltq" [validator_account.consensus_key] -pk = "tpknam1qpudpptwfh9u5mhvksrguyqk6wvyhus0kf2cs9qr0xuq9k4fepldgqv3ztq" -authorization = "signam1qpuhmvgl330cr3acugaddhn6q9xdw3577h3mv9yszau2smxmn7yvmn2yplfym4sk30r2hz943989sd68umu70e4wsk5q6j2gzzjfg4q0qjvz6f" +pk = "tpknam1qr9u5py97pdmcvnrxhzuuv79ydv5rw7r9z402sucwt6h0lvmmmwqy2wrweg" +authorization = "signam1qzt7ww0q00punp93jrvtkq62n4rk8y5d90tllmlkzr0z7urwfdkn7z8ttne92utwskl6ves4qp66r60tg2xqr568ranwfhcm0665wncqq4t5gx" [validator_account.protocol_key] -pk = "tpknam1qzxs6kchkustgjxld3xz0u3c8gfnkvda042vp06auk6zfrru5hhxqqvyxq6" -authorization = "signam1qztaxmfgncmv5jn9tak0au2ryzxwxrlhn2qyfx4fgewuv5p7jelpfpqe9mlp7y73vsw7r8hu509swj8mumgryswu38m7mvxn9asqn0cq7aqvjp" +pk = "tpknam1qrenhfdphzpszlr7fzand6qgmppge430g3a2lquqzhz64fkve5mq2hdfjaa" +authorization = "signam1qqeaqzj9fu0xsu7pvrkwla5asxde2wak7fslst0p79vxxydt40tzdj54js7dmjvqs2quygqqwup8z2cfffvm86ff8cud6gzel9g40ycw25wp5d" [validator_account.tendermint_node_key] -pk = "tpknam1qzckzn2rc4pr26e0clxajgcllasr6tke4yqrsu7wskw89uka29zykram505" -authorization = "signam1qrgvyj39ljlequl20hx2mz9wpuyjl8lj826c0upy9agt4txuyyusuqkhdmm2aajglupssqcsx8nv62etua6vn0duzrucut4m74nmhscwy3knc3" +pk = "tpknam1qpgcgptcjl22hl2te2uqnp33aqjmvfaud3a3f3sgtxezg7uu5rsv6d2flr3" +authorization = "signam1qrq7x5e7svuddy8dyr3xpcdt6a07u6sky0n5qnv5z757g33t5zm3jnnh9uhh073g05n8jx8rmdu5r2djhwh6few6u329u9cld4c7ynsw2592h8" [validator_account.eth_hot_key] -pk = "tpknam1qyp8znkp023autwqh2cy6c6vhnz8vsm4p6w9ngpnnamqk6dj5w6ktxqjnd0qj" -authorization = "signam1q9fd4nkz8df5ajh6jrsn6mrt0apvn4266walr8pnczl0xtn847u6usdemslvusseerhrd6hftse8zfch5tlpmqp4y9xz3563mu0d26hnqq942mt2" +pk = "tpknam1qypnh98mexms8edj8rcwu0cayx0459p39dwzsffxrr394mf4cse707qcctyrx" +authorization = "signam1qyrvwveg76nrz2ppnsl0em82gcl4p90cqw8eadyzcvk59e2dx0jqja8ln9l9j79sxzhhh5gdggduz78vtthzj5nzs0xvpwhjuh3hymapqq07qxzm" [validator_account.eth_cold_key] -pk = "tpknam1qyp4aw7a07f4ltuq3f0c4sgyq3kzgh6z40w8jt40wl7uhfj7e3m3u9qr792xg" -authorization = "signam1qyqcc7wstsnuadu75jnwg8hxz34nglxj9h9yqyx2c4qqdpxw50ff60hu0swfj7xdkz34tgl9e50jlmzphkgtpw3gg0hsgp35lhsl6rmeqqq28kph" +pk = "tpknam1qypz8zr0w8lsz3s98vh4p974xuxeedpecj9s2l3326r3kdz4tc0snrcpnc8yv" +authorization = "signam1q992kq4ymfl6v8arc2s2tn0w7c4f48wx6fxry9qxv2qk8zvjan8q7j9rxg73cx0f5l56fy53x2jgwv7vy8jtxzucckdzgnxc5tpzajs4qq8r02r2" [[transfer]] token = "nam" @@ -41,4 +41,4 @@ signature = "signam1qz8ch7n6jp7g7hvnzkhmprhqc5umd0gatarlttm7gpcdx6g8hmgqffdq67fn source = "validator-0" validator = "validator-0" amount = "100000" -signature = "signam1qrd7wg2sdla73z7626r2ep8895d9ed4ljq37nz6kmy2rcm36yqjugw6vle7kl70l0d585t382s9vd28k2duwz0lu7ux0vua6aaarjssgdf46n2" +signature = "signam1qqukrz3js2pgzrne90u5f7y4mstrzvmzcq7eelml9m3lzrh9zwpf0vhgjq0rsw4ufj4ffdx8ew74uxkk4df649pg6qq5fgwyqa9mpfcyvskk67" diff --git a/genesis/localnet/src/pre-genesis/validator-0/validator-wallet.toml b/genesis/localnet/src/pre-genesis/validator-0/validator-wallet.toml index 4f3db8b8b0..2e0107b173 100644 --- a/genesis/localnet/src/pre-genesis/validator-0/validator-wallet.toml +++ b/genesis/localnet/src/pre-genesis/validator-0/validator-wallet.toml @@ -1,8 +1,8 @@ -account_key = "unencrypted:00eaa8829ff8932ffad86c4b0ad1ed2f2870c12ca49f03b50e4b34d360daa24268" -consensus_key = "unencrypted:00aabd79879fce99cb528f92d8ea4593241dd49507ff456be52ca2aee98c728338" -eth_cold_key = "unencrypted:0181901af21f92e997c78c61337475d1975c8d29591601e36ace3952d7094d9447" -tendermint_node_key = "unencrypted:00afc7747d1e6d76293553864bbf482d061f1932f83b978b24ba4957dcfcda987c" +account_key = "unencrypted:0024204e13c51b26ed9b42c05647bc46b3821bb453e53d194962ede57ce5ec66ac" +consensus_key = "unencrypted:0037a44681b64d42497e2229516479f83e5344a7a30e8316bde45881a1ec745359" +eth_cold_key = "unencrypted:010d34fcb42383f0babe7c86203f07bf4134f0756a630eb07923f21c90cc068602" +tendermint_node_key = "unencrypted:002f2e94bb5834e18433343345baf47b2b5d4e1ef4d46ba0f876d3d2c89d831419" [validator_keys] -protocol_keypair = "ED25519_SK_PREFIX00b0da066a528a0e1221e6453f9d10143b07a675a250c66603e8a7e98bdbb8cf19" -eth_bridge_keypair = "SECP256K1_SK_PREFIX0133deb418af6af5c62aecbde3dc3a0ff62ea20c0c8e33cf703d0f5e35248e5ab1" +protocol_keypair = "ED25519_SK_PREFIX00610677d4c52ab8ca5e8abe7dfb40246a271a03069fded6099763cbc41e04df02" +eth_bridge_keypair = "SECP256K1_SK_PREFIX01a81af251a711382d6b649a44b36ac5d4f41106f356e1f2fb33c001e91ffaa169" diff --git a/genesis/localnet/transactions.toml b/genesis/localnet/transactions.toml index cafe123854..0662c5147b 100644 --- a/genesis/localnet/transactions.toml +++ b/genesis/localnet/transactions.toml @@ -7,35 +7,35 @@ [[validator_account]] alias = "validator-0" -vp = "vp_validator" +vp = "vp_user" commission_rate = "0.05" max_commission_rate_change = "0.01" email = "null@null.net" net_address = "127.0.0.1:27656" [validator_account.account_key] -pk = "tpknam1qzuaykg8nrmzuaefut39aaxl0gl66y62285cnwe37gq0a96qaf4qgp5yqtw" -authorization = "signam1qpcvzjdqkvhud9lez3exq3vy7dnp4kyjgsk92yx5cslwzjs0q9czx8ajxztx5pftx9hsf9w2shh6rt0uv6xeyu30ljqkrqj6hnrwn5gqfd9pwf" +pk = "tpknam1qpg2tsrplvhu3fd7z7tq5ztc2ne3s7e2ahjl2a2cddufrzdyr752g666ytj" +authorization = "signam1qzyc89wynvm4n7eq7jglv4d8upaxu38mkkktykjjtgqygmk4sq97ffxermz5wpur4rqr8gk6fze5uvc4u7q4qzqsr285gungdyhv2acgna2ltq" [validator_account.consensus_key] -pk = "tpknam1qpudpptwfh9u5mhvksrguyqk6wvyhus0kf2cs9qr0xuq9k4fepldgqv3ztq" -authorization = "signam1qpuhmvgl330cr3acugaddhn6q9xdw3577h3mv9yszau2smxmn7yvmn2yplfym4sk30r2hz943989sd68umu70e4wsk5q6j2gzzjfg4q0qjvz6f" +pk = "tpknam1qr9u5py97pdmcvnrxhzuuv79ydv5rw7r9z402sucwt6h0lvmmmwqy2wrweg" +authorization = "signam1qzt7ww0q00punp93jrvtkq62n4rk8y5d90tllmlkzr0z7urwfdkn7z8ttne92utwskl6ves4qp66r60tg2xqr568ranwfhcm0665wncqq4t5gx" [validator_account.protocol_key] -pk = "tpknam1qzxs6kchkustgjxld3xz0u3c8gfnkvda042vp06auk6zfrru5hhxqqvyxq6" -authorization = "signam1qztaxmfgncmv5jn9tak0au2ryzxwxrlhn2qyfx4fgewuv5p7jelpfpqe9mlp7y73vsw7r8hu509swj8mumgryswu38m7mvxn9asqn0cq7aqvjp" +pk = "tpknam1qrenhfdphzpszlr7fzand6qgmppge430g3a2lquqzhz64fkve5mq2hdfjaa" +authorization = "signam1qqeaqzj9fu0xsu7pvrkwla5asxde2wak7fslst0p79vxxydt40tzdj54js7dmjvqs2quygqqwup8z2cfffvm86ff8cud6gzel9g40ycw25wp5d" [validator_account.tendermint_node_key] -pk = "tpknam1qzckzn2rc4pr26e0clxajgcllasr6tke4yqrsu7wskw89uka29zykram505" -authorization = "signam1qrgvyj39ljlequl20hx2mz9wpuyjl8lj826c0upy9agt4txuyyusuqkhdmm2aajglupssqcsx8nv62etua6vn0duzrucut4m74nmhscwy3knc3" +pk = "tpknam1qpgcgptcjl22hl2te2uqnp33aqjmvfaud3a3f3sgtxezg7uu5rsv6d2flr3" +authorization = "signam1qrq7x5e7svuddy8dyr3xpcdt6a07u6sky0n5qnv5z757g33t5zm3jnnh9uhh073g05n8jx8rmdu5r2djhwh6few6u329u9cld4c7ynsw2592h8" [validator_account.eth_hot_key] -pk = "tpknam1qyp8znkp023autwqh2cy6c6vhnz8vsm4p6w9ngpnnamqk6dj5w6ktxqjnd0qj" -authorization = "signam1q9fd4nkz8df5ajh6jrsn6mrt0apvn4266walr8pnczl0xtn847u6usdemslvusseerhrd6hftse8zfch5tlpmqp4y9xz3563mu0d26hnqq942mt2" +pk = "tpknam1qypnh98mexms8edj8rcwu0cayx0459p39dwzsffxrr394mf4cse707qcctyrx" +authorization = "signam1qyrvwveg76nrz2ppnsl0em82gcl4p90cqw8eadyzcvk59e2dx0jqja8ln9l9j79sxzhhh5gdggduz78vtthzj5nzs0xvpwhjuh3hymapqq07qxzm" [validator_account.eth_cold_key] -pk = "tpknam1qyp4aw7a07f4ltuq3f0c4sgyq3kzgh6z40w8jt40wl7uhfj7e3m3u9qr792xg" -authorization = "signam1qyqcc7wstsnuadu75jnwg8hxz34nglxj9h9yqyx2c4qqdpxw50ff60hu0swfj7xdkz34tgl9e50jlmzphkgtpw3gg0hsgp35lhsl6rmeqqq28kph" +pk = "tpknam1qypz8zr0w8lsz3s98vh4p974xuxeedpecj9s2l3326r3kdz4tc0snrcpnc8yv" +authorization = "signam1q992kq4ymfl6v8arc2s2tn0w7c4f48wx6fxry9qxv2qk8zvjan8q7j9rxg73cx0f5l56fy53x2jgwv7vy8jtxzucckdzgnxc5tpzajs4qq8r02r2" [[transfer]] token = "nam" @@ -48,7 +48,8 @@ signature = "signam1qz8ch7n6jp7g7hvnzkhmprhqc5umd0gatarlttm7gpcdx6g8hmgqffdq67fn source = "validator-0" validator = "validator-0" amount = "100000" -signature = "signam1qrd7wg2sdla73z7626r2ep8895d9ed4ljq37nz6kmy2rcm36yqjugw6vle7kl70l0d585t382s9vd28k2duwz0lu7ux0vua6aaarjssgdf46n2" +signature = "signam1qqukrz3js2pgzrne90u5f7y4mstrzvmzcq7eelml9m3lzrh9zwpf0vhgjq0rsw4ufj4ffdx8ew74uxkk4df649pg6qq5fgwyqa9mpfcyvskk67" + # 2. diff --git a/genesis/localnet/validity-predicates.toml b/genesis/localnet/validity-predicates.toml index 907e7c522b..0216abe982 100644 --- a/genesis/localnet/validity-predicates.toml +++ b/genesis/localnet/validity-predicates.toml @@ -8,7 +8,3 @@ filename = "vp_implicit.wasm" [wasm.vp_user] filename = "vp_user.wasm" -# Default validator VP -[wasm.vp_validator] -filename = "vp_validator.wasm" - diff --git a/genesis/starter/validity-predicates.toml b/genesis/starter/validity-predicates.toml index 9c9e76fc83..242cc1c5c5 100644 --- a/genesis/starter/validity-predicates.toml +++ b/genesis/starter/validity-predicates.toml @@ -8,10 +8,6 @@ filename = "vp_implicit.wasm" [wasm.vp_user] filename = "vp_user.wasm" -# Default validator VP -[wasm.vp_validator] -filename = "vp_validator.wasm" - # Token VP [wasm.vp_token] filename = "vp_token.wasm" diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index f5c0ae37fa..b7b549f5d6 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -3,7 +3,6 @@ extern crate alloc; pub use namada_core::{ibc, ibc_proto, proto, tendermint, tendermint_proto}; #[cfg(feature = "tendermint-rpc")] pub use tendermint_rpc; -use tx::{TX_INIT_ACCOUNT_WASM, VP_VALIDATOR_WASM}; pub use { bip39, borsh, masp_primitives, masp_proofs, namada_core as core, namada_proof_of_stake as proof_of_stake, zeroize, @@ -55,10 +54,10 @@ use crate::tx::{ ProcessTxResponse, TX_BOND_WASM, TX_BRIDGE_POOL_WASM, TX_CHANGE_COMMISSION_WASM, TX_CHANGE_CONSENSUS_KEY_WASM, TX_CHANGE_METADATA_WASM, TX_CLAIM_REWARDS_WASM, - TX_DEACTIVATE_VALIDATOR_WASM, TX_IBC_WASM, TX_INIT_PROPOSAL, - TX_INIT_VALIDATOR_WASM, TX_REACTIVATE_VALIDATOR_WASM, TX_REDELEGATE_WASM, - TX_RESIGN_STEWARD, TX_REVEAL_PK, TX_TRANSFER_WASM, TX_UNBOND_WASM, - TX_UNJAIL_VALIDATOR_WASM, TX_UPDATE_ACCOUNT_WASM, + TX_DEACTIVATE_VALIDATOR_WASM, TX_IBC_WASM, TX_INIT_ACCOUNT_WASM, + TX_INIT_PROPOSAL, TX_INIT_VALIDATOR_WASM, TX_REACTIVATE_VALIDATOR_WASM, + TX_REDELEGATE_WASM, TX_RESIGN_STEWARD, TX_REVEAL_PK, TX_TRANSFER_WASM, + TX_UNBOND_WASM, TX_UNJAIL_VALIDATOR_WASM, TX_UPDATE_ACCOUNT_WASM, TX_UPDATE_STEWARD_COMMISSION, TX_VOTE_PROPOSAL, TX_WITHDRAW_WASM, VP_USER_WASM, }; @@ -366,7 +365,7 @@ pub trait Namada<'a>: Sized { eth_cold_key: None, eth_hot_key: None, protocol_key: None, - validator_vp_code_path: PathBuf::from(VP_VALIDATOR_WASM), + validator_vp_code_path: PathBuf::from(VP_USER_WASM), unsafe_dont_encrypt: false, tx_code_path: PathBuf::from(TX_INIT_VALIDATOR_WASM), tx: self.tx_builder(), diff --git a/sdk/src/signing.rs b/sdk/src/signing.rs index 6784be92ba..c6262d9dd0 100644 --- a/sdk/src/signing.rs +++ b/sdk/src/signing.rs @@ -54,7 +54,6 @@ use crate::tx::{ TX_INIT_PROPOSAL, TX_INIT_VALIDATOR_WASM, TX_REACTIVATE_VALIDATOR_WASM, TX_REVEAL_PK, TX_TRANSFER_WASM, TX_UNBOND_WASM, TX_UNJAIL_VALIDATOR_WASM, TX_UPDATE_ACCOUNT_WASM, TX_VOTE_PROPOSAL, TX_WITHDRAW_WASM, VP_USER_WASM, - VP_VALIDATOR_WASM, }; pub use crate::wallet::store::AddressVpType; use crate::wallet::{Wallet, WalletIo}; @@ -1067,8 +1066,6 @@ pub async fn to_ledger_vector<'a>( })?; let vp_code = if extra.tag == Some(VP_USER_WASM.to_string()) { "User".to_string() - } else if extra.tag == Some(VP_VALIDATOR_WASM.to_string()) { - "Validator".to_string() } else { HEXLOWER.encode(&extra.code.hash().0) }; @@ -1113,8 +1110,6 @@ pub async fn to_ledger_vector<'a>( })?; let vp_code = if extra.tag == Some(VP_USER_WASM.to_string()) { "User".to_string() - } else if extra.tag == Some(VP_VALIDATOR_WASM.to_string()) { - "Validator".to_string() } else { HEXLOWER.encode(&extra.code.hash().0) }; @@ -1314,8 +1309,6 @@ pub async fn to_ledger_vector<'a>( })?; let vp_code = if extra.tag == Some(VP_USER_WASM.to_string()) { "User".to_string() - } else if extra.tag == Some(VP_VALIDATOR_WASM.to_string()) { - "Validator".to_string() } else { HEXLOWER.encode(&extra.code.hash().0) }; diff --git a/sdk/src/tx.rs b/sdk/src/tx.rs index 9378615890..e26bbff4e2 100644 --- a/sdk/src/tx.rs +++ b/sdk/src/tx.rs @@ -92,8 +92,6 @@ pub const TX_TRANSFER_WASM: &str = "tx_transfer.wasm"; pub const TX_IBC_WASM: &str = "tx_ibc.wasm"; /// User validity predicate WASM path pub const VP_USER_WASM: &str = "vp_user.wasm"; -/// Validator validity predicate WASM path -pub const VP_VALIDATOR_WASM: &str = "vp_validator.wasm"; /// Bond WASM path pub const TX_BOND_WASM: &str = "tx_bond.wasm"; /// Unbond WASM path diff --git a/wasm/wasm_source/Cargo.toml b/wasm/wasm_source/Cargo.toml index 8e8e3efe4e..c4025c1207 100644 --- a/wasm/wasm_source/Cargo.toml +++ b/wasm/wasm_source/Cargo.toml @@ -38,7 +38,6 @@ tx_resign_steward = ["namada_tx_prelude"] vp_implicit = ["namada_vp_prelude", "once_cell"] vp_token = ["namada_vp_prelude"] vp_user = ["namada_vp_prelude", "once_cell"] -vp_validator = ["namada_vp_prelude", "once_cell"] [dependencies] namada_tx_prelude = {path = "../../tx_prelude", optional = true} diff --git a/wasm/wasm_source/Makefile b/wasm/wasm_source/Makefile index 6772a2e739..2da935ba7c 100644 --- a/wasm/wasm_source/Makefile +++ b/wasm/wasm_source/Makefile @@ -29,7 +29,6 @@ wasms += tx_update_steward_commission wasms += tx_resign_steward wasms += vp_implicit wasms += vp_user -wasms += vp_validator # Build all wasms in release mode all: $(wasms) diff --git a/wasm/wasm_source/src/lib.rs b/wasm/wasm_source/src/lib.rs index ae3d121f2c..e44ac1564e 100644 --- a/wasm/wasm_source/src/lib.rs +++ b/wasm/wasm_source/src/lib.rs @@ -47,5 +47,3 @@ pub mod tx_withdraw; pub mod vp_implicit; #[cfg(feature = "vp_user")] pub mod vp_user; -#[cfg(feature = "vp_validator")] -pub mod vp_validator; diff --git a/wasm/wasm_source/src/vp_user.rs b/wasm/wasm_source/src/vp_user.rs index 28bfcbdc9f..c6b7d6920e 100644 --- a/wasm/wasm_source/src/vp_user.rs +++ b/wasm/wasm_source/src/vp_user.rs @@ -1,16 +1,20 @@ -//! A basic user VP. +//! A basic user VP supports both non-validator and validator accounts. //! //! This VP currently provides a signature verification against a public key for //! sending tokens (receiving tokens is permissive). //! //! It allows to bond, unbond and withdraw tokens to and from PoS system with a -//! valid signature. +//! valid signature(s). +//! +//! For validator a tx to change a validator's commission rate or metadata +//! requires a valid signature(s) only from the validator. //! //! Any other storage key changes are allowed only with a valid signature. use namada_vp_prelude::storage::KeySeg; use namada_vp_prelude::*; use once_cell::unsync::Lazy; +use proof_of_stake::types::ValidatorState; enum KeyType<'a> { Token { owner: &'a Address }, @@ -104,14 +108,14 @@ fn validate_tx( } } KeyType::PoS => { - // Allow the account to be used in PoS + // Bond or unbond let bond_id = proof_of_stake::storage::is_bond_key(key) .map(|(bond_id, _)| bond_id) .or_else(|| { proof_of_stake::storage::is_unbond_key(key) .map(|(bond_id, _, _)| bond_id) }); - let valid = match bond_id { + let valid_bond_or_unbond_change = match bond_id { Some(bond_id) => { // Bonds and unbonds changes for this address // must be signed @@ -122,12 +126,81 @@ fn validate_tx( true } }; - debug_log!( - "PoS key {} {}", - key, - if valid { "accepted" } else { "rejected" } - ); - valid + // Commission rate changes must be signed by the validator + let comm = + proof_of_stake::storage::is_validator_commission_rate_key( + key, + ); + let valid_commission_rate_change = match comm { + Some((validator, _epoch)) => { + *validator == addr && *valid_sig + } + None => true, + }; + // Metadata changes must be signed by the validator whose + // metadata is manipulated + let metadata = + proof_of_stake::storage::is_validator_metadata_key(key); + let valid_metadata_change = match metadata { + Some(address) => *address == addr && *valid_sig, + None => true, + }; + + // Changes due to unjailing, deactivating, and reactivating are + // marked by changes in validator state + let state_change = + proof_of_stake::storage::is_validator_state_key(key); + let valid_state_change = match state_change { + Some((address, epoch)) => { + let params_pre = + proof_of_stake::read_pos_params(&ctx.pre())?; + let state_pre = + proof_of_stake::validator_state_handle(address) + .get(&ctx.pre(), epoch, ¶ms_pre)?; + + let params_post = + proof_of_stake::read_pos_params(&ctx.post())?; + let state_post = + proof_of_stake::validator_state_handle(address) + .get(&ctx.post(), epoch, ¶ms_post)?; + + match (state_pre, state_post) { + (Some(pre), Some(post)) => { + if + // Deactivation case + (matches!( + pre, + ValidatorState::Consensus + | ValidatorState::BelowCapacity + | ValidatorState::BelowThreshold + ) && post == ValidatorState::Inactive) + // Reactivation case + || pre == ValidatorState::Inactive + && post != ValidatorState::Inactive + // Unjail case + || pre == ValidatorState::Jailed + && matches!( + post, + ValidatorState::Consensus + | ValidatorState::BelowCapacity + | ValidatorState::BelowThreshold + ) + { + *address == addr && *valid_sig + } else { + true + } + } + _ => true, + } + } + None => true, + }; + + valid_bond_or_unbond_change + && valid_commission_rate_change + && valid_state_change + && valid_metadata_change } KeyType::GovernanceVote(voter) => { if voter == &addr { @@ -398,10 +471,10 @@ mod tests { ); } - /// Test that a PoS action that must be authorized is rejected without a - /// valid signature. + /// Test that a non-validator PoS action that must be authorized is rejected + /// without a valid signature. #[test] - fn test_unsigned_pos_action_rejected() { + fn test_unsigned_non_validator_pos_action_rejected() { // Init PoS genesis let pos_params = PosParams::default(); let validator = address::testing::established_address_3(); @@ -454,7 +527,7 @@ mod tests { // be able to transfer from it tx_env.credit_tokens(&vp_owner, &token, amount); - // Initialize VP environment from a transaction + // Initialize VP environment from non-validator PoS actions vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |_address| { // Bond the tokens, then unbond some of them tx::ctx() @@ -478,10 +551,100 @@ mod tests { ); } - /// Test that a PoS action that must be authorized is accepted with a valid - /// signature. + /// Test that a validator PoS action that must be authorized is rejected + /// without a valid signature. + #[test] + fn test_unsigned_validator_pos_action_rejected() { + // Init PoS genesis + let pos_params = PosParams::default(); + let validator = address::testing::established_address_3(); + let initial_stake = token::Amount::from_uint(10_098_123, 0).unwrap(); + let consensus_key = key::testing::keypair_2().ref_to(); + let protocol_key = key::testing::keypair_1().ref_to(); + let eth_cold_key = key::testing::keypair_3().ref_to(); + let eth_hot_key = key::testing::keypair_4().ref_to(); + let commission_rate = Dec::new(5, 2).unwrap(); + let max_commission_rate_change = Dec::new(1, 2).unwrap(); + + let genesis_validators = [GenesisValidator { + address: validator.clone(), + tokens: initial_stake, + consensus_key, + protocol_key, + commission_rate, + max_commission_rate_change, + eth_hot_key, + eth_cold_key, + metadata: Default::default(), + }]; + + init_pos(&genesis_validators[..], &pos_params, Epoch(0)); + + // Initialize a tx environment + let mut tx_env = tx_host_env::take(); + + let secret_key = key::testing::keypair_1(); + let public_key = secret_key.ref_to(); + let target = address::testing::established_address_3(); + let token = address::nam(); + let amount = token::Amount::from_uint(10_098_123, 0).unwrap(); + let bond_amount = token::Amount::from_uint(5_098_123, 0).unwrap(); + let unbond_amount = token::Amount::from_uint(3_098_123, 0).unwrap(); + + // Spawn the accounts to be able to modify their storage + tx_env.spawn_accounts([&target, &token]); + tx_env.init_account_storage(&validator, vec![public_key], 1); + // write the denomination of NAM into storage + storage_api::token::write_denom( + &mut tx_env.wl_storage, + &token, + token::NATIVE_MAX_DECIMAL_PLACES.into(), + ) + .unwrap(); + + // Credit the tokens to the validator before running the transaction to + // be able to transfer from it + tx_env.credit_tokens(&validator, &token, amount); + + // Validator PoS actions + vp_host_env::init_from_tx(validator.clone(), tx_env, |_address| { + // Bond the tokens, then unbond some of them + tx::ctx() + .bond_tokens(Some(&validator), &validator, bond_amount) + .unwrap(); + tx::ctx() + .unbond_tokens(Some(&validator), &validator, unbond_amount) + .unwrap(); + tx::ctx().deactivate_validator(&validator).unwrap(); + tx::ctx() + .change_validator_metadata( + &validator, + Some("email".to_owned()), + Some("desc".to_owned()), + Some("website".to_owned()), + Some("discord".to_owned()), + Some(Dec::new(6, 2).unwrap()), + ) + .unwrap(); + }); + + let vp_env = vp_host_env::take(); + let mut tx_data = Tx::from_type(TxType::Raw); + tx_data.set_data(Data::new(vec![])); + let keys_changed: BTreeSet = + vp_env.all_touched_storage_keys(); + let verifiers: BTreeSet
= BTreeSet::default(); + vp_host_env::set(vp_env); + assert!( + !validate_tx(&CTX, tx_data, validator, keys_changed, verifiers) + .unwrap() + ); + } + + /// Test that a non-validator PoS action that must be authorized is accepted + /// with a valid signature. #[test] - fn test_signed_pos_action_accepted() { + fn test_signed_non_validator_pos_action_accepted() { // Init PoS genesis let pos_params = PosParams::default(); let validator = address::testing::established_address_3(); @@ -539,7 +702,7 @@ mod tests { // be able to transfer from it tx_env.credit_tokens(&vp_owner, &token, amount); - // Initialize VP environment from a transaction + // Initialize VP environment from non-validator PoS actions vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |_address| { // Bond the tokens, then unbond some of them tx::ctx() @@ -573,6 +736,111 @@ mod tests { ); } + /// Test that a validator PoS action that must be authorized is accepted + /// with a valid signature. + #[test] + fn test_signed_validator_pos_action_accepted() { + // Init PoS genesis + let pos_params = PosParams::default(); + let validator = address::testing::established_address_3(); + let initial_stake = token::Amount::from_uint(10_098_123, 0).unwrap(); + let consensus_key = key::testing::keypair_2().ref_to(); + let protocol_key = key::testing::keypair_1().ref_to(); + let commission_rate = Dec::new(5, 2).unwrap(); + let max_commission_rate_change = Dec::new(1, 2).unwrap(); + + let genesis_validators = [GenesisValidator { + address: validator.clone(), + tokens: initial_stake, + consensus_key, + protocol_key, + commission_rate, + max_commission_rate_change, + eth_hot_key: key::common::PublicKey::Secp256k1( + key::testing::gen_keypair::() + .ref_to(), + ), + eth_cold_key: key::common::PublicKey::Secp256k1( + key::testing::gen_keypair::() + .ref_to(), + ), + metadata: Default::default(), + }]; + + init_pos(&genesis_validators[..], &pos_params, Epoch(0)); + + // Initialize a tx environment + let mut tx_env = tx_host_env::take(); + + let secret_key = key::testing::keypair_1(); + let public_key = secret_key.ref_to(); + let target = address::testing::established_address_3(); + let token = address::nam(); + let amount = token::Amount::from_uint(10_098_123, 0).unwrap(); + let bond_amount = token::Amount::from_uint(5_098_123, 0).unwrap(); + let unbond_amount = token::Amount::from_uint(3_098_123, 0).unwrap(); + + // Spawn the accounts to be able to modify their storage + tx_env.spawn_accounts([&target, &token]); + tx_env.init_account_storage(&validator, vec![public_key.clone()], 1); + + // write the denomination of NAM into storage + storage_api::token::write_denom( + &mut tx_env.wl_storage, + &token, + token::NATIVE_MAX_DECIMAL_PLACES.into(), + ) + .unwrap(); + + // Credit the tokens to the VP owner before running the transaction to + // be able to transfer from it + tx_env.credit_tokens(&validator, &token, amount); + + // Validator PoS actions + vp_host_env::init_from_tx(validator.clone(), tx_env, |_address| { + // Bond the tokens, then unbond some of them + tx::ctx() + .bond_tokens(Some(&validator), &validator, bond_amount) + .unwrap(); + tx::ctx() + .unbond_tokens(Some(&validator), &validator, unbond_amount) + .unwrap(); + tx::ctx().deactivate_validator(&validator).unwrap(); + tx::ctx() + .change_validator_metadata( + &validator, + Some("email".to_owned()), + Some("desc".to_owned()), + Some("website".to_owned()), + Some("discord".to_owned()), + Some(Dec::new(6, 2).unwrap()), + ) + .unwrap(); + }); + + let pks_map = AccountPublicKeysMap::from_iter(vec![public_key]); + + let mut vp_env = vp_host_env::take(); + let mut tx = vp_env.tx.clone(); + tx.set_data(Data::new(vec![])); + tx.set_code(Code::new(vec![], None)); + tx.add_section(Section::Signature(Signature::new( + vec![tx.raw_header_hash()], + pks_map.index_secret_keys(vec![secret_key]), + None, + ))); + let signed_tx = tx.clone(); + vp_env.tx = signed_tx.clone(); + let keys_changed: BTreeSet = + vp_env.all_touched_storage_keys(); + let verifiers: BTreeSet
= BTreeSet::default(); + vp_host_env::set(vp_env); + assert!( + validate_tx(&CTX, signed_tx, validator, keys_changed, verifiers) + .unwrap() + ); + } + /// Test that a transfer on with accounts other than self is accepted. #[test] fn test_transfer_between_other_parties_accepted() { diff --git a/wasm/wasm_source/src/vp_validator.rs b/wasm/wasm_source/src/vp_validator.rs deleted file mode 100644 index 2c104c13d8..0000000000 --- a/wasm/wasm_source/src/vp_validator.rs +++ /dev/null @@ -1,1135 +0,0 @@ -//! A basic validator VP. -//! -//! Like the user VP, this VP currently provides a signature verification -//! against a public key for sending tokens (receiving tokens is permissive). -//! -//! It allows to bond, unbond and withdraw tokens to and from PoS system with a -//! valid signature. -//! -//! Currently, the only difference with respect to the user VP is for a tx to -//! change a validator's commission rate: we require a valid signature only from -//! the validator whose commission rate is being changed. -//! -//! Any other storage key changes are allowed only with a valid signature. - -use namada_vp_prelude::storage::KeySeg; -use namada_vp_prelude::*; -use once_cell::unsync::Lazy; -use proof_of_stake::types::ValidatorState; - -enum KeyType<'a> { - Token { owner: &'a Address }, - PoS, - Vp(&'a Address), - PgfStward(&'a Address), - GovernanceVote(&'a Address), - Unknown, -} - -impl<'a> From<&'a storage::Key> for KeyType<'a> { - fn from(key: &'a storage::Key) -> KeyType<'a> { - if let Some([_, owner]) = token::is_any_token_balance_key(key) { - Self::Token { owner } - } else if proof_of_stake::storage::is_pos_key(key) { - Self::PoS - } else if gov_storage::keys::is_vote_key(key) { - let voter_address = gov_storage::keys::get_voter_address(key); - if let Some(address) = voter_address { - Self::GovernanceVote(address) - } else { - Self::Unknown - } - } else if let Some(address) = pgf_storage::keys::is_stewards_key(key) { - Self::PgfStward(address) - } else if let Some(address) = key.is_validity_predicate() { - Self::Vp(address) - } else { - Self::Unknown - } - } -} - -#[validity_predicate(gas = 134761)] -fn validate_tx( - ctx: &Ctx, - tx_data: Tx, - addr: Address, - keys_changed: BTreeSet, - verifiers: BTreeSet
, -) -> VpResult { - debug_log!( - "vp_validator called with user addr: {}, key_changed: {:?}, \ - verifiers: {:?}", - addr, - keys_changed, - verifiers - ); - - let valid_sig = Lazy::new(|| { - matches!(verify_signatures(ctx, &tx_data, &addr), Ok(true)) - }); - - if !is_valid_tx(ctx, &tx_data)? { - return reject(); - } - - for key in keys_changed.iter() { - let key_type: KeyType = key.into(); - let is_valid = match key_type { - KeyType::Token { owner, .. } => { - if owner == &addr { - let pre: token::Amount = - ctx.read_pre(key)?.unwrap_or_default(); - let post: token::Amount = - ctx.read_post(key)?.unwrap_or_default(); - let change = post.change() - pre.change(); - // debit has to signed, credit doesn't - let valid = change.non_negative() || *valid_sig; - debug_log!( - "token key: {}, change: {:?}, valid_sig: {}, valid \ - modification: {}", - key, - change, - *valid_sig, - valid - ); - valid - } else { - debug_log!( - "This address ({}) is not of owner ({}) of token key: \ - {}", - addr, - owner, - key - ); - // If this is not the owner, allow any change - true - } - } - KeyType::PoS => { - // Bond or unbond - let bond_id = proof_of_stake::storage::is_bond_key(key) - .map(|(bond_id, _)| bond_id) - .or_else(|| { - proof_of_stake::storage::is_unbond_key(key) - .map(|(bond_id, _, _)| bond_id) - }); - let valid_bond_or_unbond_change = match bond_id { - Some(bond_id) => { - // Bonds and unbonds changes for this address - // must be signed - bond_id.source != addr || *valid_sig - } - None => { - // Any other PoS changes are allowed without signature - true - } - }; - // Commission rate changes must be signed by the validator - let comm = - proof_of_stake::storage::is_validator_commission_rate_key( - key, - ); - let valid_commission_rate_change = match comm { - Some((validator, _epoch)) => { - *validator == addr && *valid_sig - } - None => true, - }; - // Metadata changes must be signed by the validator whose - // metadata is manipulated - let metadata = - proof_of_stake::storage::is_validator_metadata_key(key); - let valid_metadata_change = match metadata { - Some(address) => *address == addr && *valid_sig, - None => true, - }; - - // Changes due to unjailing, deactivating, and reactivating are - // marked by changes in validator state - let state_change = - proof_of_stake::storage::is_validator_state_key(key); - let valid_state_change = match state_change { - Some((address, epoch)) => { - let params_pre = - proof_of_stake::read_pos_params(&ctx.pre())?; - let state_pre = - proof_of_stake::validator_state_handle(address) - .get(&ctx.pre(), epoch, ¶ms_pre)?; - - let params_post = - proof_of_stake::read_pos_params(&ctx.post())?; - let state_post = - proof_of_stake::validator_state_handle(address) - .get(&ctx.post(), epoch, ¶ms_post)?; - - match (state_pre, state_post) { - (Some(pre), Some(post)) => { - if - // Deactivation case - (matches!( - pre, - ValidatorState::Consensus - | ValidatorState::BelowCapacity - | ValidatorState::BelowThreshold - ) && post == ValidatorState::Inactive) - // Reactivation case - || pre == ValidatorState::Inactive - && post != ValidatorState::Inactive - // Unjail case - || pre == ValidatorState::Jailed - && matches!( - post, - ValidatorState::Consensus - | ValidatorState::BelowCapacity - | ValidatorState::BelowThreshold - ) - { - *address == addr && *valid_sig - } else { - true - } - } - _ => true, - } - } - None => true, - }; - - let valid = valid_bond_or_unbond_change - && valid_commission_rate_change - && valid_state_change - && valid_metadata_change; - debug_log!( - "PoS key {} {}", - key, - if valid { "accepted" } else { "rejected" } - ); - valid - } - KeyType::GovernanceVote(voter) => { - if voter == &addr { - *valid_sig - } else { - true - } - } - KeyType::PgfStward(address) => { - if address == &addr { - *valid_sig - } else { - true - } - } - KeyType::Vp(owner) => { - let has_post: bool = ctx.has_key_post(key)?; - if owner == &addr { - if has_post { - let vp_hash: Vec = - ctx.read_bytes_post(key)?.unwrap(); - *valid_sig && is_vp_whitelisted(ctx, &vp_hash)? - } else { - false - } - } else { - let vp_hash: Vec = ctx.read_bytes_post(key)?.unwrap(); - is_vp_whitelisted(ctx, &vp_hash)? - } - } - KeyType::Unknown => { - if key.segments.get(0) == Some(&addr.to_db_key()) { - // Unknown changes to this address space require a valid - // signature - *valid_sig - } else { - // Unknown changes anywhere else are permitted - true - } - } - }; - if !is_valid { - debug_log!("key {} modification failed vp", key); - return reject(); - } - } - - accept() -} - -#[cfg(test)] -mod tests { - use address::testing::arb_non_internal_address; - use namada::ledger::pos::{GenesisValidator, OwnedPosParams}; - use namada::proto::{Code, Data, Signature}; - use namada::types::dec::Dec; - use namada::types::storage::Epoch; - use namada::types::transaction::TxType; - use namada_test_utils::TestWasms; - // Use this as `#[test]` annotation to enable logging - use namada_tests::log::test; - use namada_tests::native_vp::pos::init_pos; - use namada_tests::tx::{self, tx_host_env, TestTxEnv}; - use namada_tests::vp::vp_host_env::storage::Key; - use namada_tests::vp::*; - use namada_tx_prelude::{StorageWrite, TxEnv}; - use namada_vp_prelude::account::AccountPublicKeysMap; - use namada_vp_prelude::key::RefTo; - use proptest::prelude::*; - use storage::testing::arb_account_storage_key_no_vp; - - use super::*; - - /// Test that no-op transaction (i.e. no storage modifications) accepted. - #[test] - fn test_no_op_transaction() { - let mut tx_data = Tx::from_type(TxType::Raw); - tx_data.set_data(Data::new(vec![])); - let addr: Address = address::testing::established_address_1(); - let keys_changed: BTreeSet = BTreeSet::default(); - let verifiers: BTreeSet
= BTreeSet::default(); - - // The VP env must be initialized before calling `validate_tx` - vp_host_env::init(); - - assert!( - validate_tx(&CTX, tx_data, addr, keys_changed, verifiers).unwrap() - ); - } - - /// Test that a credit transfer is accepted. - #[test] - fn test_credit_transfer_accepted() { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - - let vp_owner = address::testing::established_address_1(); - let source = address::testing::established_address_2(); - let token = address::nam(); - let amount = token::Amount::from_uint(10_098_123, 0).unwrap(); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&vp_owner, &source, &token]); - - // Credit the tokens to the source before running the transaction to be - // able to transfer from it - tx_env.credit_tokens(&source, &token, amount); - // write the denomination of NAM into storage - storage_api::token::write_denom( - &mut tx_env.wl_storage, - &token, - token::NATIVE_MAX_DECIMAL_PLACES.into(), - ) - .unwrap(); - - let amount = token::DenominatedAmount { - amount, - denom: token::NATIVE_MAX_DECIMAL_PLACES.into(), - }; - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { - // Apply transfer in a transaction - tx_host_env::token::transfer( - tx::ctx(), - &source, - address, - &token, - amount, - ) - .unwrap(); - }); - - let vp_env = vp_host_env::take(); - let mut tx_data = Tx::from_type(TxType::Raw); - tx_data.set_data(Data::new(vec![])); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - validate_tx(&CTX, tx_data, vp_owner, keys_changed, verifiers) - .unwrap() - ); - } - - /// Test that a debit transfer without a valid signature is rejected. - #[test] - fn test_unsigned_debit_transfer_rejected() { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - - let vp_owner = address::testing::established_address_1(); - let target = address::testing::established_address_2(); - let token = address::nam(); - let amount = token::Amount::from_uint(10_098_123, 0).unwrap(); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&vp_owner, &target, &token]); - - // Credit the tokens to the VP owner before running the transaction to - // be able to transfer from it - tx_env.credit_tokens(&vp_owner, &token, amount); - let amount = token::DenominatedAmount { - amount, - denom: token::NATIVE_MAX_DECIMAL_PLACES.into(), - }; - // write the denomination of NAM into storage - storage_api::token::write_denom( - &mut tx_env.wl_storage, - &token, - token::NATIVE_MAX_DECIMAL_PLACES.into(), - ) - .unwrap(); - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { - // Apply transfer in a transaction - tx_host_env::token::transfer( - tx::ctx(), - address, - &target, - &token, - amount, - ) - .unwrap(); - }); - - let vp_env = vp_host_env::take(); - let mut tx_data = Tx::from_type(TxType::Raw); - tx_data.set_data(Data::new(vec![])); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - !validate_tx(&CTX, tx_data, vp_owner, keys_changed, verifiers) - .unwrap() - ); - } - - /// Test that a debit transfer with a valid signature is accepted. - #[test] - fn test_signed_debit_transfer_accepted() { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - - let vp_owner = address::testing::established_address_1(); - let keypair = key::testing::keypair_1(); - let public_key = keypair.ref_to(); - let target = address::testing::established_address_2(); - let token = address::nam(); - let amount = token::Amount::from_uint(10_098_123, 0).unwrap(); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&vp_owner, &target, &token]); - tx_env.init_account_storage(&vp_owner, vec![public_key.clone()], 1); - - // Credit the tokens to the VP owner before running the transaction to - // be able to transfer from it - tx_env.credit_tokens(&vp_owner, &token, amount); - // write the denomination of NAM into storage - storage_api::token::write_denom( - &mut tx_env.wl_storage, - &token, - token::NATIVE_MAX_DECIMAL_PLACES.into(), - ) - .unwrap(); - - let amount = token::DenominatedAmount { - amount, - denom: token::NATIVE_MAX_DECIMAL_PLACES.into(), - }; - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { - // Apply transfer in a transaction - tx_host_env::token::transfer( - tx::ctx(), - address, - &target, - &token, - amount, - ) - .unwrap(); - }); - - let pks_map = AccountPublicKeysMap::from_iter(vec![public_key]); - - let mut vp_env = vp_host_env::take(); - let mut tx = vp_env.tx.clone(); - tx.set_data(Data::new(vec![])); - tx.set_code(Code::new(vec![], None)); - tx.add_section(Section::Signature(Signature::new( - vec![tx.raw_header_hash()], - pks_map.index_secret_keys(vec![keypair]), - None, - ))); - let signed_tx = tx.clone(); - vp_env.tx = signed_tx.clone(); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - validate_tx(&CTX, signed_tx, vp_owner, keys_changed, verifiers) - .unwrap() - ); - } - - /// Test that a PoS action that must be authorized is rejected without a - /// valid signature. - #[test] - fn test_unsigned_pos_action_rejected() { - // Init PoS genesis - let pos_params = OwnedPosParams::default(); - let validator = address::testing::established_address_3(); - let initial_stake = token::Amount::from_uint(10_098_123, 0).unwrap(); - let consensus_key = key::testing::keypair_2().ref_to(); - let protocol_key = key::testing::keypair_1().ref_to(); - let eth_cold_key = key::testing::keypair_3().ref_to(); - let eth_hot_key = key::testing::keypair_4().ref_to(); - let commission_rate = Dec::new(5, 2).unwrap(); - let max_commission_rate_change = Dec::new(1, 2).unwrap(); - - let genesis_validators = [GenesisValidator { - address: validator.clone(), - tokens: initial_stake, - consensus_key, - protocol_key, - commission_rate, - max_commission_rate_change, - eth_hot_key, - eth_cold_key, - metadata: Default::default(), - }]; - - init_pos(&genesis_validators[..], &pos_params, Epoch(0)); - - // Initialize a tx environment - let mut tx_env = tx_host_env::take(); - - let secret_key = key::testing::keypair_1(); - let public_key = secret_key.ref_to(); - let vp_owner: Address = address::testing::established_address_2(); - let target = address::testing::established_address_3(); - let token = address::nam(); - let amount = token::Amount::from_uint(10_098_123, 0).unwrap(); - let bond_amount = token::Amount::from_uint(5_098_123, 0).unwrap(); - let unbond_amount = token::Amount::from_uint(3_098_123, 0).unwrap(); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&target, &token]); - tx_env.init_account_storage(&vp_owner, vec![public_key], 1); - - // Credit the tokens to the VP owner before running the transaction to - // be able to transfer from it - tx_env.credit_tokens(&vp_owner, &token, amount); - // write the denomination of NAM into storage - storage_api::token::write_denom( - &mut tx_env.wl_storage, - &token, - token::NATIVE_MAX_DECIMAL_PLACES.into(), - ) - .unwrap(); - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |_address| { - // Bond the tokens, then unbond some of them - tx::ctx() - .bond_tokens(Some(&vp_owner), &validator, bond_amount) - .unwrap(); - tx::ctx() - .unbond_tokens(Some(&vp_owner), &validator, unbond_amount) - .unwrap(); - tx::ctx() - .change_validator_commission_rate( - &validator, - &Dec::new(6, 2).unwrap(), - ) - .unwrap(); - }); - - let vp_env = vp_host_env::take(); - let mut tx_data = Tx::from_type(TxType::Raw); - tx_data.set_data(Data::new(vec![])); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - !validate_tx(&CTX, tx_data, vp_owner, keys_changed, verifiers) - .unwrap() - ); - } - - /// Test that a PoS action that must be authorized is accepted with a valid - /// signature. - #[test] - fn test_signed_pos_action_accepted() { - // Init PoS genesis - let pos_params = OwnedPosParams::default(); - let validator = address::testing::established_address_3(); - let initial_stake = token::Amount::from_uint(10_098_123, 0).unwrap(); - let consensus_key = key::testing::keypair_2().ref_to(); - let protocol_key = key::testing::keypair_1().ref_to(); - let commission_rate = Dec::new(5, 2).unwrap(); - let max_commission_rate_change = Dec::new(1, 2).unwrap(); - - let genesis_validators = [GenesisValidator { - address: validator.clone(), - tokens: initial_stake, - consensus_key, - protocol_key, - commission_rate, - max_commission_rate_change, - eth_hot_key: key::common::PublicKey::Secp256k1( - key::testing::gen_keypair::() - .ref_to(), - ), - eth_cold_key: key::common::PublicKey::Secp256k1( - key::testing::gen_keypair::() - .ref_to(), - ), - metadata: Default::default(), - }]; - - init_pos(&genesis_validators[..], &pos_params, Epoch(0)); - - // Initialize a tx environment - let mut tx_env = tx_host_env::take(); - - let secret_key = key::testing::keypair_1(); - let public_key = secret_key.ref_to(); - let target = address::testing::established_address_3(); - let token = address::nam(); - let amount = token::Amount::from_uint(10_098_123, 0).unwrap(); - let bond_amount = token::Amount::from_uint(5_098_123, 0).unwrap(); - let unbond_amount = token::Amount::from_uint(3_098_123, 0).unwrap(); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&validator, &target, &token]); - tx_env.init_account_storage(&validator, vec![public_key.clone()], 1); - - // Credit the tokens to the VP owner before running the transaction to - // be able to transfer from it - tx_env.credit_tokens(&validator, &token, amount); - // write the denomination of NAM into storage - storage_api::token::write_denom( - &mut tx_env.wl_storage, - &token, - token::NATIVE_MAX_DECIMAL_PLACES.into(), - ) - .unwrap(); - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(validator.clone(), tx_env, |_address| { - // Bond the tokens, then unbond some of them - tx::ctx() - .bond_tokens(Some(&validator), &validator, bond_amount) - .unwrap(); - tx::ctx() - .unbond_tokens(Some(&validator), &validator, unbond_amount) - .unwrap(); - tx::ctx().deactivate_validator(&validator).unwrap(); - tx::ctx() - .change_validator_metadata( - &validator, - Some("email".to_owned()), - Some("desc".to_owned()), - Some("website".to_owned()), - Some("discord".to_owned()), - Some(Dec::new(6, 2).unwrap()), - ) - .unwrap(); - }); - - let pks_map = AccountPublicKeysMap::from_iter(vec![public_key]); - - let mut vp_env = vp_host_env::take(); - let mut tx = vp_env.tx.clone(); - tx.set_data(Data::new(vec![])); - tx.set_code(Code::new(vec![], None)); - tx.add_section(Section::Signature(Signature::new( - vec![tx.raw_header_hash()], - pks_map.index_secret_keys(vec![secret_key]), - None, - ))); - let signed_tx = tx.clone(); - vp_env.tx = signed_tx.clone(); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - validate_tx(&CTX, signed_tx, validator, keys_changed, verifiers) - .unwrap() - ); - } - - /// Test that a transfer on with accounts other than self is accepted. - #[test] - fn test_transfer_between_other_parties_accepted() { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - - let vp_owner = address::testing::established_address_1(); - let source = address::testing::established_address_2(); - let target = address::testing::established_address_3(); - let token = address::nam(); - let amount = token::Amount::from_uint(10_098_123, 0).unwrap(); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&vp_owner, &source, &target, &token]); - - // Credit the tokens to the VP owner before running the transaction to - // be able to transfer from it - tx_env.credit_tokens(&source, &token, amount); - let amount = token::DenominatedAmount { - amount, - denom: token::NATIVE_MAX_DECIMAL_PLACES.into(), - }; - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { - tx::ctx().insert_verifier(address).unwrap(); - // Apply transfer in a transaction - tx_host_env::token::transfer( - tx::ctx(), - &source, - &target, - &token, - amount, - ) - .unwrap(); - }); - - let vp_env = vp_host_env::take(); - let mut tx_data = Tx::from_type(TxType::Raw); - tx_data.set_data(Data::new(vec![])); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - validate_tx(&CTX, tx_data, vp_owner, keys_changed, verifiers) - .unwrap() - ); - } - - prop_compose! { - /// Generates an account address and a storage key inside its storage. - fn arb_account_storage_subspace_key() - // Generate an address - (address in arb_non_internal_address()) - // Generate a storage key other than its VP key (VP cannot be - // modified directly via `write`, it has to be modified via - // `tx::update_validity_predicate`. - (storage_key in arb_account_storage_key_no_vp(address.clone()), - // Use the generated address too - address in Just(address)) - -> (Address, Key) { - (address, storage_key) - } - } - - proptest! { - /// Test that an unsigned tx that performs arbitrary storage writes or - /// deletes to the account is rejected. - #[test] - fn test_unsigned_arb_storage_write_rejected( - (vp_owner, storage_key) in arb_account_storage_subspace_key(), - // Generate bytes to write. If `None`, delete from the key instead - storage_value in any::>>(), - ) { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - - // Spawn all the accounts in the storage key to be able to modify - // their storage - let storage_key_addresses = storage_key.find_addresses(); - tx_env.spawn_accounts(storage_key_addresses); - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |_address| { - // Write or delete some data in the transaction - if let Some(value) = &storage_value { - tx::ctx().write(&storage_key, value).unwrap(); - } else { - tx::ctx().delete(&storage_key).unwrap(); - } - }); - - let vp_env = vp_host_env::take(); - let mut tx_data = Tx::from_type(TxType::Raw); - tx_data.set_data(Data::new(vec![])); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!(!validate_tx(&CTX, tx_data, vp_owner, keys_changed, verifiers).unwrap()); - } - } - - proptest! { - /// Test that a signed tx that performs arbitrary storage writes or - /// deletes to the account is accepted. - #[test] - fn test_signed_arb_storage_write( - (vp_owner, storage_key) in arb_account_storage_subspace_key(), - // Generate bytes to write. If `None`, delete from the key instead - storage_value in any::>>(), - ) { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - - let keypair = key::testing::keypair_1(); - let public_key = keypair.ref_to(); - - // Spawn all the accounts in the storage key to be able to modify - // their storage - let storage_key_addresses = storage_key.find_addresses(); - tx_env.spawn_accounts(storage_key_addresses); - - tx_env.init_account_storage(&vp_owner, vec![public_key.clone()], 1); - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |_address| { - // Write or delete some data in the transaction - if let Some(value) = &storage_value { - tx::ctx().write(&storage_key, value).unwrap(); - } else { - tx::ctx().delete(&storage_key).unwrap(); - } - }); - - let pks_map = AccountPublicKeysMap::from_iter(vec![public_key]); - - let mut vp_env = vp_host_env::take(); - let mut tx = vp_env.tx.clone(); - tx.set_data(Data::new(vec![])); - tx.set_code(Code::new(vec![], None)); - tx.add_section(Section::Signature(Signature::new( - vec![tx.raw_header_hash()], - pks_map.index_secret_keys(vec![keypair]), - None, - ))); - let signed_tx = tx.clone(); - vp_env.tx = signed_tx.clone(); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!(validate_tx(&CTX, signed_tx, vp_owner, keys_changed, verifiers).unwrap()); - } - } - - /// Test that a validity predicate update without a valid signature is - /// rejected. - #[test] - fn test_unsigned_vp_update_rejected() { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - - let vp_owner = address::testing::established_address_1(); - let vp_code = TestWasms::VpAlwaysTrue.read_bytes(); - let vp_hash = sha256(&vp_code); - // for the update - tx_env.store_wasm_code(vp_code); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&vp_owner]); - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { - // Update VP in a transaction - tx::ctx() - .update_validity_predicate(address, vp_hash, &None) - .unwrap(); - }); - - let vp_env = vp_host_env::take(); - let mut tx_data = Tx::from_type(TxType::Raw); - tx_data.set_data(Data::new(vec![])); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - !validate_tx(&CTX, tx_data, vp_owner, keys_changed, verifiers) - .unwrap() - ); - } - - /// Test that a validity predicate update with a valid signature is - /// accepted. - #[test] - fn test_signed_vp_update_accepted() { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - tx_env.init_parameters(None, None, None, None); - - let vp_owner = address::testing::established_address_1(); - let keypair = key::testing::keypair_1(); - let public_key = keypair.ref_to(); - let vp_code = TestWasms::VpAlwaysTrue.read_bytes(); - let vp_hash = sha256(&vp_code); - // for the update - tx_env.store_wasm_code(vp_code); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&vp_owner]); - tx_env.init_account_storage(&vp_owner, vec![public_key.clone()], 1); - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { - // Update VP in a transaction - tx::ctx() - .update_validity_predicate(address, vp_hash, &None) - .unwrap(); - }); - - let pks_map = AccountPublicKeysMap::from_iter(vec![public_key]); - - let mut vp_env = vp_host_env::take(); - let mut tx = vp_env.tx.clone(); - tx.set_data(Data::new(vec![])); - tx.set_code(Code::new(vec![], None)); - tx.add_section(Section::Signature(Signature::new( - vec![tx.raw_header_hash()], - pks_map.index_secret_keys(vec![keypair]), - None, - ))); - let signed_tx = tx.clone(); - vp_env.tx = signed_tx.clone(); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - validate_tx(&CTX, signed_tx, vp_owner, keys_changed, verifiers) - .unwrap() - ); - } - - /// Test that a validity predicate update is rejected if not whitelisted - #[test] - fn test_signed_vp_update_not_whitelisted_rejected() { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - tx_env.init_parameters( - None, - Some(vec!["some_hash".to_string()]), - None, - None, - ); - - let vp_owner = address::testing::established_address_1(); - let keypair = key::testing::keypair_1(); - let public_key = keypair.ref_to(); - let vp_code = TestWasms::VpAlwaysTrue.read_bytes(); - let vp_hash = sha256(&vp_code); - // for the update - tx_env.store_wasm_code(vp_code); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&vp_owner]); - tx_env.init_account_storage(&vp_owner, vec![public_key.clone()], 1); - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { - // Update VP in a transaction - tx::ctx() - .update_validity_predicate(address, vp_hash, &None) - .unwrap(); - }); - - let pks_map = AccountPublicKeysMap::from_iter(vec![public_key]); - - let mut vp_env = vp_host_env::take(); - let mut tx = vp_env.tx.clone(); - tx.set_data(Data::new(vec![])); - tx.set_code(Code::new(vec![], None)); - tx.add_section(Section::Signature(Signature::new( - vec![tx.raw_header_hash()], - pks_map.index_secret_keys(vec![keypair]), - None, - ))); - let signed_tx = tx.clone(); - vp_env.tx = signed_tx.clone(); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - !validate_tx(&CTX, signed_tx, vp_owner, keys_changed, verifiers) - .unwrap() - ); - } - - /// Test that a validity predicate update is accepted if whitelisted - #[test] - fn test_signed_vp_update_whitelisted_accepted() { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - - let vp_owner = address::testing::established_address_1(); - let keypair = key::testing::keypair_1(); - let public_key = keypair.ref_to(); - let vp_code = TestWasms::VpAlwaysTrue.read_bytes(); - let vp_hash = sha256(&vp_code); - // for the update - tx_env.store_wasm_code(vp_code); - - tx_env.init_parameters( - None, - Some(vec![vp_hash.to_string()]), - None, - None, - ); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&vp_owner]); - tx_env.init_account_storage(&vp_owner, vec![public_key.clone()], 1); - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { - // Update VP in a transaction - tx::ctx() - .update_validity_predicate(address, vp_hash, &None) - .unwrap(); - }); - - let pks_map = AccountPublicKeysMap::from_iter(vec![public_key]); - - let mut vp_env = vp_host_env::take(); - let mut tx = vp_env.tx.clone(); - tx.set_data(Data::new(vec![])); - tx.set_code(Code::new(vec![], None)); - tx.add_section(Section::Signature(Signature::new( - vec![tx.raw_header_hash()], - pks_map.index_secret_keys(vec![keypair]), - None, - ))); - let signed_tx = tx.clone(); - vp_env.tx = signed_tx.clone(); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - validate_tx(&CTX, signed_tx, vp_owner, keys_changed, verifiers) - .unwrap() - ); - } - - /// Test that a tx is rejected if not whitelisted - #[test] - fn test_tx_not_whitelisted_rejected() { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - - let vp_owner = address::testing::established_address_1(); - let keypair = key::testing::keypair_1(); - let public_key = keypair.ref_to(); - let vp_code = TestWasms::VpAlwaysTrue.read_bytes(); - let vp_hash = sha256(&vp_code); - // for the update - tx_env.store_wasm_code(vp_code); - - tx_env.init_parameters( - None, - Some(vec![vp_hash.to_string()]), - Some(vec!["some_hash".to_string()]), - None, - ); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&vp_owner]); - tx_env.init_account_storage(&vp_owner, vec![public_key.clone()], 1); - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { - // Update VP in a transaction - tx::ctx() - .update_validity_predicate(address, vp_hash, &None) - .unwrap(); - }); - - let pks_map = AccountPublicKeysMap::from_iter(vec![public_key]); - - let mut vp_env = vp_host_env::take(); - let mut tx = vp_env.tx.clone(); - tx.set_data(Data::new(vec![])); - tx.set_code(Code::new(vec![], None)); - tx.add_section(Section::Signature(Signature::new( - vec![tx.raw_header_hash()], - pks_map.index_secret_keys(vec![keypair]), - None, - ))); - let signed_tx = tx.clone(); - vp_env.tx = signed_tx.clone(); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - !validate_tx(&CTX, signed_tx, vp_owner, keys_changed, verifiers) - .unwrap() - ); - } - - #[test] - fn test_tx_whitelisted_accepted() { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - - let vp_owner = address::testing::established_address_1(); - let keypair = key::testing::keypair_1(); - let public_key = keypair.ref_to(); - let vp_code = TestWasms::VpAlwaysTrue.read_bytes(); - let vp_hash = sha256(&vp_code); - // for the update - tx_env.store_wasm_code(vp_code); - - // hardcoded hash of VP_ALWAYS_TRUE_WASM - tx_env.init_parameters( - None, - Some(vec![vp_hash.to_string()]), - None, - None, - ); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&vp_owner]); - tx_env.init_account_storage(&vp_owner, vec![public_key.clone()], 1); - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { - // Update VP in a transaction - tx::ctx() - .update_validity_predicate(address, vp_hash, &None) - .unwrap(); - }); - - let pks_map = AccountPublicKeysMap::from_iter(vec![public_key]); - - let mut vp_env = vp_host_env::take(); - let mut tx = vp_env.tx.clone(); - tx.set_code(Code::new(vec![], None)); - tx.set_data(Data::new(vec![])); - tx.add_section(Section::Signature(Signature::new( - vec![tx.raw_header_hash()], - pks_map.index_secret_keys(vec![keypair]), - None, - ))); - let signed_tx = tx.clone(); - vp_env.tx = signed_tx.clone(); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - validate_tx(&CTX, signed_tx, vp_owner, keys_changed, verifiers) - .unwrap() - ); - } -}