Multy-party threshold ECDSA Substrate node

Overview

Webb DKG

๐Ÿ•ธ๏ธ The Webb DKG ๐Ÿง‘โ€โœˆ๏ธ
โš ๏ธ Beta Software โš ๏ธ


Running the DKG

Currently the easiest way to run the DKG is to use a 3-node local testnet using dkg-node. We will call those nodes Alice, Bob and Charlie. Each node will use the built-in development account with the same name, i.e. node Alice will use the Alice development account and so on. Each of the three accounts has been configured as an initial authority at genesis. So, we are using three validators for our testnet.

Alice is our bootnode and is started like so:

$ RUST_LOG=dkg=trace ./target/debug/dkg-node --tmp --alice

Bob is started like so:

RUST_LOG=dkg=trace ./target/debug/dkg-node --tmp --bob

Charlie is started like so:

RUST_LOG=dkg=trace ./target/debug/dkg-node --tmp --charlie

Note that the examples above use an ephemeral DB due to the --tmp CLI option. If you want a persistent DB, use --/tmp/[node-name] instead. Replace node-name with the actual node name (e.g. alice) in order to assure separate dirctories for the DB.

Build & Run

Follow these steps to prepare a local Substrate development environment ๐Ÿ› ๏ธ

Setup of Machine

If necessary, refer to the setup instructions at the Substrate Developer Hub.

Build

Once the development environment is set up, build the DKG. This command will build the Wasm Runtime and native code:

cargo build --release

NOTE: You must use the release builds! The optimizations here are required as in debug mode, it is expected that nodes are not able to run fast enough to produce blocks.

Relay Chain

NOTE: In the following two sections, we document how to manually start a few relay chain nodes, start a parachain node (collator), and register the parachain with the relay chain.

We also have the polkadot-launch CLI tool that automate the following steps and help you easily launch relay chains and parachains. However it is still good to go through the following procedures once to understand the mechanism for running and registering a parachain.

To operate a parathread or parachain, you must connect to a relay chain. Typically you would test on a local Rococo development network, then move to the testnet, and finally launch on the mainnet. Keep in mind you need to configure the specific relay chain you will connect to in your collator chain_spec.rs. In the following examples, we will use rococo-local as the relay network.

Build Relay Chain

Clone and build Polkadot (be aware of the version tag we used):

# Get a fresh clone, or `cd` to where you have polkadot already:
git clone -b v0.9.7 --depth 1 https://github.com/paritytech/polkadot.git
cd polkadot
cargo build --release

Generate the Relay Chain Chainspec

First, we create the chain specification file (chainspec). Note the chainspec file must be generated on a single node and then shared among all nodes!

๐Ÿ‘‰ Learn more about chain specification here.

./target/release/polkadot build-spec \
--chain rococo-local \
--raw \
--disable-default-bootnode \
> rococo_local.json

Start Relay Chain

We need n + 1 full validator nodes running on a relay chain to accept n parachain / parathread connections. Here we will start two relay chain nodes so we can have one parachain node connecting in later.

From the Polkadot working directory:

# Start Relay `Alice` node
./target/release/polkadot \
--chain ./rococo_local.json \
-d /tmp/relay/alice \
--validator \
--alice \
--port 50555

Open a new terminal, same directory:

# Start Relay `Bob` node
./target/release/polkadot \
--chain ./rococo_local.json \
-d /tmp/relay/bob \
--validator \
--bob \
--port 50556

Add more nodes as needed, with non-conflicting ports, DB directories, and validator keys (--charlie, --dave, etc.).

Reserve a ParaID

To connect to a relay chain, you must first _reserve a ParaId for your parathread that will become a parachain. To do this, you will need sufficient amount of currency on the network account to reserve the ID.

In this example, we will use Charlie development account where we have funds available. Once you submit this extrinsic successfully, you can start your collators.

The easiest way to reserve your ParaId is via Polkadot Apps UI under the Parachains -> Parathreads tab and use the + ParaID button.

Parachain

Select the Correct Relay Chain

To operate your parachain, you need to specify the correct relay chain you will connect to in your collator chain_spec.rs. Specifically you pass the command for the network you need in the Extensions of your ChainSpec::from_genesis() in the code.

Extensions {
	relay_chain: "rococo-local".into(), // You MUST set this to the correct network!
	para_id: id.into(),
},

You can choose from any pre-set runtime chainspec in the Polkadot repo, by referring to the cli/src/command.rs and node/service/src/chain_spec.rs files or generate your own and use that. See the Cumulus Workshop for how.

In the following examples, we will use the rococo-local relay network we setup in the last section.

Export the DKG Genesis and Runtime

We first generate the genesis state and genesis wasm needed for the parachain registration.

# Build the dkg node (from it's top level dir)
cd dkg-substrate
cargo build --release

# Folder to store resource files needed for parachain registration
mkdir -p resources

# Build the chainspec
./target/release/dkg-node build-spec \
--disable-default-bootnode > ./resources/template-local-plain.json

# Build the raw chainspec file
./target/release/dkg-node build-spec \
--chain=./resources/template-local-plain.json \
--raw --disable-default-bootnode > ./resources/template-local-raw.json

# Export genesis state to `./resources`, using 2000 as the ParaId
./target/release/dkg-node export-genesis-state --parachain-id 2000 > ./resources/para-2000-genesis

# Export the genesis wasm
./target/release/dkg-node export-genesis-wasm > ./resources/para-2000-wasm

NOTE: we have set the para_ID to be 2000 here. This must be unique for all parathreads/chains on the relay chain you register with. You must reserve this first on the relay chain for the testnet or mainnet.

Start a DKG Node (Collator)

From the dkg-substrate working directory:

# NOTE: this command assumes the chain spec is in a directory named `polkadot`
# that is at the same level of the template working directory. Change as needed.
#
# It also assumes a ParaId of 2000. Change as needed.
./target/release/dkg-node \
-d /tmp/parachain/alice \
--collator \
--alice \
--force-authoring \
--ws-port 9945 \
--parachain-id 2000 \
-- \
--execution wasm \
--chain ../polkadot/rococo_local.json

Parachain Registration

Now that you have two relay chain nodes, and a parachain node accompanied with a relay chain light client running, the next step is to register the parachain in the relay chain with the following steps (for detail, refer to the Substrate Cumulus Worship):

  • Goto Polkadot Apps UI, connecting to your relay chain.

  • Execute a sudo extrinsic on the relay chain by going to Developer -> sudo page.

  • Pick paraSudoWrapper -> sudoScheduleParaInitialize(id, genesis) as the extrinsic type, shown below.

    ![Polkadot Apps UI](docs/assets/ss01.png)
    
  • Set the id: ParaId to 2,000 (or whatever ParaId you used above), and set the parachain: Bool option to Yes.

  • For the genesisHead, drag the genesis state file exported above, para-2000-genesis, in.

  • For the validationCode, drag the genesis wasm file exported above, para-2000-wasm, in.

Note: When registering to the public Rococo testnet, ensure you set a unique paraId larger than 1,000. Values below 1,000 are reserved exclusively for system parachains.

Restart the DKG (Collator)

The DKG node may need to be restarted to get it functioning as expected. After a new epoch starts on the relay chain, your parachain will come online. Once this happens, you should see the collator start reporting parachain blocks:

Note the delay here! It may take some time for your relay chain to enter a new epoch.

Pallets

The DKG runtime is uses the following pallets which are central to how the protocol functions.

pallet-dkg-metadata

This pallet essentially tracks the information about the current and next authority sets, including the set Ids. It does this by implementing the OneSessionHandler trait which allows it to receieve both new and queued authority sets when the session changes.

pallet-parachain-staking

This is a custom staking pallet that handles collator selection, This pallet helps the protocol select new collators based on amount staked. It also allows for nominators, who back collators by staking their assets, both collators and nominators are rewarded after every session comes to an end. Reward for collators and their nominators is dependent on how many points accrued by the collator during the session, these points are gained by successfully authoring blocks.

This pallet implements the SessionManager trait and that way is able to provide the the selected collators as validators to the session pallet.

pallet-dkg-proposals

This pallet handles maintaining valid proposers and also voting on proposals. The valid set of proposers is equivalent to the current DKG authorities. This pallet gains access to the current DKG authorities by implementing the OnAuthoritySetChangedHandler trait, that way it is able to receive the updated DKG authorities from pallet-dkg-metadata.

This pallet maintains a queue for pending proposals which the DKG authorities vote on and if the vote threshold is met, the proposal is passed on to be handled by a type that implements the ProposalHandlerTrait.

In this current iteration the proposals are Ethereum transactions.

pallet-dkg-proposal-handler

This pallet implements the ProposalHandlerTrait accepts proposals and signs them using the DKG authority keys.

pallet-dkg-mmr

This pallet serves as a leaf provider for the pallet-mmr, generating leaf data that contains a merke root hash for a particular authority set.

It also provides a type that has an implementation for converting ECDSA keys to ethereum compatible keys.

Comments
  • Mac M1 cargo build issue: error: linking with `cc` failed: exit status: 1 (Mac m1)

    Mac M1 cargo build issue: error: linking with `cc` failed: exit status: 1 (Mac m1)

    Not able to build a project because of this issue: error: linking withcc` failed: exit status: 1 | = note: "cc" "-arch" "arm64" "/var/folders/5w/j2mkxftx2xz55c696xp23gzh0000gn/T/rustciwy51y/symbols.o" "/Users/elioprifti/dkg-substrate/target/debug/deps/dkg_standalone_node-3e72bef5f25657ad.10sw7xj1rkq1p2nk.rcgu.o" "/Users/elioprifti/dkg-substrate/target/debug/deps/dkg_standalone_node-3e72bef5f25657ad.10ut9rvejkcsmvr1.rcgu.o" "/Users/elioprifti/dkg-substrate/target/debug/deps/dkg_standalone_node-3e72bef5f25657ad.112iyrdupdm8w5vw.rcgu.o" "/Users/elioprifti/dkg-substrate/target/debug/deps/elioprifti/.rustup/toolchains/nightly-2022-05-15-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/librustc_std_workspace_alloc-d0e3d0b2f5dc30fb.rlib" "/Users/elioprifti/.rustup/toolchains/nightly-2022-05-15-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/libunwind-12083e42f9a7d1fc.rlib" "/Users/elioprifti/.rustup/toolchains/nightly-2022-05-15-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/libcfg_if-def158ba03cb504e.rlib" "/Users/elioprifti/.rustup/toolchains/nightly-2022-05-15-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/liblibc-e83dd9bd71bd52bd.rlib" "/Users/elioprifti/.rustup/toolchains/nightly-2022-05-15-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/liballoc-a149d8756e403a5c.rlib" "/Users/elioprifti/.rustup/toolchains/nightly-2022-05-15-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/librustc_std_workspace_core-95a7e52c78a3fba1.rlib" "/Users/elioprifti/.rustup/toolchains/nightly-2022-05-15-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/libcore-dd6de681850a671c.rlib" "/Users/elioprifti/.rustup/toolchains/nightly-2022-05-15-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/libcompiler_builtins-ec608688b97371b8.rlib" "-lgmp" "-framework" "Security" "-framework" "Security" "-lc++" "-framework" "SystemConfiguration" "-framework" "Security" "-framework" "CoreFoundation" "-liconv" "-lSystem" "-lresolv" "-lc" "-lm" "-liconv" "-L" "/Users/elioprifti/.rustup/toolchains/nightly-2022-05-15-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib" "-o" "/Users/elioprifti/dkg-substrate/target/debug/deps/dkg_standalone_node-3e72bef5f25657ad" "-Wl,-dead_strip" "-nodefaultlibs" = note: ld: library not found for -lgmp clang: error: linker command failed with exit code 1 (use -v to see invocation)

    error: could not compile dkg-standalone-node due to previous error warning: build failed, waiting for other jobs to finish... elioprifti@pc-193-62 dkg-substrate % `

    I can build other projects but not this one. Any idea?

    Already reported this but not solution so far: https://substrate.stackexchange.com/questions/6058/error-linking-with-cc-failed-exit-status-1-mac-m1?noredirect=1#comment5956_6058

    opened by herou 11
  • Remove all ensure_root and replace with EnsureOrigin<> #2

    Remove all ensure_root and replace with EnsureOrigin<> #2

    Summary of changes Changes introduced in this pull request:

    • Replace ensure_root with ensure_origin

    Reference issue to close (if applicable)

    https://github.com/webb-tools/dkg-substrate/issues/441

    opened by herou 6
  • [BUG] Standalone network stops keygen after session 73

    [BUG] Standalone network stops keygen after session 73

    Describe the bug

    The current standalone network which contains three nodes seems to have stop generating a dkg public key after session 73 or block 43,800. The three nodes are still finalizing blocks and progressing the chain but keygen has stalled at session 73. We are currently running t=1 (signing threshold) n=2 (keygen threshold) if I am not mistaken, and it seems standalone-node-1 has been jailed for some misbehaviour and there are only 2 authority nodes participating.

    The logs indicate a keygen misbehaviour by KW63ywCaFXGM5GjrVdWKsMPCqmQGRfPCyT89ZtbryNRuqqQpD which I believe to be standalone-node-1. There is still no details about why this node was issued a misbehaviour report.

    To Reproduce Steps to reproduce the observe behaviour:

    1. Go to polkadot UI > Developer > ChainState > DKG > dkgPublickey()

    You will notice:

    dkg.dkgPublicKey: (u64,Bytes)
    [
      73
      0x03f005859977b45e09c55c6a4ac09af580e5f208c9fbd70fcc89652b555f2e4604
    ]
    

    Log output

    From standalone-node-1

    Sep 27 20:02:42 eggnet-arana-1 dkg-standalone-node[2643155]: 2022-09-27 20:02:42.946 DEBUG tokio-runtime-worker dkg_gadget::worker: Going to handle Finality notification
    Sep 27 20:02:42 eggnet-arana-1 dkg-standalone-node[2643155]: 2022-09-27 20:02:42.946 DEBUG tokio-runtime-worker dkg_gadget::worker: ๐Ÿ•ธ๏ธ  Processing block notification for block 89544
    Sep 27 20:02:42 eggnet-arana-1 dkg-standalone-node[2643155]: 2022-09-27 20:02:42.946 DEBUG tokio-runtime-worker dkg_gadget::worker: ๐Ÿ•ธ๏ธ  Latest header is now: 89544
    Sep 27 20:02:42 eggnet-arana-1 dkg-standalone-node[2643155]: 2022-09-27 20:02:42.947 DEBUG tokio-runtime-worker dkg_gadget::worker: ๐Ÿ•ธ๏ธ  QUEUED KEYGEN IN PROGRESS: false
    Sep 27 20:02:42 eggnet-arana-1 dkg-standalone-node[2643155]: 2022-09-27 20:02:42.947 DEBUG tokio-runtime-worker dkg_gadget::worker: ๐Ÿ•ธ๏ธ  QUEUED DKG ID: 74
    Sep 27 20:02:42 eggnet-arana-1 dkg-standalone-node[2643155]: 2022-09-27 20:02:42.947 DEBUG tokio-runtime-worker dkg_gadget::worker: ๐Ÿ•ธ๏ธ  QUEUED VALIDATOR SET ID: 74
    Sep 27 20:02:42 eggnet-arana-1 dkg-standalone-node[2643155]: 2022-09-27 20:02:42.947 DEBUG tokio-runtime-worker dkg_gadget::worker: ๐Ÿ•ธ๏ธ  QUEUED DKG STATUS: None
    Sep 27 20:02:42 eggnet-arana-1 dkg-standalone-node[2643155]: 2022-09-27 20:02:42.947  INFO tokio-runtime-worker dkg_gadget::worker: ๐Ÿ•ธ๏ธ  NOT IN THE SET OF BEST AUTHORITIES: round 73
    

    From standalone-node-2

    Sep 27 20:01:37 eggnet-arana-2 dkg-standalone-node[125856]: 2022-09-27 20:01:37 Received error: KeygenTimeout { bad_actors: [2] }
    Sep 27 20:01:37 eggnet-arana-2 dkg-standalone-node[125856]: 2022-09-27 20:01:37 ๐Ÿ•ธ๏ธ  DKG Keygen misbehaviour by KW63ywCaFXGM5GjrVdWKsMPCqmQGRfPCyT89ZtbryNRuqqQpD
    Sep 27 20:01:37 eggnet-arana-2 dkg-standalone-node[125856]: 2022-09-27 20:01:37 ๐Ÿ•ธ๏ธ  IN THE SET OF BEST AUTHORITIES: round 73
    Sep 27 20:01:41 eggnet-arana-2 dkg-standalone-node[125856]: 2022-09-27 20:01:41 ๐Ÿ’ค Idle (3 peers), best: #89535 (0xe2f4โ€ฆa64b), finalized #89533 (0x4a0aโ€ฆ3e0e), โฌ‡ 3.1kiB/s โฌ† 2.9kiB/s
    Sep 27 20:01:42 eggnet-arana-2 dkg-standalone-node[125856]: 2022-09-27 20:01:42 โœจ Imported #89536 (0x447dโ€ฆ6009)
    Sep 27 20:01:42 eggnet-arana-2 dkg-standalone-node[125856]: 2022-09-27 20:01:42 Failed to get next signed proposal: Unable to get next proposal batch
    Sep 27 20:01:43 eggnet-arana-2 dkg-standalone-node[125856]: 2022-09-27 20:01:43 Received error: KeygenTimeout { bad_actors: [2] }
    Sep 27 20:01:43 eggnet-arana-2 dkg-standalone-node[125856]: 2022-09-27 20:01:43 ๐Ÿ•ธ๏ธ  DKG Keygen misbehaviour by KW63ywCaFXGM5GjrVdWKsMPCqmQGRfPCyT89ZtbryNRuqqQpD
    Sep 27 20:01:43 eggnet-arana-2 dkg-standalone-node[125856]: 2022-09-27 20:01:43 ๐Ÿ•ธ๏ธ  IN THE SET OF BEST AUTHORITIES: round 73
    

    Expected behaviour

    It should continue to progress through keygen every session, and in these network params that should be every 600 blocks.

    Environment

    Machine specs:

    • vCPU/s: 2 vCPUs
    • RAM: 8192 MB
    • Storage: 50 GB NVMe + 128GB of Block Storage
    • Bandwidth: 6.94 GB of 5000 GB

    Note: The standalone network uses the integration tests parameters which can be found here.

    Other information and links

    bug ๐Ÿชฒ 
    opened by dutterbutter 6
  • [SPEC] Persistent DKG node restarts

    [SPEC] Persistent DKG node restarts

    Overview

    We want the node to be able to continue to participate in DKG after restart. Currently generated keys are stored in memory. We want to store generated keys on disk and read them upon node startup. The file contents are updated during state transitions.

    Questions

    • Should we save current votes data or just discard it in case of the node restart?

    Checklist

    • When the node starts:
      • Check if there is a file with DKG data.
        1. If the file is missing
          • [ ] Try to start a new DKG process
        2. If the file is present
          • [ ] Re-create the DKG state from that file
    • When Keygen process completes:
      • Check if there is a file with DKG data.
        1. If the file is missing
          • [ ] Create a new file
        2. If the file is present
          • [ ] Delete old file (since we have generated new keys, we assume the old DKG epoch is over)
          • [ ] Create a new file
    • When OfflineStage process completes:
      • Check if there is a file with DKG data.
        1. If the file is missing
          • [ ] Report the error
          • [ ] Try to start a new DKG process
        2. If the file is present and does not contain OfflineStage
          • [ ] Update file with OfflineStage info
        3. If the file is present and contains OfflineStage
          • [ ] Update file with OfflineStage overriding the old OfflineStage data (we assume the signers set changed, so we discard the old OfflineStage data)
    • If at any read attempt the file is corrupted:
      • [ ] Report the error
      • [ ] Delete the file
      • [ ] Try start a new DKG process
    opened by drewstone 6
  • Not able to start dkg as bootnode

    Not able to start dkg as bootnode

    Describe the bug

    I was able to successfully setup my local env.

    To Reproduce Steps to reproduce the behavior:

    1. Open terminal and execute: RUST_LOG=dkg=trace ./target/release/dkg-standalone-node --tmp --alice or RUST_LOG=dkg=trace ./target/release/dkg-standalone-node --tmp --bob or RUST_LOG=dkg=trace ./target/release/dkg-standalone-node --tmp --charlie

    Log output

    Log Output
    2022-11-24 20:29:08.910  INFO main sc_cli::runner: DKG Substrate Node    
    2022-11-24 20:29:08.910  INFO main sc_cli::runner: โœŒ๏ธ  version 3.0.0-45f135e12d2    
    2022-11-24 20:29:08.910  INFO main sc_cli::runner: โค๏ธ  by Webb tools, 2017-2022    
    2022-11-24 20:29:08.910  INFO main sc_cli::runner: ๐Ÿ“‹ Chain specification: Local Testnet    
    2022-11-24 20:29:08.910  INFO main sc_cli::runner: ๐Ÿท  Node name: Alice    
    2022-11-24 20:29:08.910  INFO main sc_cli::runner: ๐Ÿ‘ค Role: AUTHORITY    
    2022-11-24 20:29:08.910  INFO main sc_cli::runner: ๐Ÿ’พ Database: RocksDb at /var/folders/5w/j2mkxftx2xz55c696xp23gzh0000gn/T/substrateTFlrhP/chains/local_testnet/db/full    
    2022-11-24 20:29:08.910  INFO main sc_cli::runner: โ›“  Native runtime: dkg-standalone-node-19 (dkg-standalone-node-0.tx1.au1)    
    
    ====================
    
    Version: 3.0.0-45f135e12d2
    
     0: backtrace::backtrace::trace
     1: backtrace::capture::Backtrace::new
     2: sp_panic_handler::set::{{closure}}
     3: std::panicking::rust_panic_with_hook
               at /rustc/70b3681bf621bc0de91ffab711b2350068b4c466/library/std/src/panicking.rs:702:17
     4: std::panicking::begin_panic_handler::{{closure}}
               at /rustc/70b3681bf621bc0de91ffab711b2350068b4c466/library/std/src/panicking.rs:586:13
     5: std::sys_common::backtrace::__rust_end_short_backtrace
               at /rustc/70b3681bf621bc0de91ffab711b2350068b4c466/library/std/src/sys_common/backtrace.rs:138:18
     6: rust_begin_unwind
               at /rustc/70b3681bf621bc0de91ffab711b2350068b4c466/library/std/src/panicking.rs:584:5
     7: core::panicking::panic_fmt
               at /rustc/70b3681bf621bc0de91ffab711b2350068b4c466/library/core/src/panicking.rs:142:14
     8: <pallet_dkg_metadata::pallet::GenesisConfig<T> as frame_support::traits::hooks::GenesisBuild<T>>::build
     9: std::thread::local::LocalKey<T>::with
    10: sp_state_machine::basic::BasicExternalities::execute_with_storage
    11: <dkg_standalone_runtime::GenesisConfig as sp_runtime::BuildStorage>::assimilate_storage
    12: sp_runtime::BuildStorage::build_storage
    13: <sc_chain_spec::chain_spec::ChainSpec<G,E> as sp_runtime::BuildStorage>::build_storage
    14: sc_service::client::client::Client<B,E,Block,RA>::new
    15: sc_service::builder::new_full_parts
    16: dkg_standalone_node::service::new_partial
    17: dkg_standalone_node::service::new_full
    18: std::thread::local::LocalKey<T>::with
    19: tokio::park::thread::CachedParkThread::block_on
    20: tokio::runtime::scheduler::multi_thread::MultiThread::block_on
    21: tokio::runtime::Runtime::block_on
    22: sc_cli::runner::Runner<C>::run_node_until_exit
    23: dkg_standalone_node::command::run
    24: std::sys_common::backtrace::__rust_begin_short_backtrace
    25: std::rt::lang_start::{{closure}}
    26: core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once
               at /rustc/70b3681bf621bc0de91ffab711b2350068b4c466/library/core/src/ops/function.rs:280:13
        std::panicking::try::do_call
               at /rustc/70b3681bf621bc0de91ffab711b2350068b4c466/library/std/src/panicking.rs:492:40
        std::panicking::try
               at /rustc/70b3681bf621bc0de91ffab711b2350068b4c466/library/std/src/panicking.rs:456:19
        std::panic::catch_unwind
               at /rustc/70b3681bf621bc0de91ffab711b2350068b4c466/library/std/src/panic.rs:137:14
        std::rt::lang_start_internal::{{closure}}
               at /rustc/70b3681bf621bc0de91ffab711b2350068b4c466/library/std/src/rt.rs:128:48
        std::panicking::try::do_call
               at /rustc/70b3681bf621bc0de91ffab711b2350068b4c466/library/std/src/panicking.rs:492:40
        std::panicking::try
               at /rustc/70b3681bf621bc0de91ffab711b2350068b4c466/library/std/src/panicking.rs:456:19
        std::panic::catch_unwind
               at /rustc/70b3681bf621bc0de91ffab711b2350068b4c466/library/std/src/panic.rs:137:14
        std::rt::lang_start_internal
               at /rustc/70b3681bf621bc0de91ffab711b2350068b4c466/library/std/src/rt.rs:128:20
    27: _main
    
    
    Thread 'main' panicked at 'Not enough authority ids specified', /Users/elioprifti/dkg-substrate/pallets/dkg-metadata/src/lib.rs:608
    
    This is a bug. Please report it at:
    
          support.anonymous.an
    
    elioprifti@pc-193-62 dkg-substrate % 
    ...
    

    Expected behaviour

    Screenshots

    Environment (please complete the following information):

    • OS: MacOS
    • Rust version(e.g. rustc 1.65.0 (897e37553 2022-11-02))
    • Master

    Other information and links

    opened by herou 5
  • [BUG]  Authorities reputation map key don't encode the authority id or the authority account 32  correclty

    [BUG] Authorities reputation map key don't encode the authority id or the authority account 32 correclty

    Describe the bug

    To Reproduce Steps to reproduce the behavior:

    1. Run the archive standalone node $ ./scripts/run-archive-local-net.sh
    2. Go to Substrate portal
    3. Query the authority's map
    4. Query the authority's reputation map
    5. Reputation map doesn't use the same key

    Expected behavior We should be able to get reputation by account 32

    Screenshots image

    Other information and links

    opened by AhmedKorim 5
  • [BUG] Investigate unhandled promise in ProposerSetUpdate e2e tests

    [BUG] Investigate unhandled promise in ProposerSetUpdate e2e tests

    Describe the bug

    We need to investigate the ProposerSetUpdate e2e tests to find out where we are not handling a promise correctly. The ProposerSetUpdate e2e tests should be deterministic during ci runs and not timeout.

    To Reproduce Steps to reproduce the behavior:

    1. Run cargo build --release -p dkg-standalone-node --features integration-tests
    2. Run cd dkg-test-suite && git submodule update --init --recursive
    3. Run cd dkg-test-suite
    4. Run yarn install
    5. To run all tests: yarn test

    Log output

    Log Output
     1 failing
    
    1) E2E Test Runner
         Proposer Set Update Proposal
           proposer set update test:
       Error: Timeout of 300000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/home/runner/work/dkg-substrate/dkg-substrate/dkg-test-suite/tests/proposals.test.ts)
        at listOnTimeout (node:internal/timers:559:17)
        at processTimers (node:internal/timers:502:7)
    

    Expected behaviour

    ProposerSetUpdate e2e tests should be deterministic and properly resolve promises to avoid timeouts.

    Other information and links

    CI runner: https://github.com/webb-tools/dkg-substrate/runs/5755473503?check_suite_focus=true

    bug ๐Ÿชฒ 
    opened by dutterbutter 4
  • DKG database backend

    DKG database backend

    Summary of changes Changes introduced in this pull request:

    • See #468
    • For the seed used in generating the signing sets, we now using the on-chain public key as the seed, instead of the local one.
    • we do now shutdown and clear all signing rounds, once we rotate sessions locally.
    • there is no need now for providing the base_path.
    • fetch_local_keys now takes an optional session id, to fetch the local keys at specific session, this useful in case that the node did shutdown and there is no rounds nor next_rounds, fetching the current active session from on-chain would help in such cases.
    • we now prevent the bug where we do generate a new next DKG key, while there is already one that is submitted on-chain.

    Reference issue to close (if applicable)

    Closes #468

    needs review ๐Ÿ‘“ 
    opened by shekohex 3
  • [SPEC] Rework `DKGWorker` to be more share-able across different async tasks

    [SPEC] Rework `DKGWorker` to be more share-able across different async tasks

    Overview

    In the context of DKGWorker::run method we start 4 Tasks to run and watch over these results, but right now we are using tokio::select! macro, and as per its docs it outlines the following "running all async expressions on the current task, the expressions are able to run concurrently but not in parallel." and for us this means for the current flow for example if finality_notifications future/stream finished first and at the same time we have a dkg_msg from the gossip_engine stream, the select macro could pick the block notification and completely ignoring "discarding" the message from the dkg stream resulting in a completely loss of the information here.

    Research

    We should instead use tokio::spawn for each of these tasks and run them independently from each others in parallel, this from also the above docs it mentions the following: "If parallelism is required, spawn each async expression using tokio::spawn and pass the join handle to select!"

    Examples

    Here is a good example of what I do reassemble in my head of a good solution for the current issue:

    pub(crate) async fn run(mut self) {
    	// ... snip ...
    	let finality_notifications_task = async move {
    		// ...
    	};
    	let import_notifications_task = async move {
    		// ...
    	};
    	let misbehaviour_task = async move {
    		// ...
    	};
    	let error_handler_task = async move {
    		// ...
    	};
    	let dkg_messages_task = async move {
    		// ...
    	};
    
    	let handles = vec![
    		tokio::spawn(finality_notifications_task),
    		tokio::spawn(import_notifications_task),
    		tokio::spawn(misbehaviour_task),
    		tokio::spwan(error_handler_task),
    		tokio::spawn(dkg_messages_task),
    	];
    	let _ = futures::future::select_all(handles).await;
    
    	// ... snip ...
    }
    
    

    Questions/Issues

    • [x] Current Implementation of the DKGWorker is not shareable across different tasks, e.g. most functions/methods takes &mut self which is not feasible to share with a mutable state, we shall use async locks or other things to make it possible.
    • [x] decouple the worker into smaller states when possible, so that it could be easily shareable between different tasks.
    spec ๐Ÿ†• p1 ๐ŸŸ  optimization โš™๏ธ 
    opened by shekohex 3
  • [BUG] Investigate high bandwidth usage of DKG

    [BUG] Investigate high bandwidth usage of DKG

    Describe the bug

    Currently the standalone testnet is utilizing ~Avg: 105.59 MBit/s. This is far above expectation is has iteratively grown in size each day.

    Screenshots

    Screen Shot 2022-04-20 at 5 31 28 PM

    Expected behaviour

    The DKG should not be utilizing this much bandwidth after only a week in operation.

    bug ๐Ÿชฒ 
    opened by dutterbutter 3
  • add pallet functionality readme

    add pallet functionality readme

    Summary of changes Changes introduced in this pull request:

    • Add readme that describes the functionality of the pallet.

    Reference issue to close (if applicable)

    Closes

    opened by OAyomide 3
  • [TASK] Use workspace features to manage versions and contributors

    [TASK] Use workspace features to manage versions and contributors

    Issue summary New rust features that allow specifying version at the workspace level could be useful.

    Other information and links https://github.com/paritytech/polkadot/pull/6095/files

    opened by drewstone 0
  • [SPEC] Retain Known Peers even after they disconnect, for `N` ms

    [SPEC] Retain Known Peers even after they disconnect, for `N` ms

    Overview

    Currently when a Peer disconnect from our DKG Gossip Engine, we do cleanup the state of that peer, which contains the known messages, and other metadata. Which is good, but not until we are running a real-world and we have the networking issues.

    https://github.com/webb-tools/dkg-substrate/blob/792d04551e86415e7f1d9e2d0c1efff22de33730/dkg-gadget/src/gossip_engine/network.rs#L500-L525

    That would result in a clean up immediately after the peer closes the stream with us, if the same peer connect again after a few secs, they will miss any messages that got should have sent to them.

    Research

    What we want instead is that, first of all, we should keep the peers after they disconnect for constant period of time, before we clean up it's state. Second thing is to detect when a peer is disconnected and mark that peer as disconnected for now, and all messages that should go for that peer should be stored somewhere in a queue; so that when they connect again we send them the messages they have missed. That would make sure that they did not miss any messages.

    Examples

    1. In the Peer information struct, we will add two things:
    /// Peer information
    #[derive(Debug)]
    struct Peer<B: Block> {
    	/// Holds a set of messages known to this peer.
    	known_messages: LruHashSet<B::Hash>,
    	/// a counter of the messages that are received from this peer.
    	///
    	/// Implemented as a HashMap/LruHashMap with the message hash as the key,
    	/// This is used to track the frequency of the messages received from this peer.
    	/// If the same message is received from this peer more than
    	/// `MAX_DUPLICATED_MESSAGES_PER_PEER`, we will flag this peer as malicious.
    	message_counter: LruHashMap<B::Hash, usize>,
    
    	/// Keeps track of the Peer state.
    	state: PeerState,
       /// Holds a queue of messages that needs to be sent to that peer, if the did miss any messages.
    	message_queue: VecDeque<SignedDKGMessage<AuthorityId>>,
    }
    
    enum PeerState {
    	Connected,
    	Disconnected,
    }
    
    1. When we get a Event::NotificationStreamClosed we mark that peer state as PeerState::Disconnected, same goes for Event::NotificationStreamOpened if we still have that peer, we change the state to be PeerState::Connected.
    fn gossip_message(&self, message: SignedDKGMessage<AuthorityId>) {
    	// ...
    	// before we call `self.service.write_notification(...)` we check the peer state,
    	// if they are disconnected, we enqueue the message to their message queue.
    	// if not, we send it normally.
    	//
    	// in a better implementation, we should use:
    	// https://docs.rs/sc-network/latest/sc_network/struct.NetworkService.html#method.notification_sender  
    }
    
    1. when we get Event::NotificationStreamOpened we send out the messages in their queue, if any.
    2. A background task that will Run every N ms to peek into the peers, find the disconnected ones, and clean them up.

    Questions/Issues

    1. What a good value for N? a 5min is good?
    feature โž• spec ๐Ÿ†• p0 ๐Ÿ”ฅ optimization โš™๏ธ difficulty: medium ๐Ÿšฉ 
    opened by shekohex 0
  • Remove all ensure_root and replace with EnsureOrigin<>

    Remove all ensure_root and replace with EnsureOrigin<>

    Issue summary We use ensure_root in a lot of places, the better way to handle this check is to have a ForceOrigin and then configure it from runtime. This will make our future migrations a lot easier when we move away from Sudo.

    p3 ๐Ÿ”ต difficulty: starter ๐Ÿ 
    opened by 1xstj 1
  • [BUG]  Received message for mixed stage

    [BUG] Received message for mixed stage

    Describe the bug

    Looks like we receive offline messages during a voting stage!

    To Reproduce Steps to reproduce the behavior:

    1. Just run the standalone network and watch the logs!

    Log output

    Log Output
    WARN tokio-runtime-worker dkg_gadget::async_protocols::incoming: Received message for mixed stage: Local: Voting: proposal = Unsigned { kind: ProposerSetUpdate, data: [187, 176, 113, 76, 107, 33, 104, 247, 92, 245, 129, 62, 151, 247, 9, 184, 123, 66, 188, 40, 64, 81, 186, 79, 134, 67, 223, 15, 58, 84, 234, 50, 0, 0, 0, 0, 0, 0, 234, 96, 0, 0, 0, 3, 0, 0, 0, 2] }, payload: Offline(DKGOfflineMessage { key: [113, 74, 82, 170, 158, 218, 250, 48, 121, 127, 30, 17, 17, 232, 86, 139, 178, 237, 5, 203, 165, 167, 96, 234, 97, 202, 104, 44, 19, 206, 47, 47], signer_set_id: 1, offline_msg: [123, 34, 115, 101, 110, 100, 101, 114, 34, 58, 49, 44, 34, 114, 101, 99, 101, 105, 118, 101, 114, 34, 58, 110, 117, 108, 108, 44, 34, 98, 111, 100, 121, 34, 58, 123, 34, 77, 52, 34, 58, 123, 34, 98, 108, 105, 110, 100, 95, 102, 97, 99, 116, 111, 114, 34, 58, 91, 55, 50, 44, 50, 44, 53, 49, 44, 49, 56, 57, 44, 50, 52, 52, 44, 50, 48, 44, 49, 53, 44, 54, 57, 44, 49, 50, 54, 44, 49, 50, 52, 44, 49, 53, 48, 44, 53, 57, 44, 49, 49, 48, 44, 49, 52, 44, 50, 52, 53, 44, 50, 44, 49, 50, 51, 44, 49, 48, 53, 44, 56, 55, 44, 57, 49, 44, 49, 51, 44, 48, 44, 50, 52, 52, 44, 50, 52, 56, 44, 49, 55, 49, 44, 49, 54, 52, 44, 49, 49, 49, 44, 50, 48, 44, 49, 52, 48, 44, 50, 49, 50, 44, 49, 48, 50, 44, 49, 48, 54, 93, 44, 34, 103, 95, 103, 97, 109, 109, 97, 95, 105, 34, 58, 123, 34, 99, 117, 114, 118, 101, 34, 58, 34, 115, 101, 99, 112, 50, 53, 54, 107, 49, 34, 44, 34, 112, 111, 105, 110, 116, 34, 58, 91, 50, 44, 56, 44, 49, 53, 55, 44, 49, 53, 51, 44, 56, 50, 44, 49, 57, 57, 44, 50, 51, 55, 44, 49, 56, 50, 44, 49, 48, 56, 44, 50, 48, 44, 54, 53, 44, 55, 54, 44, 49, 49, 51, 44, 49, 52, 44, 55, 52, 44, 49, 50, 51, 44, 49, 52, 51, 44, 52, 55, 44, 50, 51, 49, 44, 50, 52, 52, 44, 50, 49, 54, 44, 50, 52, 49, 44, 54, 57, 44, 53, 44, 49, 48, 50, 44, 53, 55, 44, 50, 52, 51, 44, 50, 51, 48, 44, 49, 51, 48, 44, 51, 52, 44, 50, 49, 56, 44, 50, 53, 52, 44, 50, 48, 53, 93, 125, 125, 125, 125], async_index: 0 })
    

    Expected behaviour

    We should never see that warning, nor we should send the offline messages to the voting stage! it is harmless, but that means there is a bug somewhere.

    Screenshots

    Environment (please complete the following information):

    • OS: Linux
    • Rust version(e.g. rustc --version): rustc 1.62.0-nightly (70b3681bf 2022-05-14)
    • Branch/commit: master branch at https://github.com/webb-tools/dkg-substrate/commit/4104a8d9f0c11a6c7845e3fffd5c08fd93f4f956

    Other information and links

    bug ๐Ÿชฒ p2 ๐ŸŸก difficulty: medium ๐Ÿšฉ 
    opened by shekohex 1
  • [SPEC] Add TEE/SGX support for the signing/keygen functionality

    [SPEC] Add TEE/SGX support for the signing/keygen functionality

    Overview

    • We want the keygen to run inside an enclave. The key should be stored in the enclave.
    • We want the signing to run inside an enclave. All sensitive operations happen inside the enclave.
    • We can send the public key generated outside of the enclave for signing set operations.
    • Using AWS / Fortanix libraries.

    Research

    • All MPC companies use enclaves for key management / operations (Fireblocks, Lit Protocol, etc.)

    Examples

    Questions/Issues

    spec ๐Ÿ†• p3 ๐Ÿ”ต needs more info โ„น๏ธ 
    opened by drewstone 0
  • [SPEC] Generate signature only from one of the signing sets

    [SPEC] Generate signature only from one of the signing sets

    Overview

    Currently we generate multiple signing sets for for signing the same unsigned proposals. The goal is to successfully sign proposals immediately in the event that some authorities are not present. For example, if we have authorities: [1,2,3] and we only generate a single signing set (1,2), then if either party is absent, we will not be able to sign until we handle a misbehaviour. Instead, we brute force sign with multiple sets. For n authorities, to cover all signing sets of size t+1, we need to generate (n choose (t+1)) sets.

    Problems

    1. This approach does not scale well for large t/n
    2. This leads to too many messages being send back and forth
    3. The signing set index may not always align on different nodes, leading to signing round failure

    Proposed variation

    We continue to generate multiple signing sets, but only one of these signing sets will be used to generate signature

    Proposed workflow

    1. Generate signing sets as before
    2. Select one signing set from the list of all generated signing sets, to ensure we select same value across different nodes and to avoid using same set again, we should consider expanding the seed using the current finalised block
    let mut seed = local_key.public_key().to_bytes(true)[1..].to_vec();
    seed.extend(header.current_finalised_block_number());
    
    

    Since the public key and finalised block is shared among all nodes, this should lead to selection of the same signing set. This also allows us to eliminate the use of async_index to seperate signing sets.

    spec ๐Ÿ†• p3 ๐Ÿ”ต 
    opened by 1xstj 5
Owner
webb
A multi-chain privacy hub for blockchains.
webb
Rust implementation of {t,n}-threshold ECDSA (elliptic curve digital signature algorithm).

Multi-party ECDSA This project is a Rust implementation of {t,n}-threshold ECDSA (elliptic curve digital signature algorithm). Threshold ECDSA include

[ZenGo X] 706 Jan 5, 2023
An ECDSA threshold signature algorithm implemented in Rust.

Open TSS This project is a Rust implementation of multi-party {t,n}-threshold signature scheme(TSS). The current version of this library supports ECDS

LatticeX Foundation 64 Dec 17, 2022
Substrate blockchain generated with Substrate Startkit

Substrate Node Template A new FRAME-based Substrate node, ready for hacking ?? Getting Started This project contains some configuration files to help

HoangDuong 1 Oct 19, 2021
Substrate blockchain generated with Substrate Startkit

Substrate Node Template A new FRAME-based Substrate node, ready for hacking ?? Getting Started This project contains some configuration files to help

HoangDuong 1 Oct 19, 2021
Substrate blockchain generated with Substrate Startkit

Substrate Node Template A new FRAME-based Substrate node, ready for hacking ?? Getting Started This project contains some configuration files to help

Liam Parry 0 Nov 6, 2021
Cryptographic signature algorithms: ECDSA, Ed25519

RustCrypto: signatures Support for digital signatures, which provide authentication of data using public-key cryptography. All algorithms reside in th

Rust Crypto 300 Jan 8, 2023
ECDSA Signature Server

Simple REST API used for serving ECDSA signatures to prevent automation software from minting NFTs in bulk.

Jonathan 3 Nov 30, 2022
Basilisk node - cross-chain liquidity protocol built on Substrate

Basilisk node Local Development Follow these steps to prepare a local Substrate development environment ??๏ธ Simple Setup Install all the required depe

Galactic Council 52 Dec 27, 2022
Substrate Node for Anmol Network

Anmol Substrate Node ?? ??๏ธ ?? Anmol is the First Cross-Chain NFT Toolkit, on Polkadot. Introducing: Moulds NFT Breeding Multi-Chain NFT Migration ink

Anmol Network 12 Aug 28, 2022
Minimal Substrate node configured for smart contracts via pallet-contracts.

substrate-contracts-node This repository contains Substrate's node-template configured to include Substrate's pallet-contracts โ€’ a smart contract modu

Parity Technologies 73 Dec 30, 2022
Substrate Node Template Generator

Substrate Node Template Generator A tool to generate stand-alone node templates of a customized Substrate clients used in "Substrate Library Extension

Parity Technologies 2 Feb 11, 2022
Subsocial full node with Substrate/Polkadot pallets for decentralized communities: blogs, posts, comments, likes, reputation.

Subsocial Node by DappForce Subsocial is a set of Substrate pallets with web UI that allows anyone to launch their own decentralized censorship-resist

DappForce 74 Nov 24, 2022
Node implementation for aleph blockchain built with Substrate framework

This repository contains the Rust implementation of Aleph Zero blockchain node based on the Substrate framework. Aleph Zero is an open-source layer 1

Aleph Zero Foundation 55 Dec 15, 2022
A Substrate-based PoA node supporting dynamic addition/removal of authorities.

Substrate PoA A sample Substrate runtime for a PoA blockchain that allows: Dynamically add/remove authorities. Automatically remove authorities when t

Gautam Dhameja 10 Jun 16, 2022
xx network Substrate based blockchain node

xx network Substrate based blockchain node Rust Setup First, complete the basic Rust setup instructions. MacOS users: setup to compile for Linux Befor

xx network 11 Dec 20, 2022
The Data Highway Substrate-based blockchain node.

DataHighway-Parachain, a parachain on the Polkadot network. Planned features include a decentralized LPWAN roaming hub for LoRaWAN IoT devices and network operator roaming agreements, participative mining, an inter-chain data market, and DAO governance.

DataHighway 11 Dec 2, 2022
This is a node implementation of Thippy, a Substrate parachain for smart contracts

Thippy โ€’- A Smart Contracts Parachain This is a node implementation of Thippy, a Substrate parachain for smart contracts. Developing Smart Contracts f

ArthurยทThomas 15 Mar 16, 2022
Substrate Node Template

This is a Proof of existence blockchain solution built in rust using the substrate framework, here i'm implementing custom macros & pallets provided by the frame framework

Samuel Jim Nnamdi 2 Oct 24, 2022
Faterium Substrate Node, Runtime, and Pallets. Contains "faterium-polls-pallet" with logic of Faterium Polls.

Faterium Substrate Node Faterium - a place where fates are forged. This is the official implementation of Faterium Crowdfunding Polls in Rust as Subst

Faterium 3 Dec 15, 2022