From e40e37a6acfe8f473436c48547f88be34cffb848 Mon Sep 17 00:00:00 2001 From: punwai Date: Mon, 12 Sep 2022 01:27:20 -0700 Subject: [PATCH] [crypto] Switch signature scheme to BLS + Add Networking key. (#857) * [crypto] switch to BLS * [crypto] network changes --- Cargo.lock | 24 ++++++----- Docker/entry.sh | 3 ++ Docker/gen.validators.sh | 1 + Docker/scripts/gen.committee.py | 9 ++++- Docker/validators/committee.json | 12 ++++-- .../validators/validator-0/network-key.json | 5 +++ .../validators/validator-0/primary-key.json | 6 +-- Docker/validators/validator-0/worker-key.json | 6 +-- .../validators/validator-1/network-key.json | 5 +++ .../validators/validator-1/primary-key.json | 6 +-- Docker/validators/validator-1/worker-key.json | 6 +-- .../validators/validator-2/network-key.json | 5 +++ .../validators/validator-2/primary-key.json | 6 +-- Docker/validators/validator-2/worker-key.json | 6 +-- .../validators/validator-3/network-key.json | 5 +++ .../validators/validator-3/primary-key.json | 6 +-- Docker/validators/validator-3/worker-key.json | 6 +-- Docker/validators/workers.json | 24 +++++------ benchmark/benchmark/commands.py | 35 +++++++++++----- benchmark/benchmark/config.py | 15 ++++--- benchmark/benchmark/full_demo.py | 15 ++++++- benchmark/benchmark/local.py | 15 ++++++- benchmark/benchmark/remote.py | 15 ++++++- benchmark/benchmark/utils.py | 5 +++ config/Cargo.toml | 1 + config/src/lib.rs | 31 ++++++++++---- config/tests/config_tests.rs | 2 + .../snapshots/config_tests__committee.snap | 20 ++++++---- .../snapshots/config_tests__worker_cache.snap | 40 +++++++++---------- consensus/src/consensus.rs | 4 ++ crypto/src/lib.rs | 16 +++++--- network/src/primary.rs | 6 +-- network/src/traits.rs | 18 +++++---- node/src/generate_format.rs | 32 +++++++++++---- node/src/lib.rs | 7 +++- node/src/main.rs | 38 ++++++++++++++---- node/src/restarter.rs | 31 ++++++++++---- node/tests/node_smoke_test.rs | 22 ++++++++++ node/tests/reconfigure.rs | 33 ++++++++++++--- node/tests/staged/narwhal.yaml | 27 +++++++------ primary/src/block_remover.rs | 4 +- primary/src/block_synchronizer/mod.rs | 10 ++--- primary/src/block_synchronizer/peers.rs | 3 ++ .../tests/block_synchronizer_tests.rs | 32 +++++++-------- primary/src/block_waiter.rs | 4 +- primary/src/core.rs | 13 +++--- primary/src/grpc_server/configuration.rs | 1 + primary/src/header_waiter.rs | 8 ++-- primary/src/helper.rs | 8 ++-- primary/src/primary.rs | 9 +++-- primary/src/tests/certificate_waiter_tests.rs | 4 +- primary/src/tests/core_tests.rs | 30 +++++++------- primary/src/tests/header_waiter_tests.rs | 2 +- primary/src/tests/helper_tests.rs | 24 +++++------ primary/src/tests/proposer_tests.rs | 2 +- primary/tests/epoch_change.rs | 19 ++++++--- .../tests/integration_tests_proposer_api.rs | 13 ++++-- .../tests/integration_tests_validator_api.rs | 21 +++++++--- test_utils/Cargo.toml | 1 + test_utils/src/cluster.rs | 17 +++++--- test_utils/src/lib.rs | 34 +++++++++++----- types/src/consensus.rs | 2 + types/src/primary.rs | 8 +++- types/src/worker.rs | 1 + worker/src/worker.rs | 6 +-- 65 files changed, 570 insertions(+), 275 deletions(-) create mode 100644 Docker/validators/validator-0/network-key.json create mode 100644 Docker/validators/validator-1/network-key.json create mode 100644 Docker/validators/validator-2/network-key.json create mode 100644 Docker/validators/validator-3/network-key.json diff --git a/Cargo.lock b/Cargo.lock index 2eee6ceb3..5aaa2617c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -829,6 +829,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", + "serde_with", "tempfile", "test_utils", "thiserror", @@ -1922,9 +1923,9 @@ checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" [[package]] name = "httparse" -version = "1.8.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" [[package]] name = "httpdate" @@ -2718,9 +2719,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.9" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" +checksum = "9423e2b32f7a043629287a536f21951e8c6a82482d0acb1eeebfc90bc2225b22" [[package]] name = "peeking_take_while" @@ -2938,9 +2939,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.1.19" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a49e86d2c26a24059894a3afa13fd17d063419b05dfb83f06d9c3566060c3f5a" +checksum = "697ae720ee02011f439e0701db107ffe2916d83f718342d65d7f8bf7b8a5fee9" dependencies = [ "proc-macro2 1.0.40", "syn 1.0.98", @@ -3923,9 +3924,9 @@ checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "socket2" -version = "0.4.7" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +checksum = "10c98bba371b9b22a71a9414e420f92ddeb2369239af08200816169d5e2dd7aa" dependencies = [ "libc", "winapi", @@ -4185,6 +4186,7 @@ dependencies = [ "prometheus", "rand 0.8.5", "serde", + "sha3 0.10.4", "telemetry-subscribers", "tempfile", "thiserror", @@ -4973,13 +4975,13 @@ dependencies = [ [[package]] name = "which" -version = "4.3.0" +version = "4.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" +checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae" dependencies = [ "either", + "lazy_static", "libc", - "once_cell", ] [[package]] diff --git a/Docker/entry.sh b/Docker/entry.sh index 4036c28e9..7e9bdd0e0 100755 --- a/Docker/entry.sh +++ b/Docker/entry.sh @@ -14,6 +14,7 @@ fi # Environment variables to use on the script NODE_BIN="./bin/node" PRIMARY_KEYS_PATH=${KEYS_PATH:="/validators/validator-$VALIDATOR_ID/primary-key.json"} +PRIMARY_NETWORK_KEYS_PATH=${KEYS_PATH:="/validators/validator-$VALIDATOR_ID/network-key.json"} WORKER_KEYS_PATH=${KEYS_PATH:="/validators/validator-$VALIDATOR_ID/worker-key.json"} COMMITTEE_PATH=${COMMITTEE_PATH:="/validators/committee.json"} WORKERS_PATH=${WORKERS_PATH:="/validators/workers.json"} @@ -38,6 +39,7 @@ if [[ "$NODE_TYPE" = "primary" ]]; then $NODE_BIN $LOG_LEVEL run \ --primary-keys $PRIMARY_KEYS_PATH \ + --primary-network-keys $PRIMARY_NETWORK_KEYS_PATH \ --worker-keys $WORKER_KEYS_PATH \ --committee $COMMITTEE_PATH \ --workers $WORKERS_PATH \ @@ -49,6 +51,7 @@ elif [[ "$NODE_TYPE" = "worker" ]]; then $NODE_BIN $LOG_LEVEL run \ --primary-keys $PRIMARY_KEYS_PATH \ + --primary-network-keys $PRIMARY_NETWORK_KEYS_PATH \ --worker-keys $WORKER_KEYS_PATH \ --committee $COMMITTEE_PATH \ --workers $WORKERS_PATH \ diff --git a/Docker/gen.validators.sh b/Docker/gen.validators.sh index ba4380bd7..f446db2f3 100755 --- a/Docker/gen.validators.sh +++ b/Docker/gen.validators.sh @@ -99,6 +99,7 @@ do val=${target}/validator-${i} mkdir -p ${val}/{db-primary,db-worker-0,logs} ${node} generate_keys --filename ${val}/key.json + ${node} generate_network_keys --filename ${val}/network-key.json done cp validators/parameters.json ${target}/parameters.json diff --git a/Docker/scripts/gen.committee.py b/Docker/scripts/gen.committee.py index b3fa95393..bc1c957d5 100755 --- a/Docker/scripts/gen.committee.py +++ b/Docker/scripts/gen.committee.py @@ -25,9 +25,16 @@ def main(): k = open("{}/validator-{:02d}/key.json".format(args.d, i)).read() keys.append(json.loads(k)) + network_keys = [] + for i in range(args.n): + k = open("{}/validator-{:02d}/network-key.json".format(args.d, i)).read() + network_keys.append(json.loads(k)) + + temp = {} - for i, k in enumerate(keys): + for i, (k, nk) in enumerate(zip(keys, network_keys)): temp[k['name']] = { + "network_key": nk['name'], "primary": { "primary_to_primary": "/dns/primary_{:02d}/tcp/3000/http".format(i), "worker_to_primary": "/dns/primary_{:02d}/tcp/3001/http".format(i) diff --git a/Docker/validators/committee.json b/Docker/validators/committee.json index 847b81c04..ad382a98e 100644 --- a/Docker/validators/committee.json +++ b/Docker/validators/committee.json @@ -1,27 +1,31 @@ { "authorities": { - "Zy82aSpF8QghKE4wWvyIoTWyLetCuUSfk2gxHEtwdbg=": { + "i9TwX9Z/CiFznIoO14nIUdJ9Wpo0o50o7tSGtmdhuB5hTK1h5WNvsmUOhc3pdgFaFfKhe1O1NNlTb+sraT0I+ZtOsJUrO5e5figU7XPj5tzRkTlJUoBPtjb1f3RbbXHj": { + "network_key": "TVvqbV9LvRfPslOSMFUNxm0w0PfH9ytSVkZuqKN0DtU=", "primary": { "primary_to_primary": "/dns/primary_0/tcp/3000/http", "worker_to_primary": "/dns/primary_0/tcp/3001/http" }, "stake": 1 }, - "fbhvgLnet2HdE0NUITUpekQxdRRWKxbZczM6Qg55sP8=": { + "lEExVRsXRE2O5+Yhaunn0+yckZz249/OERxaTrCQZUIz7E4gmyGQWmKFEpBA2p8VCcAHvveCvupstx7Qp8/w1gpqo2kFRXqagO/IRDOfJiItmtVxzHWxlnSP/2XKSkZf": { + "network_key": "5EpwzXiTL8B2OuazfuHC9S9Hp0uRZFYElYj25ilVljM=", "primary": { "primary_to_primary": "/dns/primary_1/tcp/3000/http", "worker_to_primary": "/dns/primary_1/tcp/3001/http" }, "stake": 1 }, - "noDjBFfXGqQioHTf6jEIPYthhUWCMsC12ZJ9DMh7Ujk=": { + "pF/T4zMSkvDcHkCuk4Q8jsjcS+vZb/yAj2d8/R7CLH10dP3UxQKjwIeTklXJk/nLDfUg3MN86jMPSO/+2JTqO46oE86XssCKK+SeQCjft+gL0EzdvNlBs5iEt1YGlsoK": { + "network_key": "Rd6StTmpiACXs/wN/pv5DtG9h+OImvplxD/xTU2sV0I=", "primary": { "primary_to_primary": "/dns/primary_2/tcp/3000/http", "worker_to_primary": "/dns/primary_2/tcp/3001/http" }, "stake": 1 }, - "Z+K3OEI/eldyTTdp27mQFDdBPqjkss9wOkN6RceDTuM=": { + "ofwVakr2b+MoerCcQp+skTHfVVPOit575513sx443Cw7ESN6QxPcC6aWnhMUd/EwAI2mVImC4pKaE9G88vzA7B40X7SegLe1lFIJWE8Jyvds1yxWcnmESFF+L8ZLGI9i": { + "network_key": "6BHCB8duL285+IiyvcbLnozof/jElGmjYef5wHN9MXk=", "primary": { "primary_to_primary": "/dns/primary_3/tcp/3000/http", "worker_to_primary": "/dns/primary_3/tcp/3001/http" diff --git a/Docker/validators/validator-0/network-key.json b/Docker/validators/validator-0/network-key.json new file mode 100644 index 000000000..d4ecc92af --- /dev/null +++ b/Docker/validators/validator-0/network-key.json @@ -0,0 +1,5 @@ +{ + "type": "Ed25519KeyPair", + "name": "TVvqbV9LvRfPslOSMFUNxm0w0PfH9ytSVkZuqKN0DtU=", + "secret": "2kRrHl/taJiAd+xzt0yykxexiqh0wOJ0NhpUYyZG280=" +} diff --git a/Docker/validators/validator-0/primary-key.json b/Docker/validators/validator-0/primary-key.json index 21148df4e..7c3016222 100644 --- a/Docker/validators/validator-0/primary-key.json +++ b/Docker/validators/validator-0/primary-key.json @@ -1,5 +1,5 @@ { - "type": "Ed25519KeyPair", - "name": "Zy82aSpF8QghKE4wWvyIoTWyLetCuUSfk2gxHEtwdbg=", - "secret": "mfxcM1O0t9GeCZges3sbHRQr63yRl9uDkIhlV66NxjM=" + "type": "BLS12381KeyPair", + "name": "i9TwX9Z/CiFznIoO14nIUdJ9Wpo0o50o7tSGtmdhuB5hTK1h5WNvsmUOhc3pdgFaFfKhe1O1NNlTb+sraT0I+ZtOsJUrO5e5figU7XPj5tzRkTlJUoBPtjb1f3RbbXHj", + "secret": "VbmSNN5iStVTnN/Pq/P5EwjfeLhrrY5dILFR8A6l1xI=" } diff --git a/Docker/validators/validator-0/worker-key.json b/Docker/validators/validator-0/worker-key.json index a45243d21..7c3016222 100644 --- a/Docker/validators/validator-0/worker-key.json +++ b/Docker/validators/validator-0/worker-key.json @@ -1,5 +1,5 @@ { - "type": "Ed25519KeyPair", - "name": "hgeabM6XVJdIJQJjas05IiZAm2VFhtxwqIz0gDMYyjw=", - "secret": "odAwN+GmVs9BMtBDiWDGT5fcpMmMzzUMtE/szmVpEVk=" + "type": "BLS12381KeyPair", + "name": "i9TwX9Z/CiFznIoO14nIUdJ9Wpo0o50o7tSGtmdhuB5hTK1h5WNvsmUOhc3pdgFaFfKhe1O1NNlTb+sraT0I+ZtOsJUrO5e5figU7XPj5tzRkTlJUoBPtjb1f3RbbXHj", + "secret": "VbmSNN5iStVTnN/Pq/P5EwjfeLhrrY5dILFR8A6l1xI=" } diff --git a/Docker/validators/validator-1/network-key.json b/Docker/validators/validator-1/network-key.json new file mode 100644 index 000000000..c1cbc88c4 --- /dev/null +++ b/Docker/validators/validator-1/network-key.json @@ -0,0 +1,5 @@ +{ + "type": "Ed25519KeyPair", + "name": "5EpwzXiTL8B2OuazfuHC9S9Hp0uRZFYElYj25ilVljM=", + "secret": "yP3ZZjwX0njXV5l4vgbXzErOizcVskF4xzrJZwfJRUQ=" +} diff --git a/Docker/validators/validator-1/primary-key.json b/Docker/validators/validator-1/primary-key.json index 8f84ac4f9..2ea365608 100644 --- a/Docker/validators/validator-1/primary-key.json +++ b/Docker/validators/validator-1/primary-key.json @@ -1,5 +1,5 @@ { - "type": "Ed25519KeyPair", - "name": "fbhvgLnet2HdE0NUITUpekQxdRRWKxbZczM6Qg55sP8=", - "secret": "tLh0pgy0IQfDbsCn8DN2rkSKfWCHQxs1OKLdS0kpJds=" + "type": "BLS12381KeyPair", + "name": "lEExVRsXRE2O5+Yhaunn0+yckZz249/OERxaTrCQZUIz7E4gmyGQWmKFEpBA2p8VCcAHvveCvupstx7Qp8/w1gpqo2kFRXqagO/IRDOfJiItmtVxzHWxlnSP/2XKSkZf", + "secret": "brYlYkS7Kl9Ew3xC7hl5Rv2hJU7xx1pTgvkThiNBIkU=" } diff --git a/Docker/validators/validator-1/worker-key.json b/Docker/validators/validator-1/worker-key.json index 5c1a3a437..2ea365608 100644 --- a/Docker/validators/validator-1/worker-key.json +++ b/Docker/validators/validator-1/worker-key.json @@ -1,5 +1,5 @@ { - "type": "Ed25519KeyPair", - "name": "7o+0AxuS4muiCYxLOMT9pzdLug2LmrAzB7yLE7TrxwA=", - "secret": "a5IKgyaSAVRPtmzhvjGobSe5/gbFUi/2sF78DlLI/EE=" + "type": "BLS12381KeyPair", + "name": "lEExVRsXRE2O5+Yhaunn0+yckZz249/OERxaTrCQZUIz7E4gmyGQWmKFEpBA2p8VCcAHvveCvupstx7Qp8/w1gpqo2kFRXqagO/IRDOfJiItmtVxzHWxlnSP/2XKSkZf", + "secret": "brYlYkS7Kl9Ew3xC7hl5Rv2hJU7xx1pTgvkThiNBIkU=" } diff --git a/Docker/validators/validator-2/network-key.json b/Docker/validators/validator-2/network-key.json new file mode 100644 index 000000000..5728dbe45 --- /dev/null +++ b/Docker/validators/validator-2/network-key.json @@ -0,0 +1,5 @@ +{ + "type": "Ed25519KeyPair", + "name": "Rd6StTmpiACXs/wN/pv5DtG9h+OImvplxD/xTU2sV0I=", + "secret": "KPigXDOul6tXan2pmfIk0J4wEYee+TQBB/siF6P5nTI=" +} diff --git a/Docker/validators/validator-2/primary-key.json b/Docker/validators/validator-2/primary-key.json index ec7da0005..821927aa8 100644 --- a/Docker/validators/validator-2/primary-key.json +++ b/Docker/validators/validator-2/primary-key.json @@ -1,5 +1,5 @@ { - "type": "Ed25519KeyPair", - "name": "noDjBFfXGqQioHTf6jEIPYthhUWCMsC12ZJ9DMh7Ujk=", - "secret": "p6NZvFtzHLViY16bPZQ/gvTXanwtMQ+iIVLzt0L3fBg=" + "type": "BLS12381KeyPair", + "name": "pF/T4zMSkvDcHkCuk4Q8jsjcS+vZb/yAj2d8/R7CLH10dP3UxQKjwIeTklXJk/nLDfUg3MN86jMPSO/+2JTqO46oE86XssCKK+SeQCjft+gL0EzdvNlBs5iEt1YGlsoK", + "secret": "auDsbkQnuR4BzY076jZ8UQrUWk8Wk53+8FQ5yMNYqb4=" } diff --git a/Docker/validators/validator-2/worker-key.json b/Docker/validators/validator-2/worker-key.json index 69cf39cee..821927aa8 100644 --- a/Docker/validators/validator-2/worker-key.json +++ b/Docker/validators/validator-2/worker-key.json @@ -1,5 +1,5 @@ { - "type": "Ed25519KeyPair", - "name": "63HCaWWXpqB8fhrGgBSNy7XfbSpakrILoXA5DaaYx1o=", - "secret": "M6HIPZPJQbjLAY9BVCjKsGTWooW6a+HKgtmuFGDaJTo=" + "type": "BLS12381KeyPair", + "name": "pF/T4zMSkvDcHkCuk4Q8jsjcS+vZb/yAj2d8/R7CLH10dP3UxQKjwIeTklXJk/nLDfUg3MN86jMPSO/+2JTqO46oE86XssCKK+SeQCjft+gL0EzdvNlBs5iEt1YGlsoK", + "secret": "auDsbkQnuR4BzY076jZ8UQrUWk8Wk53+8FQ5yMNYqb4=" } diff --git a/Docker/validators/validator-3/network-key.json b/Docker/validators/validator-3/network-key.json new file mode 100644 index 000000000..82423a9a9 --- /dev/null +++ b/Docker/validators/validator-3/network-key.json @@ -0,0 +1,5 @@ +{ + "type": "Ed25519KeyPair", + "name": "6BHCB8duL285+IiyvcbLnozof/jElGmjYef5wHN9MXk=", + "secret": "ifdVHBnI9J6bMbcbLZwzRb4T1fIzkGc2+LWitrGTwAM=" +} diff --git a/Docker/validators/validator-3/primary-key.json b/Docker/validators/validator-3/primary-key.json index 929e0d851..193832668 100644 --- a/Docker/validators/validator-3/primary-key.json +++ b/Docker/validators/validator-3/primary-key.json @@ -1,5 +1,5 @@ { - "type": "Ed25519KeyPair", - "name": "Z+K3OEI/eldyTTdp27mQFDdBPqjkss9wOkN6RceDTuM=", - "secret": "5txgo772aYLLWUmLi3zWaLDEM6Ey62wOik7mYyQbysw=" + "type": "BLS12381KeyPair", + "name": "ofwVakr2b+MoerCcQp+skTHfVVPOit575513sx443Cw7ESN6QxPcC6aWnhMUd/EwAI2mVImC4pKaE9G88vzA7B40X7SegLe1lFIJWE8Jyvds1yxWcnmESFF+L8ZLGI9i", + "secret": "celbRnC5R3Ok8GHSvzFFlWt0TwBXFM2E27kha+/kCC4=" } diff --git a/Docker/validators/validator-3/worker-key.json b/Docker/validators/validator-3/worker-key.json index cc458e99d..193832668 100644 --- a/Docker/validators/validator-3/worker-key.json +++ b/Docker/validators/validator-3/worker-key.json @@ -1,5 +1,5 @@ { - "type": "Ed25519KeyPair", - "name": "cJbSCbB7f3l/Tmeix4Ts3Th8xS3TTh4ohnakHKhObmc=", - "secret": "X/l+9RaoDB7N8Efn1kQ02T6nvW9kQ1aP5SktR/4GZT4=" + "type": "BLS12381KeyPair", + "name": "ofwVakr2b+MoerCcQp+skTHfVVPOit575513sx443Cw7ESN6QxPcC6aWnhMUd/EwAI2mVImC4pKaE9G88vzA7B40X7SegLe1lFIJWE8Jyvds1yxWcnmESFF+L8ZLGI9i", + "secret": "celbRnC5R3Ok8GHSvzFFlWt0TwBXFM2E27kha+/kCC4=" } diff --git a/Docker/validators/workers.json b/Docker/validators/workers.json index d72c7e998..3cbc1a09d 100644 --- a/Docker/validators/workers.json +++ b/Docker/validators/workers.json @@ -1,35 +1,35 @@ { "workers": { - "Zy82aSpF8QghKE4wWvyIoTWyLetCuUSfk2gxHEtwdbg=": { + "i9TwX9Z/CiFznIoO14nIUdJ9Wpo0o50o7tSGtmdhuB5hTK1h5WNvsmUOhc3pdgFaFfKhe1O1NNlTb+sraT0I+ZtOsJUrO5e5figU7XPj5tzRkTlJUoBPtjb1f3RbbXHj": { "0": { - "name": "hgeabM6XVJdIJQJjas05IiZAm2VFhtxwqIz0gDMYyjw=", "primary_to_worker": "/dns/worker_0/tcp/4000/http", "transactions": "/dns/worker_0/tcp/4001/http", - "worker_to_worker": "/dns/worker_0/tcp/4002/http" + "worker_to_worker": "/dns/worker_0/tcp/4002/http", + "name": "i9TwX9Z/CiFznIoO14nIUdJ9Wpo0o50o7tSGtmdhuB5hTK1h5WNvsmUOhc3pdgFaFfKhe1O1NNlTb+sraT0I+ZtOsJUrO5e5figU7XPj5tzRkTlJUoBPtjb1f3RbbXHj" } }, - "fbhvgLnet2HdE0NUITUpekQxdRRWKxbZczM6Qg55sP8=": { + "lEExVRsXRE2O5+Yhaunn0+yckZz249/OERxaTrCQZUIz7E4gmyGQWmKFEpBA2p8VCcAHvveCvupstx7Qp8/w1gpqo2kFRXqagO/IRDOfJiItmtVxzHWxlnSP/2XKSkZf": { "0": { - "name": "7o+0AxuS4muiCYxLOMT9pzdLug2LmrAzB7yLE7TrxwA=", "primary_to_worker": "/dns/worker_1/tcp/4000/http", "transactions": "/dns/worker_1/tcp/4001/http", - "worker_to_worker": "/dns/worker_1/tcp/4002/http" + "worker_to_worker": "/dns/worker_1/tcp/4002/http", + "name": "lEExVRsXRE2O5+Yhaunn0+yckZz249/OERxaTrCQZUIz7E4gmyGQWmKFEpBA2p8VCcAHvveCvupstx7Qp8/w1gpqo2kFRXqagO/IRDOfJiItmtVxzHWxlnSP/2XKSkZf" } }, - "noDjBFfXGqQioHTf6jEIPYthhUWCMsC12ZJ9DMh7Ujk=": { + "pF/T4zMSkvDcHkCuk4Q8jsjcS+vZb/yAj2d8/R7CLH10dP3UxQKjwIeTklXJk/nLDfUg3MN86jMPSO/+2JTqO46oE86XssCKK+SeQCjft+gL0EzdvNlBs5iEt1YGlsoK": { "0": { - "name": "63HCaWWXpqB8fhrGgBSNy7XfbSpakrILoXA5DaaYx1o=", "primary_to_worker": "/dns/worker_2/tcp/4000/http", "transactions": "/dns/worker_2/tcp/4001/http", - "worker_to_worker": "/dns/worker_2/tcp/4002/http" + "worker_to_worker": "/dns/worker_2/tcp/4002/http", + "name": "pF/T4zMSkvDcHkCuk4Q8jsjcS+vZb/yAj2d8/R7CLH10dP3UxQKjwIeTklXJk/nLDfUg3MN86jMPSO/+2JTqO46oE86XssCKK+SeQCjft+gL0EzdvNlBs5iEt1YGlsoK" } }, - "Z+K3OEI/eldyTTdp27mQFDdBPqjkss9wOkN6RceDTuM=": { + "ofwVakr2b+MoerCcQp+skTHfVVPOit575513sx443Cw7ESN6QxPcC6aWnhMUd/EwAI2mVImC4pKaE9G88vzA7B40X7SegLe1lFIJWE8Jyvds1yxWcnmESFF+L8ZLGI9i": { "0": { - "name": "cJbSCbB7f3l/Tmeix4Ts3Th8xS3TTh4ohnakHKhObmc=", "primary_to_worker": "/dns/worker_3/tcp/4000/http", "transactions": "/dns/worker_3/tcp/4001/http", - "worker_to_worker": "/dns/worker_3/tcp/4002/http" + "worker_to_worker": "/dns/worker_3/tcp/4002/http", + "name": "ofwVakr2b+MoerCcQp+skTHfVVPOit575513sx443Cw7ESN6QxPcC6aWnhMUd/EwAI2mVImC4pKaE9G88vzA7B40X7SegLe1lFIJWE8Jyvds1yxWcnmESFF+L8ZLGI9i" } } }, diff --git a/benchmark/benchmark/commands.py b/benchmark/benchmark/commands.py index eb93752cb..7ae36c3ff 100644 --- a/benchmark/benchmark/commands.py +++ b/benchmark/benchmark/commands.py @@ -31,42 +31,59 @@ def generate_key(filename): return f'./node generate_keys --filename {filename}' @staticmethod - def run_primary(primary_keys, worker_keys, committee, workers, store, parameters, debug=False): + def generate_network_key(filename): + assert isinstance(filename, str) + return f'./node generate_network_keys --filename {filename}' + + @staticmethod + def run_primary(primary_keys, primary_network_keys, worker_keys, committee, workers, store, parameters, debug=False): assert isinstance(primary_keys, str) + assert isinstance(primary_network_keys, str) assert isinstance(worker_keys, str) assert isinstance(committee, str) assert isinstance(workers, str) assert isinstance(parameters, str) assert isinstance(debug, bool) v = '-vvv' if debug else '-vv' - return (f'./node {v} run --primary-keys {primary_keys} --worker-keys {worker_keys} ' - f'--committee {committee} --workers {workers} --store {store} ' + return (f'./node {v} run --primary-keys {primary_keys} --primary-network-keys {primary_network_keys} ' + f'--worker-keys {worker_keys} --committee {committee} --workers {workers} --store {store} ' f'--parameters {parameters} primary') @staticmethod - def run_no_consensus_primary(primary_keys, worker_keys, committee, workers, store, parameters, debug=False): + def run_no_consensus_primary( + primary_keys, + primary_network_keys, + worker_keys, + committee, + workers, + store, + parameters, + debug=False + ): assert isinstance(primary_keys, str) + assert isinstance(primary_network_keys, str) assert isinstance(worker_keys, str) assert isinstance(committee, str) assert isinstance(workers, str) assert isinstance(parameters, str) assert isinstance(debug, bool) v = '-vvv' if debug else '-vv' - return (f'./node {v} run --primary-keys {primary_keys} --worker-keys {worker_keys} ' - f'--committee {committee} --workers {workers} --store {store} ' + return (f'./node {v} run --primary-keys {primary_keys} --primary-network-keys {primary_network_keys} ' + f'--worker-keys {worker_keys} --committee {committee} --workers {workers} --store {store} ' f'--parameters {parameters} primary --consensus-disabled') @staticmethod - def run_worker(primary_keys, worker_keys, committee, workers, store, parameters, id, debug=False): + def run_worker(primary_keys, primary_network_keys, worker_keys, committee, workers, store, parameters, id, debug=False): assert isinstance(primary_keys, str) + assert isinstance(primary_network_keys, str) assert isinstance(worker_keys, str) assert isinstance(committee, str) assert isinstance(workers, str) assert isinstance(parameters, str) assert isinstance(debug, bool) v = '-vvv' if debug else '-vv' - return (f'./node {v} run --primary-keys {primary_keys} --worker-keys {worker_keys} ' - f'--committee {committee} --workers {workers} --store {store} ' + return (f'./node {v} run --primary-keys {primary_keys} --primary-network-keys {primary_network_keys} ' + f'--worker-keys {worker_keys} --committee {committee} --workers {workers} --store {store} ' f'--parameters {parameters} worker --id {id}') @staticmethod diff --git a/benchmark/benchmark/config.py b/benchmark/benchmark/config.py index b15a0ef84..c3e84fc68 100644 --- a/benchmark/benchmark/config.py +++ b/benchmark/benchmark/config.py @@ -155,6 +155,7 @@ class Committee: "primary_to_primary": x.x.x.x:x, "worker_to_primary": x.x.x.x:x, }, + "network_key: NETWORK_KEY== }, ... } @@ -170,17 +171,17 @@ def __init__(self, addresses, base_port): assert isinstance(addresses, OrderedDict) assert all(isinstance(x, str) for x in addresses.keys()) assert all( - isinstance(x, list) and len(x) >= 1 for x in addresses.values() + isinstance(address, list) and len(address) >= 1 for (_, address) in addresses.values() ) assert all( - isinstance(x, str) for y in addresses.values() for x in y + isinstance(x, str) for (_, address) in addresses.values() for x in address ) assert len({len(x) for x in addresses.values()}) == 1 assert isinstance(base_port, int) and base_port > 1024 port = base_port self.json = {'authorities': OrderedDict(), 'epoch': 0} - for name, hosts in addresses.items(): + for name, (network_name, hosts) in addresses.items(): host = hosts.pop(0) primary_addr = { 'primary_to_primary': f'/ip4/{host}/tcp/{port}/http', @@ -190,7 +191,8 @@ def __init__(self, addresses, base_port): self.json['authorities'][name] = { 'stake': 1, - 'primary': primary_addr + 'primary': primary_addr, + 'network_key': network_name } def primary_addresses(self, faults=0): @@ -241,11 +243,12 @@ def ip(multi_address): class LocalCommittee(Committee): - def __init__(self, names, port): + def __init__(self, names, network_names, port): assert isinstance(names, list) assert all(isinstance(x, str) for x in names) assert isinstance(port, int) - addresses = OrderedDict((x, ['127.0.0.1']) for x in names) + assert len(names) == len(network_names) + addresses = OrderedDict((name, (network_name, ['127.0.0.1'])) for name, network_name in zip(names, network_names)) super().__init__(addresses, port) diff --git a/benchmark/benchmark/full_demo.py b/benchmark/benchmark/full_demo.py index 86aa61102..b66fac858 100644 --- a/benchmark/benchmark/full_demo.py +++ b/benchmark/benchmark/full_demo.py @@ -81,9 +81,18 @@ def run(self, debug=False): cmd = CommandMaker.generate_key(filename).split() subprocess.run(cmd, check=True) primary_keys += [Key.from_file(filename)] - primary_names = [x.name for x in primary_keys] - committee = LocalCommittee(primary_names, self.BASE_PORT) + + primary_network_keys = [] + primary_network_key_files = [ + PathMaker.primary_network_key_file(i) for i in range(nodes)] + for filename in primary_network_key_files: + cmd = CommandMaker.generate_network_key(filename).split() + subprocess.run(cmd, check=True) + primary_network_keys += [Key.from_file(filename)] + primary_network_names = [x.name for x in primary_network_keys] + + committee = LocalCommittee(primary_names, primary_network_names, self.BASE_PORT) committee.print(PathMaker.committee_file()) worker_keys = [] @@ -122,6 +131,7 @@ def run(self, debug=False): for i, address in enumerate(committee.primary_addresses(self.faults)): cmd = CommandMaker.run_no_consensus_primary( PathMaker.primary_key_file(i), + PathMaker.primary_network_key_file(i), PathMaker.worker_key_file(0), PathMaker.committee_file(), PathMaker.workers_file(), @@ -137,6 +147,7 @@ def run(self, debug=False): for (id, address) in addresses: cmd = CommandMaker.run_worker( PathMaker.primary_key_file(i), + PathMaker.primary_network_key_file(i), PathMaker.worker_key_file(i*self.workers + id), PathMaker.committee_file(), PathMaker.workers_file(), diff --git a/benchmark/benchmark/local.py b/benchmark/benchmark/local.py index d44b1e253..2fdca8c75 100644 --- a/benchmark/benchmark/local.py +++ b/benchmark/benchmark/local.py @@ -68,9 +68,18 @@ def run(self, debug=False): cmd = CommandMaker.generate_key(filename).split() subprocess.run(cmd, check=True) primary_keys += [Key.from_file(filename)] - primary_names = [x.name for x in primary_keys] - committee = LocalCommittee(primary_names, self.BASE_PORT) + + primary_network_keys = [] + primary_network_key_files = [ + PathMaker.primary_network_key_file(i) for i in range(nodes)] + for filename in primary_network_key_files: + cmd = CommandMaker.generate_network_key(filename).split() + subprocess.run(cmd, check=True) + primary_network_keys += [Key.from_file(filename)] + primary_network_names = [x.name for x in primary_network_keys] + + committee = LocalCommittee(primary_names, primary_network_names, self.BASE_PORT) committee.print(PathMaker.committee_file()) worker_keys = [] @@ -109,6 +118,7 @@ def run(self, debug=False): for i, address in enumerate(committee.primary_addresses(self.faults)): cmd = CommandMaker.run_primary( PathMaker.primary_key_file(i), + PathMaker.primary_network_key_file(i), PathMaker.worker_key_file(0), PathMaker.committee_file(), PathMaker.workers_file(), @@ -124,6 +134,7 @@ def run(self, debug=False): for (id, address) in addresses: cmd = CommandMaker.run_worker( PathMaker.primary_key_file(i), + PathMaker.primary_network_key_file(i), PathMaker.worker_key_file(i*self.workers + id), PathMaker.committee_file(), PathMaker.workers_file(), diff --git a/benchmark/benchmark/remote.py b/benchmark/benchmark/remote.py index 2bf1622eb..15fdd1abb 100644 --- a/benchmark/benchmark/remote.py +++ b/benchmark/benchmark/remote.py @@ -186,16 +186,24 @@ def _config(self, hosts, node_parameters, bench_parameters): cmd = CommandMaker.generate_key(filename).split() subprocess.run(cmd, check=True) primary_keys += [Key.from_file(filename)] - primary_names = [x.name for x in primary_keys] + primary_network_keys = [] + primary_network_key_files = [PathMaker.primary_network_key_file( + i) for i in range(len(hosts))] + for filename in primary_network_key_files: + cmd = CommandMaker.generate_network_key(filename).split() + subprocess.run(cmd, check=True) + primary_network_keys += [Key.from_file(filename)] + primary_network_names = [x.name for x in primary_network_keys] + if bench_parameters.collocate: addresses = OrderedDict( (x, [y] * (bench_parameters.workers + 1)) for x, y in zip(primary_names, hosts) ) else: addresses = OrderedDict( - (x, y) for x, y in zip(primary_names, hosts) + (x, (y, z)) for x, y, z in zip(primary_names, primary_network_names, hosts) ) committee = Committee(addresses, self.settings.base_port) committee.print(PathMaker.committee_file()) @@ -242,6 +250,7 @@ def _config(self, hosts, node_parameters, bench_parameters): c.put(PathMaker.committee_file(), '.') c.put(PathMaker.workers_file(), '.') c.put(PathMaker.primary_key_file(i), '.') + c.put(PathMaker.primary_network_key_file(i), '.') for j in range(bench_parameters.workers): c.put(PathMaker.worker_key_file( i*bench_parameters.workers + j), '.') @@ -280,6 +289,7 @@ def _run_single(self, rate, committee, worker_cache, bench_parameters, debug=Fal host = address.split(':')[1].strip("/") cmd = CommandMaker.run_primary( PathMaker.primary_key_file(i), + PathMaker.primary_network_key_file(i), PathMaker.worker_key_file(i), PathMaker.committee_file(), PathMaker.workers_file(), @@ -297,6 +307,7 @@ def _run_single(self, rate, committee, worker_cache, bench_parameters, debug=Fal host = address.split(':')[1].strip("/") cmd = CommandMaker.run_worker( PathMaker.primary_key_file(i), + PathMaker.primary_network_key_file(i), PathMaker.worker_key_file(i*bench_parameters.workers + id), PathMaker.committee_file(), PathMaker.workers_file(), diff --git a/benchmark/benchmark/utils.py b/benchmark/benchmark/utils.py index 414170b2f..8e9019147 100644 --- a/benchmark/benchmark/utils.py +++ b/benchmark/benchmark/utils.py @@ -46,6 +46,11 @@ def primary_key_file(i): assert isinstance(i, int) and i >= 0 return f'.primary-{i}-key.json' + @staticmethod + def primary_network_key_file(i): + assert isinstance(i, int) and i >= 0 + return f'.primary-{i}-network-key.json' + @staticmethod def worker_key_file(i): assert isinstance(i, int) and i >= 0 diff --git a/config/Cargo.toml b/config/Cargo.toml index 9f9690dab..ea0301fad 100644 --- a/config/Cargo.toml +++ b/config/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" match_opt = "0.1.2" multiaddr = "0.14.0" serde = { version = "1.0.144", features = ["derive"] } +serde_with = "2.0.0" serde_json = "1.0.85" thiserror = "1.0.34" tracing = "0.1.36" diff --git a/config/src/lib.rs b/config/src/lib.rs index 5189fd891..77d70f31d 100644 --- a/config/src/lib.rs +++ b/config/src/lib.rs @@ -7,9 +7,10 @@ rust_2018_idioms, rust_2021_compatibility )] +#![allow(clippy::mutable_key_type)] use arc_swap::ArcSwap; -use crypto::PublicKey; +use crypto::{NetworkPublicKey, PublicKey}; use fastcrypto::traits::EncodeDecodeBase64; use multiaddr::Multiaddr; use rand::{rngs::StdRng, seq::SliceRandom, SeedableRng}; @@ -18,7 +19,6 @@ use std::{ collections::{BTreeMap, HashSet}, fs::{self, OpenOptions}, io::{BufWriter, Write as _}, - ops::Deref, sync::Arc, time::Duration, }; @@ -331,7 +331,7 @@ impl Parameters { #[derive(Clone, Serialize, Deserialize, Eq, Hash, PartialEq, Debug)] pub struct WorkerInfo { /// The public key of this worker. - pub name: PublicKey, + pub name: NetworkPublicKey, /// Address to receive client transactions (WAN). pub transactions: Multiaddr, /// Address to receive messages from other workers (WAN). @@ -482,6 +482,8 @@ pub struct Authority { pub stake: Stake, /// The network addresses of the primary. pub primary: PrimaryAddresses, + /// Network key of the primary. + pub network_key: NetworkPublicKey, } pub type SharedCommittee = Arc>; @@ -576,16 +578,31 @@ impl Committee { .ok_or_else(|| ConfigError::NotInCommittee((*to).encode_base64())) } - /// Returns the addresses of all primaries except `myself`. - pub fn others_primaries(&self, myself: &PublicKey) -> Vec<(PublicKey, PrimaryAddresses)> { + pub fn network_key(&self, pk: &PublicKey) -> Result { + self.authorities + .get(&pk.clone()) + .map(|x| x.network_key.clone()) + .ok_or_else(|| ConfigError::NotInCommittee((*pk).encode_base64())) + } + + /// Return all the network addresses in the committee. + pub fn others_primaries( + &self, + myself: &PublicKey, + ) -> Vec<(PublicKey, PrimaryAddresses, NetworkPublicKey)> { self.authorities .iter() .filter(|(name, _)| *name != myself) - .map(|(name, authority)| (name.deref().clone(), authority.primary.clone())) + .map(|(name, authority)| { + ( + name.clone(), + authority.primary.clone(), + authority.network_key.clone(), + ) + }) .collect() } - /// Return all the network addresses in the committee. fn get_all_network_addresses(&self) -> HashSet<&Multiaddr> { self.authorities .values() diff --git a/config/tests/config_tests.rs b/config/tests/config_tests.rs index 87caa675b..b7c7190d9 100644 --- a/config/tests/config_tests.rs +++ b/config/tests/config_tests.rs @@ -1,6 +1,8 @@ // Copyright (c) 2022, Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 +#![allow(clippy::mutable_key_type)] + // This file contains tests that detect changes in Narwhal configs and parameters. // If a PR breaks one or more tests here, the PR probably has a real impact // on a Narwhal configuration file. When test failure happens, the PR should diff --git a/config/tests/snapshots/config_tests__committee.snap b/config/tests/snapshots/config_tests__committee.snap index 82e6bcbb3..530284d31 100644 --- a/config/tests/snapshots/config_tests__committee.snap +++ b/config/tests/snapshots/config_tests__committee.snap @@ -4,33 +4,37 @@ expression: committee --- { "authorities": { - "O6EMZUvkFG2rPW2rgLPOJM4323x0XCslMgXWL5Z7ALM=": { + "imU9ZewykCt0OOx70OkQCqKzj1TbVdD9nLqdCSutEIvSrtOWllaN9v/8w4B6dyrRE/Gacj+Cx/q5L15FycCX1spJIWMrt54HVB4beTy/MsgwvN6XZS6B4O4jCHbSqqiJ": { "stake": 1, "primary": { "primary_to_primary": "/ip4/127.0.0.1/tcp/0/http", "worker_to_primary": "/ip4/127.0.0.1/tcp/0/http" - } + }, + "network_key": "u8qKILpUof274Kfj23GlMvka4OUUaYoRt2i/pigwivY=" }, - "gznZnDM7s6J3/reAuNRsrDDNzZBQ2+I1+4zGe5HBsGo=": { + "jGbcLB6p5T8JhcF7TnrxmRK208QODFkgpaElCbTrNhn14H7Fbqd/CzBim6HMctdbE5RgeCpfDi+J+0xCtLil+uPSYBAiIOY9B1Tn4YRt7v05iOreTtN/E4VDfRneGhYY": { "stake": 1, "primary": { "primary_to_primary": "/ip4/127.0.0.1/tcp/0/http", "worker_to_primary": "/ip4/127.0.0.1/tcp/0/http" - } + }, + "network_key": "rvP0pLjsod/DQzYb+OQ2vULeklnAS4MU644gVN1ugqs=" }, - "nUdhahjfIDkwfwZCImAliLUqaq6qe2/oxrTZ66inh7E=": { + "qFBJ9C1pDBTCGNrGZTsHjiByNT1f4Shn++FfLXahY9V972gwsu8Qil1Kx1uDCuCPAkErNvcm91//7LK1bZKtwxxFIB0oibvW8UQwAVmbdQT0ZwCaJv02t25Zkpw0j9Kx": { "stake": 1, "primary": { "primary_to_primary": "/ip4/127.0.0.1/tcp/0/http", "worker_to_primary": "/ip4/127.0.0.1/tcp/0/http" - } + }, + "network_key": "fBEBLo4XV9uxBFd2fOjqDAkLzwJJ4sBIDtEayytwO7A=" }, - "ucbuFjDvPnERRKZI2wa7sihPcnTPvuU//O5QPMGkkgA=": { + "tOu6CCUfQFvA7Oo9IQsi6Q25ThGDmgcTXMYn4QVX8D8HeuI1DBmnctVFka/y0GijF5oKKOglBJNWsPz6LaE5YczKopYHmwm2kIxBwYHPdj186+KU8QfuvlZpHn/OnuCS": { "stake": 1, "primary": { "primary_to_primary": "/ip4/127.0.0.1/tcp/0/http", "worker_to_primary": "/ip4/127.0.0.1/tcp/0/http" - } + }, + "network_key": "hkGX9Mxcq2yO3Ut5xIXvuaVVcYt1tgPi6LmPVewN4mc=" } }, "epoch": 0 diff --git a/config/tests/snapshots/config_tests__worker_cache.snap b/config/tests/snapshots/config_tests__worker_cache.snap index 6dcee1cc4..993ee5e48 100644 --- a/config/tests/snapshots/config_tests__worker_cache.snap +++ b/config/tests/snapshots/config_tests__worker_cache.snap @@ -4,105 +4,105 @@ expression: worker_cache --- { "workers": { - "O6EMZUvkFG2rPW2rgLPOJM4323x0XCslMgXWL5Z7ALM=": { + "imU9ZewykCt0OOx70OkQCqKzj1TbVdD9nLqdCSutEIvSrtOWllaN9v/8w4B6dyrRE/Gacj+Cx/q5L15FycCX1spJIWMrt54HVB4beTy/MsgwvN6XZS6B4O4jCHbSqqiJ": { "0": { - "name": "dt4/oHrYlTWhdms3mHV8irOu9b6H3uFunhBt2LUJcp4=", + "name": "RNF9nFI3ufFssQSnKIZJ6ZutBDvyaLS56YkHLG8Vp4M=", "transactions": "/ip4/127.0.0.1/tcp/0/http", "worker_to_worker": "/ip4/127.0.0.1/tcp/0/http", "primary_to_worker": "/ip4/127.0.0.1/tcp/0/http" }, "1": { - "name": "lrisYqEadH5cgLhsT1EW5q6uVKxwCXLTJQO3klahUy8=", + "name": "19cMbgXwfn7K5L5EBoJY95YJ7DV9yoEtGnxsMrRueaI=", "transactions": "/ip4/127.0.0.1/tcp/0/http", "worker_to_worker": "/ip4/127.0.0.1/tcp/0/http", "primary_to_worker": "/ip4/127.0.0.1/tcp/0/http" }, "2": { - "name": "VayIYzPsiroVrY4eilEUVKCM/LfNcMWN2ELKoHCNGr8=", + "name": "pVzIOJcbHCbe9OIooldEfGE/ksQw5ptaaIOZ6FDVl2g=", "transactions": "/ip4/127.0.0.1/tcp/0/http", "worker_to_worker": "/ip4/127.0.0.1/tcp/0/http", "primary_to_worker": "/ip4/127.0.0.1/tcp/0/http" }, "3": { - "name": "Kt9mRluFkBunwfq2VREQbBXuSYGOsFo95bA/PIrvVhc=", + "name": "KHL7ygxRj/gaUagjjNQzwA7FCgPyvLOm2ctqsGcwH8E=", "transactions": "/ip4/127.0.0.1/tcp/0/http", "worker_to_worker": "/ip4/127.0.0.1/tcp/0/http", "primary_to_worker": "/ip4/127.0.0.1/tcp/0/http" } }, - "gznZnDM7s6J3/reAuNRsrDDNzZBQ2+I1+4zGe5HBsGo=": { + "jGbcLB6p5T8JhcF7TnrxmRK208QODFkgpaElCbTrNhn14H7Fbqd/CzBim6HMctdbE5RgeCpfDi+J+0xCtLil+uPSYBAiIOY9B1Tn4YRt7v05iOreTtN/E4VDfRneGhYY": { "0": { - "name": "hkGX9Mxcq2yO3Ut5xIXvuaVVcYt1tgPi6LmPVewN4mc=", + "name": "zGIzLjS7LVzWn2Dvuyo2y5FsfrRYMB6jZjbE27ASvYg=", "transactions": "/ip4/127.0.0.1/tcp/0/http", "worker_to_worker": "/ip4/127.0.0.1/tcp/0/http", "primary_to_worker": "/ip4/127.0.0.1/tcp/0/http" }, "1": { - "name": "vVDfe4JyrKvldWAMAgdqeUvACFqw15e4PUoj4ByOfCQ=", + "name": "nUdhahjfIDkwfwZCImAliLUqaq6qe2/oxrTZ66inh7E=", "transactions": "/ip4/127.0.0.1/tcp/0/http", "worker_to_worker": "/ip4/127.0.0.1/tcp/0/http", "primary_to_worker": "/ip4/127.0.0.1/tcp/0/http" }, "2": { - "name": "+oKq7VFT0pAQvjlvEti2YUw5fHXEYT/bs21P9wTlAKs=", + "name": "r7SQXpVQz0YqggB4JKBV2XWuk0RwxHfZ3bttKyZMNvo=", "transactions": "/ip4/127.0.0.1/tcp/0/http", "worker_to_worker": "/ip4/127.0.0.1/tcp/0/http", "primary_to_worker": "/ip4/127.0.0.1/tcp/0/http" }, "3": { - "name": "FsiKyAGnhMcChNBf+L2B8EHX6mMup8oqJ8bK/9ZRkww=", + "name": "XEf+9+MRPcAcVu9NR3v+UVevwzlpoBT4u1U34YzOxkw=", "transactions": "/ip4/127.0.0.1/tcp/0/http", "worker_to_worker": "/ip4/127.0.0.1/tcp/0/http", "primary_to_worker": "/ip4/127.0.0.1/tcp/0/http" } }, - "nUdhahjfIDkwfwZCImAliLUqaq6qe2/oxrTZ66inh7E=": { + "qFBJ9C1pDBTCGNrGZTsHjiByNT1f4Shn++FfLXahY9V972gwsu8Qil1Kx1uDCuCPAkErNvcm91//7LK1bZKtwxxFIB0oibvW8UQwAVmbdQT0ZwCaJv02t25Zkpw0j9Kx": { "0": { - "name": "6j/Odu4Qs6ZF+zBAUR36tMnNYFj0GSkBTRZGb147LCo=", + "name": "cseVuRrgvo0/Q0aJ5r9HHKQyf/El+gF4mpmrxVtCgOY=", "transactions": "/ip4/127.0.0.1/tcp/0/http", "worker_to_worker": "/ip4/127.0.0.1/tcp/0/http", "primary_to_worker": "/ip4/127.0.0.1/tcp/0/http" }, "1": { - "name": "r7SQXpVQz0YqggB4JKBV2XWuk0RwxHfZ3bttKyZMNvo=", + "name": "qjiox7McEestcwruZkiJ6PX4rAF9+DE+/1Z2tAm67OA=", "transactions": "/ip4/127.0.0.1/tcp/0/http", "worker_to_worker": "/ip4/127.0.0.1/tcp/0/http", "primary_to_worker": "/ip4/127.0.0.1/tcp/0/http" }, "2": { - "name": "l+fthD+rGkLOnCEpQ1IewioCVodHzAA7iB+9J/cL3+A=", + "name": "lbXAklH9C/Vm214pNQUgOjugcQOkwDie68PV0Nv6smc=", "transactions": "/ip4/127.0.0.1/tcp/0/http", "worker_to_worker": "/ip4/127.0.0.1/tcp/0/http", "primary_to_worker": "/ip4/127.0.0.1/tcp/0/http" }, "3": { - "name": "XEf+9+MRPcAcVu9NR3v+UVevwzlpoBT4u1U34YzOxkw=", + "name": "B/IVZMS3q99iaMGt3p3tC6HfMSKWif9Wov+b5KpzAGA=", "transactions": "/ip4/127.0.0.1/tcp/0/http", "worker_to_worker": "/ip4/127.0.0.1/tcp/0/http", "primary_to_worker": "/ip4/127.0.0.1/tcp/0/http" } }, - "ucbuFjDvPnERRKZI2wa7sihPcnTPvuU//O5QPMGkkgA=": { + "tOu6CCUfQFvA7Oo9IQsi6Q25ThGDmgcTXMYn4QVX8D8HeuI1DBmnctVFka/y0GijF5oKKOglBJNWsPz6LaE5YczKopYHmwm2kIxBwYHPdj186+KU8QfuvlZpHn/OnuCS": { "0": { - "name": "rvP0pLjsod/DQzYb+OQ2vULeklnAS4MU644gVN1ugqs=", + "name": "+oKq7VFT0pAQvjlvEti2YUw5fHXEYT/bs21P9wTlAKs=", "transactions": "/ip4/127.0.0.1/tcp/0/http", "worker_to_worker": "/ip4/127.0.0.1/tcp/0/http", "primary_to_worker": "/ip4/127.0.0.1/tcp/0/http" }, "1": { - "name": "ildi4hrBzbOHBELHe0w69Yx87bh3nQJw5tTx4vc2fXQ=", + "name": "O6EMZUvkFG2rPW2rgLPOJM4323x0XCslMgXWL5Z7ALM=", "transactions": "/ip4/127.0.0.1/tcp/0/http", "worker_to_worker": "/ip4/127.0.0.1/tcp/0/http", "primary_to_worker": "/ip4/127.0.0.1/tcp/0/http" }, "2": { - "name": "zGIzLjS7LVzWn2Dvuyo2y5FsfrRYMB6jZjbE27ASvYg=", + "name": "lrisYqEadH5cgLhsT1EW5q6uVKxwCXLTJQO3klahUy8=", "transactions": "/ip4/127.0.0.1/tcp/0/http", "worker_to_worker": "/ip4/127.0.0.1/tcp/0/http", "primary_to_worker": "/ip4/127.0.0.1/tcp/0/http" }, "3": { - "name": "I47bbumpH9yOcb5QwKP7PPKS2QJN26wCqqcJCWsKqdo=", + "name": "Kt9mRluFkBunwfq2VREQbBXuSYGOsFo95bA/PIrvVhc=", "transactions": "/ip4/127.0.0.1/tcp/0/http", "worker_to_worker": "/ip4/127.0.0.1/tcp/0/http", "primary_to_worker": "/ip4/127.0.0.1/tcp/0/http" diff --git a/consensus/src/consensus.rs b/consensus/src/consensus.rs index e7e9183e7..aad1c56d4 100644 --- a/consensus/src/consensus.rs +++ b/consensus/src/consensus.rs @@ -1,6 +1,9 @@ // Copyright (c) 2021, Facebook, Inc. and its affiliates // Copyright (c) 2022, Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 + +#![allow(clippy::mutable_key_type)] + use crate::{metrics::ConsensusMetrics, ConsensusOutput, SequenceNumber}; use config::Committee; use crypto::PublicKey; @@ -242,6 +245,7 @@ where Ok(ConsensusState::new(genesis, self.metrics.clone())) } + #[allow(clippy::mutable_key_type)] async fn run( &mut self, recover_last_committed: HashMap, diff --git a/crypto/src/lib.rs b/crypto/src/lib.rs index 5f5834ec7..d7f56844c 100644 --- a/crypto/src/lib.rs +++ b/crypto/src/lib.rs @@ -8,7 +8,7 @@ rust_2021_compatibility )] -use fastcrypto::ed25519; +use fastcrypto::{bls12381, ed25519}; // This re-export allows using the trait-defined APIs pub use fastcrypto::traits; @@ -26,11 +26,11 @@ pub use fastcrypto::traits; // to change all four aliases to point to concrete types that work with each other. Failure to do // so will result in a ton of compilation errors, and worse: it will not make sense! -pub type PublicKey = ed25519::Ed25519PublicKey; -pub type Signature = ed25519::Ed25519Signature; -pub type AggregateSignature = ed25519::Ed25519AggregateSignature; -pub type PrivateKey = ed25519::Ed25519PrivateKey; -pub type KeyPair = ed25519::Ed25519KeyPair; +pub type PublicKey = bls12381::BLS12381PublicKey; +pub type Signature = bls12381::BLS12381Signature; +pub type AggregateSignature = bls12381::BLS12381AggregateSignature; +pub type PrivateKey = bls12381::BLS12381PrivateKey; +pub type KeyPair = bls12381::BLS12381KeyPair; // Example to use BLS12-377 instead: // #[cfg(feature = "celo")] @@ -41,6 +41,10 @@ pub type KeyPair = ed25519::Ed25519KeyPair; // pub type PrivateKey = bls12377::BLS12377PrivateKey; // #[cfg(feature = "celo")] // pub type KeyPair = bls12377::BLS12377KeyPair; + +pub type NetworkPublicKey = ed25519::Ed25519PublicKey; +pub type NetworkKeyPair = ed25519::Ed25519KeyPair; + //////////////////////////////////////////////////////////////////////// #[cfg(all(test, feature = "celo"))] diff --git a/network/src/primary.rs b/network/src/primary.rs index d94772756..56e4e1683 100644 --- a/network/src/primary.rs +++ b/network/src/primary.rs @@ -9,7 +9,7 @@ use crate::{ }; use anemo::PeerId; use async_trait::async_trait; -use crypto::PublicKey; +use crypto::NetworkPublicKey; use multiaddr::Multiaddr; use rand::{rngs::SmallRng, SeedableRng as _}; use std::collections::HashMap; @@ -205,7 +205,7 @@ impl PrimaryNetwork { impl UnreliableNetwork2 for PrimaryNetwork { async fn unreliable_send( &mut self, - peer: PublicKey, + peer: NetworkPublicKey, message: &PrimaryMessage, ) -> JoinHandle<()> { let network = self.network.clone(); @@ -235,7 +235,7 @@ impl Lucky for PrimaryNetwork { impl ReliableNetwork2 for PrimaryNetwork { async fn send( &mut self, - peer: PublicKey, + peer: NetworkPublicKey, message: &PrimaryMessage, ) -> CancelOnDropHandler>> { // Safety diff --git a/network/src/traits.rs b/network/src/traits.rs index 0454cd133..623a21aac 100644 --- a/network/src/traits.rs +++ b/network/src/traits.rs @@ -1,7 +1,7 @@ // Copyright (c) 2022, Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 use async_trait::async_trait; -use crypto::PublicKey; +use crypto::NetworkPublicKey; use multiaddr::Multiaddr; use rand::prelude::{SliceRandom, SmallRng}; use serde::Serialize; @@ -104,13 +104,17 @@ pub trait ReliableNetwork: BaseNetwork { #[async_trait] pub trait UnreliableNetwork2 { - async fn unreliable_send(&mut self, peer: PublicKey, message: &Message) -> JoinHandle<()>; + async fn unreliable_send( + &mut self, + peer: NetworkPublicKey, + message: &Message, + ) -> JoinHandle<()>; /// Broadcasts a message to all `peers` passed as an argument. /// The attempts to send individual messages are best effort and will not be retried. async fn unreliable_broadcast( &mut self, - peers: Vec, + peers: Vec, message: &Message, ) -> Vec> { let mut handlers = Vec::new(); @@ -132,7 +136,7 @@ pub trait LuckyNetwork2 { /// message only to them. This is useful to pick nodes with whom to sync. async fn lucky_broadcast( &mut self, - mut peers: Vec, + mut peers: Vec, message: &Message, num_nodes: usize, ) -> Vec>; @@ -147,7 +151,7 @@ where { async fn lucky_broadcast( &mut self, - mut peers: Vec, + mut peers: Vec, message: &M, nodes: usize, ) -> Vec> { @@ -161,13 +165,13 @@ where pub trait ReliableNetwork2 { async fn send( &mut self, - peer: PublicKey, + peer: NetworkPublicKey, message: &Message, ) -> CancelOnDropHandler>>; async fn broadcast( &mut self, - peers: Vec, + peers: Vec, message: &Message, ) -> Vec>>> { let mut handlers = Vec::new(); diff --git a/node/src/generate_format.rs b/node/src/generate_format.rs index 747f53f0f..80d809a7c 100644 --- a/node/src/generate_format.rs +++ b/node/src/generate_format.rs @@ -1,7 +1,7 @@ // Copyright (c) 2022, Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 use config::{Authority, Committee, Epoch, PrimaryAddresses, WorkerIndex, WorkerInfo}; -use crypto::KeyPair; +use crypto::{KeyPair, NetworkKeyPair}; use fastcrypto::{ traits::{KeyPair as _, Signer}, Digest, Hash, @@ -24,8 +24,18 @@ fn get_registry() -> Result { // tracer.trace_value(&mut samples, ...)?; // with all the base types contained in messages, especially the ones with custom serializers; // or involving generics (see [serde_reflection documentation](https://docs.rs/serde-reflection/latest/serde_reflection/)). + // Trace the corresponding header let mut rng = StdRng::from_seed([0; 32]); - let kp = KeyPair::generate(&mut rng); + let (keys, network_keys): (Vec<_>, Vec<_>) = (0..4) + .map(|_| { + ( + KeyPair::generate(&mut rng), + NetworkKeyPair::generate(&mut rng), + ) + }) + .unzip(); + + let kp = keys[0].copy(); let pk = kp.public().clone(); tracer.trace_value(&mut samples, &pk)?; @@ -34,14 +44,13 @@ fn get_registry() -> Result { let signature = kp.try_sign(msg).unwrap(); tracer.trace_value(&mut samples, &signature)?; - // Trace the corresponding header - let keys: Vec<_> = (0..4).map(|_| KeyPair::generate(&mut rng)).collect(); let committee = Committee { epoch: Epoch::default(), authorities: keys .iter() + .zip(network_keys.iter()) .enumerate() - .map(|(i, kp)| { + .map(|(i, (kp, network_key))| { let id = kp.public(); let primary = PrimaryAddresses { primary_to_primary: format!("/ip4/127.0.0.1/tcp/{}/http", 100 + i) @@ -51,7 +60,14 @@ fn get_registry() -> Result { .parse() .unwrap(), }; - (id.clone(), Authority { stake: 1, primary }) + ( + id.clone(), + Authority { + stake: 1, + primary, + network_key: network_key.public().clone(), + }, + ) }) .collect(), }; @@ -73,7 +89,7 @@ fn get_registry() -> Result { signature: kp.sign(Digest::from(header_digest).as_ref()), ..header }; - let pk = keys[0].public().clone(); + let worker_pk = network_keys[0].public().clone(); let certificate = Certificate::new_unsigned(&committee, header.clone(), vec![]).unwrap(); let signature = keys[0].sign(certificate.digest().as_ref()); let certificate = @@ -89,7 +105,7 @@ fn get_registry() -> Result { vec![( 0, WorkerInfo { - name: pk.clone(), + name: worker_pk, primary_to_worker: "/ip4/127.0.0.1/tcp/300/http".to_string().parse().unwrap(), transactions: "/ip4/127.0.0.1/tcp/400/http".to_string().parse().unwrap(), worker_to_worker: "/ip4/127.0.0.1/tcp/500/http".to_string().parse().unwrap(), diff --git a/node/src/lib.rs b/node/src/lib.rs index ff6c7fbd4..3a0d13920 100644 --- a/node/src/lib.rs +++ b/node/src/lib.rs @@ -8,7 +8,7 @@ use consensus::{ Consensus, ConsensusOutput, }; -use crypto::{KeyPair, PublicKey}; +use crypto::{KeyPair, NetworkKeyPair, PublicKey}; use executor::{ get_restored_consensus_output, ExecutionState, Executor, ExecutorOutput, SerializedTransaction, SubscriberResult, @@ -127,6 +127,8 @@ impl Node { pub async fn spawn_primary( // The private-public key pair of this authority. keypair: KeyPair, + // The private-public network key pair of this authority. + network_keypair: NetworkKeyPair, // The committee information. committee: SharedCommittee, // The worker information cache. @@ -231,6 +233,7 @@ impl Node { let primary_handles = Primary::spawn( name.clone(), keypair, + network_keypair, committee.clone(), worker_cache.clone(), parameters.clone(), @@ -363,7 +366,7 @@ impl Node { // The public key of this authority. primary_name: PublicKey, // The ids & keypairs of the workers to spawn. - ids_and_keypairs: Vec<(WorkerId, KeyPair)>, + ids_and_keypairs: Vec<(WorkerId, NetworkKeyPair)>, // The committee information. committee: SharedCommittee, // The worker information cache. diff --git a/node/src/main.rs b/node/src/main.rs index 368d39bfa..5ef7b2aa8 100644 --- a/node/src/main.rs +++ b/node/src/main.rs @@ -11,10 +11,10 @@ use arc_swap::ArcSwap; use clap::{crate_name, crate_version, App, AppSettings, ArgMatches, SubCommand}; use config::{Committee, Import, Parameters, WorkerCache, WorkerId}; -use crypto::KeyPair; +use crypto::{KeyPair, NetworkKeyPair}; use executor::{SerializedTransaction, SubscriberResult}; use eyre::Context; -use fastcrypto::{ed25519::Ed25519KeyPair, generate_production_keypair, traits::KeyPair as _}; +use fastcrypto::{generate_production_keypair, traits::KeyPair as _}; use futures::future::join_all; use node::{ execution_state::SimpleExecutionState, @@ -46,10 +46,16 @@ async fn main() -> Result<(), eyre::Report> { .about("Print a fresh key pair to file") .args_from_usage("--filename= 'The file where to print the new key pair'"), ) + .subcommand( + SubCommand::with_name("generate_network_keys") + .about("Print a fresh network key pair (ed25519) to file") + .args_from_usage("--filename= 'The file where to print the new network key pair'"), + ) .subcommand( SubCommand::with_name("run") .about("Run a node") .args_from_usage("--primary-keys= 'The file containing the node's primary keys'") + .args_from_usage("--primary-network-keys= 'The file containing the node's primary network keys'") .args_from_usage("--worker-keys= 'The file containing the node's worker keys'") .args_from_usage("--committee= 'The file containing committee information'") .args_from_usage("--workers= 'The file containing worker information'") @@ -91,14 +97,23 @@ async fn main() -> Result<(), eyre::Report> { let _guard = setup_telemetry(tracing_level, network_tracing_level, None); let kp = generate_production_keypair::(); config::Export::export(&kp, sub_matches.value_of("filename").unwrap()) - .context("Failed to generate key pair")? + .context("Failed to generate key pair")?; + } + ("generate_network_keys", Some(sub_matches)) => { + let _guard = setup_telemetry(tracing_level, network_tracing_level, None); + let network_kp = generate_production_keypair::(); + config::Export::export(&network_kp, sub_matches.value_of("filename").unwrap()) + .context("Failed to generate network key pair")? } ("run", Some(sub_matches)) => { let primary_key_file = sub_matches.value_of("primary-keys").unwrap(); let primary_keypair = KeyPair::import(primary_key_file) .context("Failed to load the node's primary keypair")?; + let primary_network_key_file = sub_matches.value_of("primary-network-keys").unwrap(); + let primary_network_keypair = NetworkKeyPair::import(primary_network_key_file) + .context("Failed to load the node's primary network keypair")?; let worker_key_file = sub_matches.value_of("worker-keys").unwrap(); - let worker_keypair = KeyPair::import(worker_key_file) + let worker_keypair = NetworkKeyPair::import(worker_key_file) .context("Failed to load the node's worker keypair")?; let registry = match sub_matches.subcommand() { ("primary", _) => primary_metrics_registry(primary_keypair.public().clone()), @@ -123,7 +138,14 @@ async fn main() -> Result<(), eyre::Report> { let _guard = setup_telemetry(tracing_level, network_tracing_level, Some(®istry)); } } - run(sub_matches, primary_keypair, worker_keypair, registry).await? + run( + sub_matches, + primary_keypair, + primary_network_keypair, + worker_keypair, + registry, + ) + .await? } _ => unreachable!(), } @@ -180,8 +202,9 @@ fn setup_benchmark_telemetry( // Runs either a worker or a primary. async fn run( matches: &ArgMatches<'_>, - primary_keypair: Ed25519KeyPair, - worker_keypair: Ed25519KeyPair, + primary_keypair: KeyPair, + primary_network_keypair: NetworkKeyPair, + worker_keypair: NetworkKeyPair, registry: Registry, ) -> Result<(), eyre::Report> { let committee_file = matches.value_of("committee").unwrap(); @@ -218,6 +241,7 @@ async fn run( ("primary", Some(sub_matches)) => { Node::spawn_primary( primary_keypair, + primary_network_keypair, committee, worker_cache, &store, diff --git a/node/src/restarter.rs b/node/src/restarter.rs index faedf9b65..3c9482348 100644 --- a/node/src/restarter.rs +++ b/node/src/restarter.rs @@ -3,7 +3,7 @@ use crate::{Node, NodeStorage}; use arc_swap::ArcSwap; use config::{Committee, Parameters, SharedWorkerCache, WorkerCache, WorkerId}; -use crypto::KeyPair; +use crypto::{KeyPair, NetworkKeyPair}; use executor::{ExecutionState, ExecutorOutput}; use fastcrypto::traits::KeyPair as _; use futures::future::join_all; @@ -20,13 +20,20 @@ pub struct NodeRestarter; impl NodeRestarter { pub async fn watch( primary_keypair: KeyPair, - worker_ids_and_keypairs: Vec<(WorkerId, KeyPair)>, + primary_network_keypair: NetworkKeyPair, + worker_ids_and_keypairs: Vec<(WorkerId, NetworkKeyPair)>, committee: &Committee, worker_cache: SharedWorkerCache, storage_base_path: PathBuf, execution_state: Arc, parameters: Parameters, - mut rx_reconfigure: Receiver<(KeyPair, Committee, Vec<(WorkerId, KeyPair)>, WorkerCache)>, + mut rx_reconfigure: Receiver<( + KeyPair, + NetworkKeyPair, + Committee, + Vec<(WorkerId, NetworkKeyPair)>, + WorkerCache, + )>, tx_output: Sender>, registry: &Registry, ) where @@ -35,6 +42,7 @@ impl NodeRestarter { State::Error: Debug, { let mut primary_keypair = primary_keypair; + let mut primary_network_keypair = primary_network_keypair; let mut name = primary_keypair.public().clone(); let mut worker_ids_and_keypairs = worker_ids_and_keypairs; let mut committee = committee.clone(); @@ -55,6 +63,7 @@ impl NodeRestarter { // Restart the relevant components. let primary_handles = Node::spawn_primary( primary_keypair, + primary_network_keypair, Arc::new(ArcSwap::new(Arc::new(committee.clone()))), worker_cache.clone(), &store, @@ -81,11 +90,16 @@ impl NodeRestarter { handles.extend(worker_handles); // Wait for a committee change. - let (new_keypair, new_committee, new_worker_ids_and_keypairs, new_worker_cache) = - match rx_reconfigure.recv().await { - Some(x) => x, - None => break, - }; + let ( + new_keypair, + new_network_keypair, + new_committee, + new_worker_ids_and_keypairs, + new_worker_cache, + ) = match rx_reconfigure.recv().await { + Some(x) => x, + None => break, + }; tracing::info!("Starting reconfiguration with committee {committee}"); // Shutdown all relevant components. @@ -127,6 +141,7 @@ impl NodeRestarter { // Update the settings for the next epoch. primary_keypair = new_keypair; + primary_network_keypair = new_network_keypair; name = primary_keypair.public().clone(); worker_ids_and_keypairs = new_worker_ids_and_keypairs; committee = new_committee; diff --git a/node/tests/node_smoke_test.rs b/node/tests/node_smoke_test.rs index 90523a4a7..6d45f3e96 100644 --- a/node/tests/node_smoke_test.rs +++ b/node/tests/node_smoke_test.rs @@ -25,6 +25,15 @@ fn test_primary_no_consensus() { .keypair() .export(&primary_keys_file_path) .unwrap(); + let primary_network_keys_file_path = + format!("{config_path}/smoke_test_network_primary_keys.json"); + fixture + .authorities() + .next() + .unwrap() + .network_keypair() + .export(&primary_network_keys_file_path) + .unwrap(); let worker_keys_file_path = format!("{config_path}/smoke_test_worker_keys.json"); fixture .authorities() @@ -52,6 +61,8 @@ fn test_primary_no_consensus() { &workers_file_path, "--primary-keys", &primary_keys_file_path, + "--primary-network-keys", + &primary_network_keys_file_path, "--worker-keys", &worker_keys_file_path, "--store", @@ -98,6 +109,15 @@ fn test_primary_with_consensus() { .keypair() .export(&primary_keys_file_path) .unwrap(); + let primary_network_keys_file_path = + format!("{config_path}/smoke_test_network_primary_keys.json"); + fixture + .authorities() + .next() + .unwrap() + .network_keypair() + .export(&primary_network_keys_file_path) + .unwrap(); let worker_keys_file_path = format!("{config_path}/smoke_test_worker_keys.json"); fixture .authorities() @@ -125,6 +145,8 @@ fn test_primary_with_consensus() { &workers_file_path, "--primary-keys", &primary_keys_file_path, + "--primary-network-keys", + &primary_network_keys_file_path, "--worker-keys", &worker_keys_file_path, "--store", diff --git a/node/tests/reconfigure.rs b/node/tests/reconfigure.rs index 12e12095a..ff45c4792 100644 --- a/node/tests/reconfigure.rs +++ b/node/tests/reconfigure.rs @@ -4,7 +4,7 @@ use arc_swap::ArcSwap; use bytes::Bytes; use config::{Committee, Parameters, SharedWorkerCache, WorkerCache, WorkerId}; use consensus::ConsensusOutput; -use crypto::{KeyPair, PublicKey}; +use crypto::{KeyPair, NetworkKeyPair, PublicKey}; use executor::{ExecutionIndices, ExecutionState, ExecutionStateError}; use fastcrypto::traits::KeyPair as _; use futures::future::join_all; @@ -26,22 +26,37 @@ use types::{ReconfigureNotification, TransactionProto, TransactionsClient, Worke /// A simple/dumb execution engine. struct SimpleExecutionState { keypair: KeyPair, - worker_keypairs: Vec, + network_keypair: NetworkKeyPair, + worker_keypairs: Vec, worker_cache: WorkerCache, committee: Arc>, - tx_reconfigure: Sender<(KeyPair, Committee, Vec<(WorkerId, KeyPair)>, WorkerCache)>, + tx_reconfigure: Sender<( + KeyPair, + NetworkKeyPair, + Committee, + Vec<(WorkerId, NetworkKeyPair)>, + WorkerCache, + )>, } impl SimpleExecutionState { pub fn new( keypair: KeyPair, - worker_keypairs: Vec, + network_keypair: NetworkKeyPair, + worker_keypairs: Vec, worker_cache: WorkerCache, committee: Committee, - tx_reconfigure: Sender<(KeyPair, Committee, Vec<(WorkerId, KeyPair)>, WorkerCache)>, + tx_reconfigure: Sender<( + KeyPair, + NetworkKeyPair, + Committee, + Vec<(WorkerId, NetworkKeyPair)>, + WorkerCache, + )>, ) -> Self { Self { keypair, + network_keypair, worker_keypairs, worker_cache, committee: Arc::new(Mutex::new(committee)), @@ -81,6 +96,7 @@ impl ExecutionState for SimpleExecutionState { self.tx_reconfigure .send(( self.keypair.copy(), + self.network_keypair.copy(), new_committee, worker_ids_and_keypairs, self.worker_cache.clone(), @@ -193,6 +209,7 @@ async fn restart() { let execution_state = Arc::new(SimpleExecutionState::new( a.keypair().copy(), + a.network_keypair().copy(), a.worker_keypairs(), fixture.worker_cache(), committee.clone(), @@ -209,9 +226,11 @@ async fn restart() { let execution_state = execution_state.clone(); let parameters = parameters.clone(); let keypair = a.keypair().copy(); + let network_keypair = a.network_keypair().copy(); tokio::spawn(async move { NodeRestarter::watch( keypair, + network_keypair, worker_ids_and_keypairs, &committee, worker_cache, @@ -292,6 +311,7 @@ async fn epoch_change() { let execution_state = Arc::new(SimpleExecutionState::new( a.keypair().copy(), + a.network_keypair().copy(), a.worker_keypairs(), fixture.worker_cache(), committee.clone(), @@ -306,7 +326,7 @@ async fn epoch_change() { let mut primary_network = WorkerToPrimaryNetwork::default(); let mut worker_network = PrimaryToWorkerNetwork::default(); - while let Some((_, committee, _, _)) = rx_node_reconfigure.recv().await { + while let Some((_, _, committee, _, _)) = rx_node_reconfigure.recv().await { let address = committee .primary(&name_clone) .expect("Our key is not in the committee") @@ -336,6 +356,7 @@ async fn epoch_change() { let _primary_handles = Node::spawn_primary( a.keypair().copy(), + a.network_keypair().copy(), Arc::new(ArcSwap::new(Arc::new(committee.clone()))), worker_cache.clone(), &store, diff --git a/node/tests/staged/narwhal.yaml b/node/tests/staged/narwhal.yaml index 88f6000f7..80ecbd9e8 100644 --- a/node/tests/staged/narwhal.yaml +++ b/node/tests/staged/narwhal.yaml @@ -4,6 +4,15 @@ Authority: - stake: U32 - primary: TYPENAME: PrimaryAddresses + - network_key: + TYPENAME: Ed25519PublicKey +BLS12381AggregateSignature: + STRUCT: + - sig: + OPTION: BYTES +BLS12381Signature: + STRUCT: + - sig: BYTES Batch: NEWTYPESTRUCT: SEQ: @@ -18,7 +27,7 @@ Certificate: - header: TYPENAME: Header - aggregated_signature: - TYPENAME: Ed25519AggregateSignature + TYPENAME: BLS12381AggregateSignature - signed_authorities: BYTES CertificateDigest: NEWTYPESTRUCT: @@ -29,23 +38,15 @@ Committee: STRUCT: - authorities: MAP: - KEY: - TYPENAME: Ed25519PublicKey + KEY: STR VALUE: TYPENAME: Authority - epoch: U64 -Ed25519AggregateSignature: - NEWTYPESTRUCT: - SEQ: BYTES Ed25519PublicKey: NEWTYPESTRUCT: STR -Ed25519Signature: - STRUCT: - - raw: BYTES Header: STRUCT: - - author: - TYPENAME: Ed25519PublicKey + - author: STR - round: U64 - epoch: U64 - payload: @@ -59,7 +60,7 @@ Header: - id: TYPENAME: HeaderDigest - signature: - TYPENAME: Ed25519Signature + TYPENAME: BLS12381Signature HeaderDigest: NEWTYPESTRUCT: TUPLEARRAY: @@ -76,7 +77,7 @@ PrimaryWorkerMessage: TUPLE: - SEQ: TYPENAME: BatchDigest - - TYPENAME: Ed25519PublicKey + - STR 1: Cleanup: NEWTYPE: U64 diff --git a/primary/src/block_remover.rs b/primary/src/block_remover.rs index 65a092c7a..031b6eebe 100644 --- a/primary/src/block_remover.rs +++ b/primary/src/block_remover.rs @@ -81,7 +81,7 @@ pub struct DeleteBatchMessage { /// # use fastcrypto::Hash; /// # use std::env::temp_dir; /// # use fastcrypto::Digest; -/// # use fastcrypto::ed25519::Ed25519PublicKey; +/// # use crypto::PublicKey; /// # use config::{Committee, WorkerCache, SharedWorkerCache}; /// # use consensus::dag::Dag; /// # use futures::future::join_all; @@ -124,7 +124,7 @@ pub struct DeleteBatchMessage { /// let (tx_removed_certificates, _rx_removed_certificates) = test_utils::test_channel!(1); /// let (tx_delete_block_result, mut rx_delete_block_result) = channel(1); /// -/// let name = Ed25519PublicKey::default(); +/// let name = PublicKey::default(); /// let committee = Committee{ epoch: 0, authorities: BTreeMap::new() }; /// let worker_cache: SharedWorkerCache = WorkerCache{ epoch: 0, workers: BTreeMap::new() }.into(); /// let (_tx_reconfigure, rx_reconfigure) = watch::channel(ReconfigureNotification::NewEpoch(committee.clone())); diff --git a/primary/src/block_synchronizer/mod.rs b/primary/src/block_synchronizer/mod.rs index 7a861cf59..e45fe2eb5 100644 --- a/primary/src/block_synchronizer/mod.rs +++ b/primary/src/block_synchronizer/mod.rs @@ -631,18 +631,18 @@ impl BlockSynchronizer { async fn broadcast_batch_request(&mut self, message: PrimaryMessage) -> Vec { // Naively now just broadcast the request to all the primaries - let primaries_names: Vec<_> = self + let (keys, network_keys): (Vec<_>, Vec<_>) = self .committee .others_primaries(&self.name) .into_iter() - .map(|(name, _address)| name) - .collect(); + .map(|(name, _address, network_key)| (name, network_key)) + .unzip(); self.primary_network - .unreliable_broadcast(primaries_names.clone(), &message) + .unreliable_broadcast(network_keys.clone(), &message) .await; - primaries_names + keys } #[instrument(level="trace", skip_all, fields(request_id = ?request_id))] diff --git a/primary/src/block_synchronizer/peers.rs b/primary/src/block_synchronizer/peers.rs index ce2535d5f..0fa269f10 100644 --- a/primary/src/block_synchronizer/peers.rs +++ b/primary/src/block_synchronizer/peers.rs @@ -1,5 +1,6 @@ // Copyright (c) 2022, Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 + use crypto::PublicKey; use fastcrypto::Hash; use rand::{prelude::SliceRandom as _, rngs::SmallRng}; @@ -74,6 +75,7 @@ impl Peers { } } + #[allow(clippy::mutable_key_type)] pub fn peers(&self) -> &HashMap> { &self.peers } @@ -268,6 +270,7 @@ mod tests { } } + #[allow(clippy::mutable_key_type)] #[test] fn test_assign_certificates_to_peers_when_all_respond_uniquely() { struct TestCase { diff --git a/primary/src/block_synchronizer/tests/block_synchronizer_tests.rs b/primary/src/block_synchronizer/tests/block_synchronizer_tests.rs index dbf3f4853..76c5c0915 100644 --- a/primary/src/block_synchronizer/tests/block_synchronizer_tests.rs +++ b/primary/src/block_synchronizer/tests/block_synchronizer_tests.rs @@ -26,7 +26,7 @@ use tokio::{ }; use types::ReconfigureNotification; -use crypto::KeyPair; +use crypto::NetworkKeyPair; use fastcrypto::traits::KeyPair as _; use tracing::debug; use types::{Certificate, CertificateDigest}; @@ -44,7 +44,7 @@ async fn test_successful_headers_synchronization() { let author = fixture.authorities().next().unwrap(); let primary = fixture.authorities().nth(1).unwrap(); let name = primary.public_key(); - let network_key = primary.keypair().copy().private().0.to_bytes(); + let network_key = primary.network_keypair().copy().private().0.to_bytes(); let (_tx_reconfigure, rx_reconfigure) = watch::channel(ReconfigureNotification::NewEpoch(committee.clone())); @@ -85,8 +85,8 @@ async fn test_successful_headers_synchronization() { .start(anemo::Router::new()) .unwrap(); - for (pubkey, addresses) in committee.others_primaries(&name) { - let peer_id = PeerId(pubkey.0.to_bytes()); + for (_pubkey, addresses, network_pubkey) in committee.others_primaries(&name) { + let peer_id = PeerId(network_pubkey.0.to_bytes()); let address = network::multiaddr_to_address(&addresses.primary_to_primary).unwrap(); let peer_info = PeerInfo { peer_id, @@ -125,7 +125,7 @@ async fn test_successful_headers_synchronization() { .unwrap() .primary_to_primary; println!("New primary added: {:?}", address); - primary_listener(1, a.keypair().copy(), address) + primary_listener(1, a.network_keypair().copy(), address) }) .collect(); @@ -244,7 +244,7 @@ async fn test_successful_payload_synchronization() { let author = fixture.authorities().next().unwrap(); let primary = fixture.authorities().nth(1).unwrap(); let name = primary.public_key(); - let network_key = primary.keypair().copy().private().0.to_bytes(); + let network_key = primary.network_keypair().copy().private().0.to_bytes(); let (_tx_reconfigure, rx_reconfigure) = watch::channel(ReconfigureNotification::NewEpoch(committee.clone())); @@ -286,8 +286,8 @@ async fn test_successful_payload_synchronization() { .start(anemo::Router::new()) .unwrap(); - for (pubkey, addresses) in committee.others_primaries(&name) { - let peer_id = PeerId(pubkey.0.to_bytes()); + for (_pubkey, addresses, network_pubkey) in committee.others_primaries(&name) { + let peer_id = PeerId(network_pubkey.0.to_bytes()); let address = network::multiaddr_to_address(&addresses.primary_to_primary).unwrap(); let peer_info = PeerInfo { peer_id, @@ -326,7 +326,7 @@ async fn test_successful_payload_synchronization() { .unwrap() .primary_to_primary; println!("New primary added: {:?}", address); - primary_listener(1, a.keypair().copy(), address) + primary_listener(1, a.network_keypair().copy(), address) }) .collect(); @@ -485,7 +485,7 @@ async fn test_multiple_overlapping_requests() { let author = fixture.authorities().next().unwrap(); let primary = fixture.authorities().nth(1).unwrap(); let name = primary.public_key(); - let network_key = primary.keypair().copy().private().0.to_bytes(); + let network_key = primary.network_keypair().copy().private().0.to_bytes(); let (_, rx_reconfigure) = watch::channel(ReconfigureNotification::NewEpoch(committee.clone())); let (_, rx_commands) = test_utils::test_channel!(10); @@ -618,7 +618,7 @@ async fn test_timeout_while_waiting_for_certificates() { let author = fixture.authorities().next().unwrap(); let primary = fixture.authorities().nth(1).unwrap(); let name = primary.public_key(); - let network_key = primary.keypair().copy().private().0.to_bytes(); + let network_key = primary.network_keypair().copy().private().0.to_bytes(); let (_tx_reconfigure, rx_reconfigure) = watch::channel(ReconfigureNotification::NewEpoch(committee.clone())); @@ -730,7 +730,7 @@ async fn test_reply_with_certificates_already_in_storage() { let author = fixture.authorities().next().unwrap(); let primary = fixture.authorities().nth(1).unwrap(); let name = primary.public_key(); - let network_key = primary.keypair().copy().private().0.to_bytes(); + let network_key = primary.network_keypair().copy().private().0.to_bytes(); let (_, rx_reconfigure) = watch::channel(ReconfigureNotification::NewEpoch(committee.clone())); let (_, rx_commands) = test_utils::test_channel!(10); @@ -838,7 +838,7 @@ async fn test_reply_with_payload_already_in_storage() { let author = fixture.authorities().next().unwrap(); let primary = fixture.authorities().nth(1).unwrap(); let name = primary.public_key(); - let network_key = primary.keypair().copy().private().0.to_bytes(); + let network_key = primary.network_keypair().copy().private().0.to_bytes(); let (_, rx_reconfigure) = watch::channel(ReconfigureNotification::NewEpoch(committee.clone())); let (_, rx_commands) = test_utils::test_channel!(10); @@ -947,7 +947,7 @@ async fn test_reply_with_payload_already_in_storage_for_own_certificates() { let committee = fixture.committee(); let worker_cache = fixture.shared_worker_cache(); let primary = fixture.authorities().next().unwrap(); - let network_key = primary.keypair().copy().private().0.to_bytes(); + let network_key = primary.network_keypair().copy().private().0.to_bytes(); // AND make sure the key used for our "own" primary is the one that will // be used to create the headers. @@ -1044,11 +1044,11 @@ async fn test_reply_with_payload_already_in_storage_for_own_certificates() { #[must_use] fn primary_listener( num_of_expected_responses: i32, - keypair: KeyPair, + network_keypair: NetworkKeyPair, address: multiaddr::Multiaddr, ) -> JoinHandle> { tokio::spawn(async move { - let (mut recv, _network) = PrimaryToPrimaryMockServer::spawn(keypair, address); + let (mut recv, _network) = PrimaryToPrimaryMockServer::spawn(network_keypair, address); let mut responses = Vec::new(); loop { diff --git a/primary/src/block_waiter.rs b/primary/src/block_waiter.rs index c4699a7fa..7ea705987 100644 --- a/primary/src/block_waiter.rs +++ b/primary/src/block_waiter.rs @@ -124,8 +124,8 @@ type RequestKey = Vec; /// # use arc_swap::ArcSwap; /// # use fastcrypto::Hash; /// # use std::env::temp_dir; -/// # use fastcrypto::ed25519::Ed25519PublicKey; /// # use config::{Committee, WorkerCache, SharedWorkerCache}; +/// # use crypto::PublicKey; /// # use std::collections::BTreeMap; /// # use types::Certificate; /// # use primary::{BlockWaiter, BlockHeader, BlockCommand, block_synchronizer::{BlockSynchronizeResult, handler::{Error, Handler}}}; @@ -164,7 +164,7 @@ type RequestKey = Vec; /// let (tx_batches, rx_batches) = test_utils::test_channel!(1); /// let (tx_get_block, mut rx_get_block) = oneshot::channel(); /// -/// let name = Ed25519PublicKey::default(); +/// let name = PublicKey::default(); /// let committee = Committee{ epoch: 0, authorities: BTreeMap::new() }; /// let worker_cache: SharedWorkerCache = WorkerCache{ epoch: 0, workers: BTreeMap::new() }.into(); /// let (_tx_reconfigure, rx_reconfigure) = watch::channel(ReconfigureNotification::NewEpoch(committee.clone())); diff --git a/primary/src/core.rs b/primary/src/core.rs index 2dce7a953..9f1e9a9c4 100644 --- a/primary/src/core.rs +++ b/primary/src/core.rs @@ -162,7 +162,7 @@ impl Core { .committee .others_primaries(&self.name) .into_iter() - .map(|(pubkey, _)| pubkey) + .map(|(_, _, network_key)| network_key) .collect(); let message = PrimaryMessage::Header(header.clone()); @@ -287,7 +287,10 @@ impl Core { } else { let handler = self .network - .send(header.author.clone(), &PrimaryMessage::Vote(vote)) + .send( + self.committee.network_key(&header.author).unwrap(), + &PrimaryMessage::Vote(vote), + ) .await; self.cancel_handlers .entry(header.round) @@ -311,14 +314,14 @@ impl Core { debug!("Assembled {:?}", certificate); // Broadcast the certificate. - let peers = self + let network_keys = self .committee .others_primaries(&self.name) .into_iter() - .map(|(pubkey, _)| pubkey) + .map(|(_, _, network_key)| network_key) .collect(); let message = PrimaryMessage::Certificate(certificate.clone()); - let handlers = self.network.broadcast(peers, &message).await; + let handlers = self.network.broadcast(network_keys, &message).await; self.cancel_handlers .entry(certificate.round()) .or_insert_with(Vec::new) diff --git a/primary/src/grpc_server/configuration.rs b/primary/src/grpc_server/configuration.rs index 4e6faceee..21d9fd484 100644 --- a/primary/src/grpc_server/configuration.rs +++ b/primary/src/grpc_server/configuration.rs @@ -97,6 +97,7 @@ impl Configuration for NarwhalConfiguration { ))) } + #[allow(clippy::mutable_key_type)] async fn new_network_info( &self, request: Request, diff --git a/primary/src/header_waiter.rs b/primary/src/header_waiter.rs index 7738a8b5d..0e6d36338 100644 --- a/primary/src/header_waiter.rs +++ b/primary/src/header_waiter.rs @@ -276,7 +276,7 @@ impl HeaderWaiter { } if !requires_sync.is_empty() { let message = PrimaryMessage::CertificatesRequest(requires_sync, self.name.clone()); - self.primary_network.unreliable_send(author.clone(), &message).await; + self.primary_network.unreliable_send(self.committee.network_key(&author).unwrap(), &message).await; } } } @@ -314,13 +314,13 @@ impl HeaderWaiter { } if !retry.is_empty() { - let addresses = self.committee + let network_keys = self.committee .others_primaries(&self.name) .into_iter() - .map(|(pubkey, _x)| pubkey) + .map(|(_, _, network_key)| network_key) .collect(); let message = PrimaryMessage::CertificatesRequest(retry, self.name.clone()); - self.primary_network.lucky_broadcast(addresses, &message, self.sync_retry_nodes).await; + self.primary_network.lucky_broadcast(network_keys, &message, self.sync_retry_nodes).await; } // Reschedule the timer. timer.as_mut().reset(Instant::now() + Duration::from_millis(TIMER_RESOLUTION)); diff --git a/primary/src/helper.rs b/primary/src/helper.rs index 4cdddd3fb..ac45052cf 100644 --- a/primary/src/helper.rs +++ b/primary/src/helper.rs @@ -157,7 +157,7 @@ impl Helper { from: self.name.clone(), }; self.primary_network - .unreliable_send(origin.clone(), &message) + .unreliable_send(self.committee.network_key(&origin).unwrap(), &message) .await; return Err(HelperError::StoreError(err)); @@ -195,7 +195,7 @@ impl Helper { from: self.name.clone(), }; self.primary_network - .unreliable_send(origin.clone(), &message) + .unreliable_send(self.committee.network_key(&origin).unwrap(), &message) .await; Ok(()) @@ -244,14 +244,14 @@ impl Helper { }; self.primary_network - .unreliable_send(origin.clone(), &message) + .unreliable_send(self.committee.network_key(&origin).unwrap(), &message) .await; } else { for certificate in certificates.into_iter().flatten() { // TODO: Remove this deserialization-serialization in the critical path. let message = PrimaryMessage::Certificate(certificate); self.primary_network - .unreliable_send(origin.clone(), &message) + .unreliable_send(self.committee.network_key(&origin).unwrap(), &message) .await; } } diff --git a/primary/src/primary.rs b/primary/src/primary.rs index 5bb90b73f..967a0af4c 100644 --- a/primary/src/primary.rs +++ b/primary/src/primary.rs @@ -23,7 +23,7 @@ use anemo::{types::PeerInfo, PeerId}; use async_trait::async_trait; use config::{Parameters, SharedCommittee, SharedWorkerCache, WorkerId, WorkerInfo}; use consensus::dag::Dag; -use crypto::{KeyPair, PublicKey}; +use crypto::{KeyPair, NetworkKeyPair, PublicKey}; use fastcrypto::{ traits::{EncodeDecodeBase64, KeyPair as _}, SignatureService, @@ -68,6 +68,7 @@ impl Primary { pub fn spawn( name: PublicKey, signer: KeyPair, + network_signer: NetworkKeyPair, committee: SharedCommittee, worker_cache: SharedWorkerCache, parameters: Parameters, @@ -199,7 +200,7 @@ impl Primary { let routes = anemo::Router::new().add_rpc_service(primary_service); let network = anemo::Network::bind(addr) .server_name("narwhal") - .private_key(signer.copy().private().0.to_bytes()) + .private_key(network_signer.copy().private().0.to_bytes()) .start(routes) .unwrap(); info!( @@ -208,8 +209,8 @@ impl Primary { address ); - for (pubkey, addresses) in committee.load().others_primaries(&name) { - let peer_id = PeerId(pubkey.0.to_bytes()); + for (_, addresses, network_pubkey) in committee.load().others_primaries(&name) { + let peer_id = PeerId(network_pubkey.0.to_bytes()); let address = network::multiaddr_to_address(&addresses.primary_to_primary).unwrap(); let peer_info = PeerInfo { peer_id, diff --git a/primary/src/tests/certificate_waiter_tests.rs b/primary/src/tests/certificate_waiter_tests.rs index 8e5170e4d..3633351d7 100644 --- a/primary/src/tests/certificate_waiter_tests.rs +++ b/primary/src/tests/certificate_waiter_tests.rs @@ -22,7 +22,7 @@ async fn process_certificate_missing_parents_in_reverse() { let committee = fixture.committee(); let worker_cache = fixture.shared_worker_cache(); let primary = fixture.authorities().next().unwrap(); - let network_key = primary.keypair().copy().private().0.to_bytes(); + let network_key = primary.network_keypair().copy().private().0.to_bytes(); let name = primary.public_key(); let signature_service = SignatureService::new(primary.keypair().copy()); @@ -176,7 +176,7 @@ async fn process_certificate_check_gc_fires() { let committee = fixture.committee(); let worker_cache = fixture.shared_worker_cache(); let primary = fixture.authorities().next().unwrap(); - let network_key = primary.keypair().copy().private().0.to_bytes(); + let network_key = primary.network_keypair().copy().private().0.to_bytes(); let name = primary.public_key(); let signature_service = SignatureService::new(primary.keypair().copy()); diff --git a/primary/src/tests/core_tests.rs b/primary/src/tests/core_tests.rs index 8e008af32..97bf1ff3d 100644 --- a/primary/src/tests/core_tests.rs +++ b/primary/src/tests/core_tests.rs @@ -21,7 +21,7 @@ async fn process_header() { let header = author.header(&committee); - let network_key = primary.keypair().copy().private().0.to_bytes(); + let network_key = primary.network_keypair().copy().private().0.to_bytes(); let name = primary.public_key(); let mut signature_service = SignatureService::new(primary.keypair().copy()); @@ -49,7 +49,7 @@ async fn process_header() { .unwrap() .primary_to_primary; let (mut handle, _network) = - PrimaryToPrimaryMockServer::spawn(author.keypair().copy(), address.clone()); + PrimaryToPrimaryMockServer::spawn(author.network_keypair().copy(), address.clone()); // Make a synchronizer for the core. let synchronizer = Synchronizer::new( @@ -74,8 +74,9 @@ async fn process_header() { .unwrap(); let address = network::multiaddr_to_address(&address).unwrap(); + let network_key = author.network_keypair().public(); let peer_info = PeerInfo { - peer_id: PeerId(header.author.0.to_bytes()), + peer_id: PeerId(network_key.0.to_bytes()), affinity: anemo::types::PeerAffinity::High, address: vec![address], }; @@ -134,7 +135,7 @@ async fn process_header_missing_parent() { let committee = fixture.committee(); let worker_cache = fixture.shared_worker_cache(); let primary = fixture.authorities().next().unwrap(); - let network_key = primary.keypair().copy().private().0.to_bytes(); + let network_key = primary.network_keypair().copy().private().0.to_bytes(); let name = primary.public_key(); let signature_service = SignatureService::new(primary.keypair().copy()); @@ -223,7 +224,7 @@ async fn process_header_missing_payload() { let committee = fixture.committee(); let worker_cache = fixture.shared_worker_cache(); let primary = fixture.authorities().next().unwrap(); - let network_key = primary.keypair().copy().private().0.to_bytes(); + let network_key = primary.network_keypair().copy().private().0.to_bytes(); let name = primary.public_key(); let signature_service = SignatureService::new(primary.keypair().copy()); @@ -312,7 +313,7 @@ async fn process_votes() { let committee = fixture.committee(); let worker_cache = fixture.shared_worker_cache(); let primary = fixture.authorities().next().unwrap(); - let network_key = primary.keypair().copy().private().0.to_bytes(); + let network_key = primary.network_keypair().copy().private().0.to_bytes(); let name = primary.public_key(); let signature_service = SignatureService::new(primary.keypair().copy()); @@ -352,8 +353,8 @@ async fn process_votes() { .start(anemo::Router::new()) .unwrap(); - for (pubkey, addresses) in committee.others_primaries(&name) { - let peer_id = PeerId(pubkey.0.to_bytes()); + for (_pubkey, addresses, network_pubkey) in committee.others_primaries(&name) { + let peer_id = PeerId(network_pubkey.0.to_bytes()); let address = network::multiaddr_to_address(&addresses.primary_to_primary).unwrap(); let peer_info = PeerInfo { peer_id, @@ -398,7 +399,7 @@ async fn process_votes() { .primary(&a.public_key()) .unwrap() .primary_to_primary; - PrimaryToPrimaryMockServer::spawn(a.keypair().copy(), address) + PrimaryToPrimaryMockServer::spawn(a.network_keypair().copy(), address) }) .collect(); @@ -436,7 +437,7 @@ async fn process_certificates() { let committee = fixture.committee(); let worker_cache = fixture.shared_worker_cache(); let primary = fixture.authorities().last().unwrap(); - let network_key = primary.keypair().copy().private().0.to_bytes(); + let network_key = primary.network_keypair().copy().private().0.to_bytes(); let name = primary.public_key(); let signature_service = SignatureService::new(primary.keypair().copy()); @@ -555,7 +556,7 @@ async fn shutdown_core() { let committee = fixture.committee(); let worker_cache = fixture.shared_worker_cache(); let primary = fixture.authorities().next().unwrap(); - let network_key = primary.keypair().copy().private().0.to_bytes(); + let network_key = primary.network_keypair().copy().private().0.to_bytes(); let name = primary.public_key(); let signature_service = SignatureService::new(primary.keypair().copy()); @@ -629,7 +630,7 @@ async fn reconfigure_core() { let worker_cache = fixture.shared_worker_cache(); let author = fixture.authorities().next().unwrap(); let primary = fixture.authorities().nth(1).unwrap(); - let network_key = primary.keypair().copy().private().0.to_bytes(); + let network_key = primary.network_keypair().copy().private().0.to_bytes(); let name = primary.public_key(); let mut signature_service = SignatureService::new(primary.keypair().copy()); @@ -663,7 +664,7 @@ async fn reconfigure_core() { .unwrap() .primary_to_primary; let (mut handle, _network) = - PrimaryToPrimaryMockServer::spawn(author.keypair().copy(), address.clone()); + PrimaryToPrimaryMockServer::spawn(author.network_keypair().copy(), address.clone()); // Make a synchronizer for the core. let synchronizer = Synchronizer::new( @@ -685,8 +686,9 @@ async fn reconfigure_core() { .start(anemo::Router::new()) .unwrap(); let address = network::multiaddr_to_address(&address).unwrap(); + let network_key = author.network_keypair(); let peer_info = PeerInfo { - peer_id: PeerId(header.author.0.to_bytes()), + peer_id: PeerId(network_key.public().0.to_bytes()), affinity: anemo::types::PeerAffinity::High, address: vec![address], }; diff --git a/primary/src/tests/header_waiter_tests.rs b/primary/src/tests/header_waiter_tests.rs index 0eb61bae5..16694646f 100644 --- a/primary/src/tests/header_waiter_tests.rs +++ b/primary/src/tests/header_waiter_tests.rs @@ -39,7 +39,7 @@ async fn successfully_synchronize_batches() { let network = anemo::Network::bind(own_address) .server_name("narwhal") - .private_key(primary.keypair().copy().private().0.to_bytes()) + .private_key(primary.network_keypair().copy().private().0.to_bytes()) .start(anemo::Router::new()) .unwrap(); diff --git a/primary/src/tests/helper_tests.rs b/primary/src/tests/helper_tests.rs index 367b9a7e4..392122a0d 100644 --- a/primary/src/tests/helper_tests.rs +++ b/primary/src/tests/helper_tests.rs @@ -42,7 +42,7 @@ async fn test_process_certificates_stream_mode() { .unwrap(); let network = anemo::Network::bind(own_address) .server_name("narwhal") - .private_key(author.keypair().copy().private().0.to_bytes()) + .private_key(author.network_keypair().copy().private().0.to_bytes()) .start(anemo::Router::new()) .unwrap(); @@ -52,7 +52,7 @@ async fn test_process_certificates_stream_mode() { .primary_to_primary; let address = network::multiaddr_to_address(&address).unwrap(); let peer_info = PeerInfo { - peer_id: PeerId(requestor_name.0.to_bytes()), + peer_id: PeerId(requestor.network_public_key().0.to_bytes()), affinity: anemo::types::PeerAffinity::High, address: vec![address], }; @@ -92,7 +92,7 @@ async fn test_process_certificates_stream_mode() { .primary(&requestor_name) .unwrap() .primary_to_primary; - let requestor_key = requestor.keypair().copy(); + let requestor_key = requestor.network_keypair().copy(); let (mut handler, _network) = PrimaryToPrimaryMockServer::spawn(requestor_key, address); // Wait for connectivity @@ -158,7 +158,7 @@ async fn test_process_certificates_batch_mode() { .unwrap(); let network = anemo::Network::bind(own_address) .server_name("narwhal") - .private_key(author.keypair().copy().private().0.to_bytes()) + .private_key(author.network_keypair().copy().private().0.to_bytes()) .start(anemo::Router::new()) .unwrap(); @@ -168,7 +168,7 @@ async fn test_process_certificates_batch_mode() { .primary_to_primary; let address = network::multiaddr_to_address(&address).unwrap(); let peer_info = PeerInfo { - peer_id: PeerId(requestor_name.0.to_bytes()), + peer_id: PeerId(requestor.network_public_key().0.to_bytes()), affinity: anemo::types::PeerAffinity::High, address: vec![address], }; @@ -217,7 +217,7 @@ async fn test_process_certificates_batch_mode() { .primary(&requestor_name) .unwrap() .primary_to_primary; - let requestor_key = requestor.keypair().copy(); + let requestor_key = requestor.network_keypair().copy(); let (mut handler, _network) = PrimaryToPrimaryMockServer::spawn(requestor_key, address); // Wait for connectivity @@ -295,7 +295,7 @@ async fn test_process_payload_availability_success() { .unwrap(); let network = anemo::Network::bind(own_address) .server_name("narwhal") - .private_key(author.keypair().copy().private().0.to_bytes()) + .private_key(author.network_keypair().copy().private().0.to_bytes()) .start(anemo::Router::new()) .unwrap(); @@ -305,7 +305,7 @@ async fn test_process_payload_availability_success() { .primary_to_primary; let address = network::multiaddr_to_address(&address).unwrap(); let peer_info = PeerInfo { - peer_id: PeerId(requestor_name.0.to_bytes()), + peer_id: PeerId(requestor.network_public_key().0.to_bytes()), affinity: anemo::types::PeerAffinity::High, address: vec![address], }; @@ -358,7 +358,7 @@ async fn test_process_payload_availability_success() { .primary(&requestor_name) .unwrap() .primary_to_primary; - let requestor_key = requestor.keypair().copy(); + let requestor_key = requestor.network_keypair().copy(); let (mut handler, _network) = PrimaryToPrimaryMockServer::spawn(requestor_key, address); // Wait for connectivity @@ -455,7 +455,7 @@ async fn test_process_payload_availability_when_failures() { .unwrap(); let network = anemo::Network::bind(own_address) .server_name("narwhal") - .private_key(author.keypair().copy().private().0.to_bytes()) + .private_key(author.network_keypair().copy().private().0.to_bytes()) .start(anemo::Router::new()) .unwrap(); @@ -465,7 +465,7 @@ async fn test_process_payload_availability_when_failures() { .primary_to_primary; let address = network::multiaddr_to_address(&address).unwrap(); let peer_info = PeerInfo { - peer_id: PeerId(requestor_name.0.to_bytes()), + peer_id: PeerId(requestor.network_public_key().0.to_bytes()), affinity: anemo::types::PeerAffinity::High, address: vec![address], }; @@ -524,7 +524,7 @@ async fn test_process_payload_availability_when_failures() { .primary(&requestor_name) .unwrap() .primary_to_primary; - let requestor_key = requestor.keypair().copy(); + let requestor_key = requestor.network_keypair().copy(); let (mut handler, _network) = PrimaryToPrimaryMockServer::spawn(requestor_key, address); // Wait for connectivity diff --git a/primary/src/tests/proposer_tests.rs b/primary/src/tests/proposer_tests.rs index 495e2e7d4..b1aece355 100644 --- a/primary/src/tests/proposer_tests.rs +++ b/primary/src/tests/proposer_tests.rs @@ -80,7 +80,7 @@ async fn propose_payload() { // Send enough digests for the header payload. let mut name_bytes = [0u8; 32]; - name_bytes.copy_from_slice(name.as_ref()); + name_bytes.copy_from_slice(&name.as_ref()[..32]); let digest = BatchDigest(name_bytes); let worker_id = 0; diff --git a/primary/tests/epoch_change.rs b/primary/tests/epoch_change.rs index 35c72e86b..e53bafe45 100644 --- a/primary/tests/epoch_change.rs +++ b/primary/tests/epoch_change.rs @@ -49,7 +49,8 @@ async fn test_simple_epoch_change() { Primary::spawn( name, - signer, + signer.copy(), + authority.network_keypair().copy(), Arc::new(ArcSwap::from_pointee(committee_0.clone())), worker_cache_0.clone(), parameters.clone(), @@ -120,6 +121,7 @@ async fn test_simple_epoch_change() { } } +#[allow(clippy::mutable_key_type)] #[tokio::test] async fn test_partial_committee_change() { let parameters = Parameters { @@ -154,7 +156,8 @@ async fn test_partial_committee_change() { Primary::spawn( name, - signer, + signer.copy(), + authority.network_keypair().copy(), Arc::new(ArcSwap::from_pointee(committee_0.clone())), worker_cache_0.clone(), parameters.clone(), @@ -213,7 +216,8 @@ async fn test_partial_committee_change() { Primary::spawn( name, - signer, + signer.copy(), + authority.network_keypair().copy(), Arc::new(ArcSwap::from_pointee(committee_1.clone())), worker_cache_1.clone(), parameters.clone(), @@ -299,7 +303,8 @@ async fn test_restart_with_new_committee_change() { let primary_handles = Primary::spawn( name, - signer, + signer.copy(), + authority.network_keypair().copy(), Arc::new(ArcSwap::new(Arc::new(committee_0.clone()))), worker_cache_0.clone(), parameters.clone(), @@ -382,7 +387,8 @@ async fn test_restart_with_new_committee_change() { let primary_handles = Primary::spawn( name, - signer, + signer.copy(), + authority.network_keypair().copy(), Arc::new(ArcSwap::new(Arc::new(new_committee.clone()))), Arc::new(ArcSwap::new(Arc::new(new_worker_cache.clone()))), parameters.clone(), @@ -471,7 +477,8 @@ async fn test_simple_committee_update() { Primary::spawn( name, - signer, + signer.copy(), + authority.network_keypair().copy(), Arc::new(ArcSwap::from_pointee(committee_0.clone())), worker_cache_0.clone(), parameters.clone(), diff --git a/primary/tests/integration_tests_proposer_api.rs b/primary/tests/integration_tests_proposer_api.rs index caa84774d..1f67e96cb 100644 --- a/primary/tests/integration_tests_proposer_api.rs +++ b/primary/tests/integration_tests_proposer_api.rs @@ -36,6 +36,7 @@ async fn test_rounds_errors() { let author = fixture.authorities().last().unwrap(); let keypair = author.keypair().copy(); + let network_keypair = author.network_keypair().copy(); let name = keypair.public().clone(); struct TestCase { @@ -96,7 +97,8 @@ async fn test_rounds_errors() { Primary::spawn( name.clone(), - keypair, + keypair.copy(), + network_keypair, Arc::new(ArcSwap::from_pointee(committee.clone())), worker_cache, parameters.clone(), @@ -180,7 +182,8 @@ async fn test_rounds_return_successful_response() { Primary::spawn( name.clone(), - keypair, + keypair.copy(), + author.network_keypair().copy(), Arc::new(ArcSwap::from_pointee(committee.clone())), worker_cache, parameters.clone(), @@ -332,7 +335,8 @@ async fn test_node_read_causal_signed_certificates() { // Spawn Primary 1 that we will be interacting with. Primary::spawn( name_1.clone(), - keypair_1, + keypair_1.copy(), + authority_1.network_keypair().copy(), Arc::new(ArcSwap::from_pointee(committee.clone())), worker_cache.clone(), primary_1_parameters.clone(), @@ -371,7 +375,8 @@ async fn test_node_read_causal_signed_certificates() { // Spawn Primary 2 Primary::spawn( name_2.clone(), - keypair_2, + keypair_2.copy(), + authority_2.network_keypair().copy(), Arc::new(ArcSwap::from_pointee(committee.clone())), worker_cache.clone(), primary_2_parameters.clone(), diff --git a/primary/tests/integration_tests_validator_api.rs b/primary/tests/integration_tests_validator_api.rs index 0453d92e2..99f50bd4c 100644 --- a/primary/tests/integration_tests_validator_api.rs +++ b/primary/tests/integration_tests_validator_api.rs @@ -115,7 +115,8 @@ async fn test_get_collections() { Primary::spawn( name.clone(), - signer, + signer.copy(), + author.network_keypair().copy(), Arc::new(ArcSwap::from_pointee(committee.clone())), worker_cache.clone(), parameters.clone(), @@ -311,7 +312,8 @@ async fn test_remove_collections() { Primary::spawn( name.clone(), - signer, + signer.copy(), + author.network_keypair().copy(), Arc::new(ArcSwap::from_pointee(committee.clone())), worker_cache.clone(), parameters.clone(), @@ -528,7 +530,8 @@ async fn test_read_causal_signed_certificates() { // Spawn Primary 1 that we will be interacting with. Primary::spawn( name_1.clone(), - keypair_1, + keypair_1.copy(), + authority_1.network_keypair().copy(), Arc::new(ArcSwap::from_pointee(committee.clone())), worker_cache.clone(), primary_1_parameters.clone(), @@ -567,7 +570,8 @@ async fn test_read_causal_signed_certificates() { // Spawn Primary 2 Primary::spawn( name_2.clone(), - keypair_2, + keypair_2.copy(), + authority_2.network_keypair().copy(), Arc::new(ArcSwap::from_pointee(committee.clone())), worker_cache.clone(), primary_2_parameters.clone(), @@ -657,6 +661,7 @@ async fn test_read_causal_unsigned_certificates() { ..Parameters::default() }; let keypair_2 = authority_2.keypair().copy(); + let network_keypair_2 = authority_2.network_keypair().copy(); let name_2 = authority_2.public_key(); // Make the data store. @@ -736,7 +741,8 @@ async fn test_read_causal_unsigned_certificates() { // Spawn Primary 1 that we will be interacting with. Primary::spawn( name_1.clone(), - keypair_1, + keypair_1.copy(), + authority_1.network_keypair().copy(), Arc::new(ArcSwap::from_pointee(committee.clone())), worker_cache.clone(), primary_1_parameters.clone(), @@ -768,7 +774,8 @@ async fn test_read_causal_unsigned_certificates() { // Spawn Primary 2 Primary::spawn( name_2.clone(), - keypair_2, + keypair_2.copy(), + network_keypair_2, Arc::new(ArcSwap::from_pointee(committee.clone())), worker_cache.clone(), primary_2_parameters.clone(), @@ -929,6 +936,7 @@ async fn test_get_collections_with_missing_certificates() { Primary::spawn( name_1.clone(), authority_1.keypair().copy(), + authority_1.network_keypair().copy(), Arc::new(ArcSwap::from_pointee(committee.clone())), worker_cache.clone(), parameters.clone(), @@ -982,6 +990,7 @@ async fn test_get_collections_with_missing_certificates() { Primary::spawn( name_2.clone(), authority_2.keypair().copy(), + authority_2.network_keypair().copy(), Arc::new(ArcSwap::from_pointee(committee.clone())), worker_cache.clone(), parameters.clone(), diff --git a/test_utils/Cargo.toml b/test_utils/Cargo.toml index 945cf02f0..fb438b562 100644 --- a/test_utils/Cargo.toml +++ b/test_utils/Cargo.toml @@ -26,6 +26,7 @@ tokio = { version = "1.20.1", features = ["sync", "rt", "macros"] } tokio-util = { version = "0.7.3", features = ["codec"] } tonic = "0.7.2" tracing = "0.1.36" +sha3 = "0.10.4" config = { path = "../config" } fastcrypto = "0.1.2" diff --git a/test_utils/src/cluster.rs b/test_utils/src/cluster.rs index 01dd5582e..7063b90c9 100644 --- a/test_utils/src/cluster.rs +++ b/test_utils/src/cluster.rs @@ -3,7 +3,7 @@ use crate::{temp_dir, CommitteeFixture}; use arc_swap::ArcSwap; use config::{Parameters, SharedCommittee, SharedWorkerCache, WorkerId}; -use crypto::{KeyPair, PublicKey}; +use crypto::{KeyPair, NetworkKeyPair, PublicKey}; use executor::{SerializedTransaction, SubscriberResult}; use fastcrypto::traits::KeyPair as _; use itertools::Itertools; @@ -64,6 +64,7 @@ impl Cluster { let authority = AuthorityDetails::new( id, authority_fixture.keypair().copy(), + authority_fixture.network_keypair().copy(), authority_fixture.worker_keypairs(), params.clone(), shared_committee.clone(), @@ -269,6 +270,7 @@ impl Cluster { pub struct PrimaryNodeDetails { pub id: usize, pub key_pair: Arc, + pub network_key_pair: Arc, pub tx_transaction_confirmation: Sender<(SubscriberResult>, SerializedTransaction)>, registry: Registry, store_path: PathBuf, @@ -283,6 +285,7 @@ impl PrimaryNodeDetails { fn new( id: usize, key_pair: KeyPair, + network_key_pair: NetworkKeyPair, parameters: Parameters, committee: SharedCommittee, worker_cache: SharedWorkerCache, @@ -294,6 +297,7 @@ impl PrimaryNodeDetails { Self { id, key_pair: Arc::new(key_pair), + network_key_pair: Arc::new(network_key_pair), registry: Registry::new(), store_path: temp_dir(), tx_transaction_confirmation: tx, @@ -342,6 +346,7 @@ impl PrimaryNodeDetails { let primary_store: NodeStorage = NodeStorage::reopen(store_path.clone()); let mut primary_handlers = Node::spawn_primary( self.key_pair.copy(), + self.network_key_pair.copy(), self.committee.clone(), self.worker_cache.clone(), &primary_store, @@ -432,7 +437,7 @@ impl WorkerNodeDetails { } /// Starts the node. When preserve_store is true then the last used - async fn start(&mut self, keypair: KeyPair, preserve_store: bool) { + async fn start(&mut self, keypair: NetworkKeyPair, preserve_store: bool) { if self.is_running() { panic!( "Worker with id {} is already running, can't start again", @@ -496,7 +501,7 @@ pub struct AuthorityDetails { struct AuthorityDetailsInternal { primary: PrimaryNodeDetails, - worker_keypairs: Vec, + worker_keypairs: Vec, workers: HashMap, } @@ -504,7 +509,8 @@ impl AuthorityDetails { pub fn new( id: usize, key_pair: KeyPair, - worker_keypairs: Vec, + network_key_pair: NetworkKeyPair, + worker_keypairs: Vec, parameters: Parameters, committee: SharedCommittee, worker_cache: SharedWorkerCache, @@ -515,6 +521,7 @@ impl AuthorityDetails { let primary = PrimaryNodeDetails::new( id, key_pair, + network_key_pair, parameters.clone(), committee.clone(), worker_cache.clone(), @@ -591,7 +598,7 @@ impl AuthorityDetails { .worker_keypairs .iter() .map(|kp| kp.copy()) - .collect::>(); + .collect::>(); for (id, worker) in internal.workers.iter_mut() { let keypair = worker_keypairs.get(*id as usize).unwrap().copy(); diff --git a/test_utils/src/lib.rs b/test_utils/src/lib.rs index 1962ce6c5..018eb3164 100644 --- a/test_utils/src/lib.rs +++ b/test_utils/src/lib.rs @@ -6,7 +6,7 @@ use config::{ utils::get_available_port, Authority, Committee, Epoch, PrimaryAddresses, SharedWorkerCache, WorkerCache, WorkerId, WorkerIndex, WorkerInfo, }; -use crypto::{KeyPair, PublicKey}; +use crypto::{KeyPair, NetworkKeyPair, NetworkPublicKey, PublicKey}; use fastcrypto::{ traits::{KeyPair as _, Signer as _}, Digest, Hash as _, @@ -177,7 +177,10 @@ pub struct PrimaryToPrimaryMockServer { } impl PrimaryToPrimaryMockServer { - pub fn spawn(keypair: KeyPair, address: Multiaddr) -> (Receiver, Network) { + pub fn spawn( + network_keypair: NetworkKeyPair, + address: Multiaddr, + ) -> (Receiver, Network) { let addr = network::multiaddr_to_address(&address).unwrap(); let (sender, receiver) = channel(1); let service = PrimaryToPrimaryServer::new(Self { sender }); @@ -185,7 +188,7 @@ impl PrimaryToPrimaryMockServer { let routes = anemo::Router::new().add_rpc_service(service); let network = anemo::Network::bind(addr) .server_name("narwhal") - .private_key(keypair.private().0.to_bytes()) + .private_key(network_keypair.private().0.to_bytes()) .start(routes) .unwrap(); info!("starting network on: {}", network.local_addr()); @@ -794,6 +797,7 @@ impl CommitteeFixture { pub struct AuthorityFixture { keypair: KeyPair, + network_keypair: NetworkKeyPair, stake: u32, addresses: PrimaryAddresses, workers: BTreeMap, @@ -804,11 +808,15 @@ impl AuthorityFixture { &self.keypair } + pub fn network_keypair(&self) -> &NetworkKeyPair { + &self.network_keypair + } + pub fn worker(&self, id: WorkerId) -> &WorkerFixture { self.workers.get(&id).unwrap() } - pub fn worker_keypairs(&self) -> Vec { + pub fn worker_keypairs(&self) -> Vec { self.workers .values() .map(|worker| worker.keypair.copy()) @@ -819,10 +827,15 @@ impl AuthorityFixture { self.keypair.public().clone() } + pub fn network_public_key(&self) -> NetworkPublicKey { + self.network_keypair.public().clone() + } + pub fn authority(&self) -> Authority { Authority { stake: self.stake, primary: self.addresses.clone(), + network_key: self.network_keypair.public().clone(), } } @@ -865,6 +878,7 @@ impl AuthorityFixture { P: FnMut() -> u16, { let keypair = KeyPair::generate(&mut rng); + let network_keypair = NetworkKeyPair::generate(&mut rng); let primary_addresses = PrimaryAddresses { primary_to_primary: format!("/ip4/127.0.0.1/tcp/{}/http", get_port()) .parse() @@ -884,6 +898,7 @@ impl AuthorityFixture { Self { keypair, + network_keypair, stake: 1, addresses: primary_addresses, workers, @@ -892,14 +907,14 @@ impl AuthorityFixture { } pub struct WorkerFixture { - keypair: KeyPair, + keypair: NetworkKeyPair, #[allow(dead_code)] id: WorkerId, info: WorkerInfo, } impl WorkerFixture { - pub fn keypair(&self) -> &KeyPair { + pub fn keypair(&self) -> &NetworkKeyPair { &self.keypair } @@ -908,8 +923,9 @@ impl WorkerFixture { R: ::rand::RngCore + ::rand::CryptoRng, P: FnMut() -> u16, { - let keypair = KeyPair::generate(&mut rng); - let name = keypair.public().clone(); + let keypair = NetworkKeyPair::generate(&mut rng); + let network_keypair = NetworkKeyPair::generate(&mut rng); + let worker_name = network_keypair.public().clone(); let primary_to_worker = format!("/ip4/127.0.0.1/tcp/{}/http", get_port()) .parse() .unwrap(); @@ -924,7 +940,7 @@ impl WorkerFixture { keypair, id, info: WorkerInfo { - name, + name: worker_name, primary_to_worker, worker_to_worker, transactions, diff --git a/types/src/consensus.rs b/types/src/consensus.rs index 607a0956f..af8ddeb55 100644 --- a/types/src/consensus.rs +++ b/types/src/consensus.rs @@ -1,5 +1,7 @@ // Copyright (c) 2022, Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 +#![allow(clippy::mutable_key_type)] + use crate::{CertificateDigest, Round}; use crypto::PublicKey; use std::{collections::HashMap, ops::RangeInclusive}; diff --git a/types/src/primary.rs b/types/src/primary.rs index 5b44c87c1..fc14f310a 100644 --- a/types/src/primary.rs +++ b/types/src/primary.rs @@ -466,9 +466,12 @@ impl Certificate { DagError::CertificateRequiresQuorum ); - let aggregated_signature = + let aggregated_signature = if sigs.is_empty() { + AggregateSignature::default() + } else { AggregateSignature::aggregate(sigs.into_iter().map(|(_, sig)| sig).collect()) - .map_err(DagError::InvalidSignature)?; + .map_err(DagError::InvalidSignature)? + }; Ok(Certificate { header, @@ -673,6 +676,7 @@ pub enum ReconfigureNotification { } /// The messages sent by the primary to its workers. +#[allow(clippy::large_enum_variant)] #[derive(Debug, Serialize, Deserialize)] pub enum PrimaryWorkerMessage { /// The primary indicates that the worker need to sync the target missing batches. diff --git a/types/src/worker.rs b/types/src/worker.rs index 78c7c4c90..e46cb91b0 100644 --- a/types/src/worker.rs +++ b/types/src/worker.rs @@ -9,6 +9,7 @@ use thiserror::Error; use crate::{Batch, BatchDigest}; /// The message exchanged between workers. +#[allow(clippy::large_enum_variant)] #[derive(Debug, Serialize, Deserialize)] pub enum WorkerMessage { /// Used by workers to send a new batch or to reply to a batch request. diff --git a/worker/src/worker.rs b/worker/src/worker.rs index e42468a61..0bfd54e41 100644 --- a/worker/src/worker.rs +++ b/worker/src/worker.rs @@ -9,7 +9,7 @@ use crate::{ use async_trait::async_trait; use bytes::Bytes; use config::{Parameters, SharedCommittee, SharedWorkerCache, WorkerId}; -use crypto::{KeyPair, PublicKey}; +use crypto::{NetworkKeyPair, PublicKey}; use futures::{Stream, StreamExt}; use multiaddr::{Multiaddr, Protocol}; use network::{metrics::WorkerNetworkMetrics, WorkerNetwork}; @@ -47,7 +47,7 @@ pub struct Worker { // The private-public key pair of this worker. // TODO: utilize keypair in network communication #[allow(dead_code)] - keypair: KeyPair, + keypair: NetworkKeyPair, /// The id of this worker used for index-based lookup by other NW nodes. id: WorkerId, /// The committee information. @@ -65,7 +65,7 @@ const INADDR_ANY: Ipv4Addr = Ipv4Addr::new(0, 0, 0, 0); impl Worker { pub fn spawn( primary_name: PublicKey, - keypair: KeyPair, + keypair: NetworkKeyPair, id: WorkerId, committee: SharedCommittee, worker_cache: SharedWorkerCache,