# Install Rust toolchains
$ curl https://sh.rustup.rs -sSf | sh -s -- -y && \
export PATH="$PATH:$HOME/.cargo/bin"
# Build the node binrary
$ git clone -b v1.0 https://github.com/paritytech/substrate
$ cargo install --force --path subkey subkey
$ cd node-template && ./scripts/init.sh && ./scripts/build.sh
$ cargo build --release
$ cd ..
$ ./target/release/node-template \
--base-path /tmp/alice \
--chain=local \
--key //Alice \
--port 30333 \
--telemetry-url ws://telemetry.polkadot.io:1024 \
--validator \
--name AlicesNode
$ ./target/release/node-template \
--base-path /tmp/bob \
--chain=local \
--key //Bob \
--port 30334 \
--telemetry-url ws://telemetry.polkadot.io:1024 \
--validator \
--name BobsNode \
--bootnodes /ip4/<Alices IP Address>/tcp/<Alices Port>/p2p/<Alices Node ID>
- open
https://polkadot.js.org/apps/#/settings
- use custom endpoint and input
ws://localhost:9944/
- Choose
Explorer
in the left panel, and see the new blocks are generated almost every 10 seconds.
When consensus is rejected, try clear the data of the chain
- purge chain data with
./target/release/node-template purge-chain
. - delete the temp data in base path.
Create new file called poe.rs
under ./node-template/runtime/src
, now let's add some stuff in it.
use support::{decl_module, decl_storage, decl_event, ensure, StorageMap};
use rstd::vec::Vec;
use system::ensure_signed;
pub trait Trait: system::Trait {
/// The overarching event type.
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
}
decl_event!(
pub enum Event<T> where AccountId = <T as system::Trait>::AccountId {
// Event emitted when a proof has been stored into chain storage
ProofStored(AccountId, Vec<u8>),
// Event emitted when a proof has been erased from chain storage
ProofErased(AccountId, Vec<u8>),
}
);
decl_storage! {
trait Store for Module<T: Trait> as PoeStorage {
// Define a 'Proofs' storage item for a map with
// the proof digest as the key, and associated AccountId as value.
// The 'get(proofs)' is the default getter.
Proofs get(proofs): map Vec<u8> => T::AccountId;
}
}
decl_module! {
/// The module declaration.
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
// A default function for depositing events
fn deposit_event() = default;
// Allow a user to store an unclaimed proof
fn store_proof(origin, digest: Vec<u8>) {
// Verify that the incoming transaction is signed
let sender = ensure_signed(origin)?;
// Verify that the specified proof has not been claimed yet
ensure!(!<Proofs::<T>>::exists(&digest), "This proof has already been claimed");
// Store the proof and the claim owner
<Proofs::<T>>::insert(&digest, sender.clone());
// Emit an event that the claim was stored
Self::deposit_event(RawEvent::ProofStored(sender, digest));
}
// Allow the owner of a proof to erase their claim
fn erase_proof(origin, digest: Vec<u8>) {
// Determine who is calling the function
let sender = ensure_signed(origin)?;
// Verify that the specified proof has been claimed
ensure!(<Proofs::<T>>::exists(&digest), "This proof has not been stored yet");
// Get owner of the claim
let owner = Self::proofs(&digest);
// Verify that sender of the current call is the claim owner
ensure!(sender == owner, "You must own this proof to erase it");
// Remove claim from storage
<Proofs::<T>>::remove(&digest);
// Emit an event that the claim was erased
Self::deposit_event(RawEvent::ProofErased(sender, digest));
}
}
}
Edit the lib.rs
file in the same folder.
# Step 1: Add module into runtime
mod poe;
# Step 2: Add the trait implementation
impl poe::Trait for Runtime {
type Event = Event;
}
# Step 3: Update `construct_runtime`
construct_runtime!(
pub enum Runtime where
Block = Block,
NodeBlock = opaque::Block,
UncheckedExtrinsic = UncheckedExtrinsic
{
...
POEModule: poe::{Module, Call, Storage, Event<T>},
}
);
And be sure you are under /node-template
folder
$ ./scripts/build.sh
$ cargo build --release
See complete lib.rs and poe.rs
For detail, check Shawn's Create your first Substrate blockchan tutorial, which maybe slightly difference from the tutorial here.
A Web App is live here.
If you want to connect with your local host, please folk the substrate front end template, and comment in this line to connect to local node, also comment out the next line with remote websocket link.
The UI part code is here
-
open the blockchain explorer here
https://polkadot.js.org/apps/#/sudo
-
Upload the wasm file, you could click on the small file icon on the right side, and choose the wasm under
./node-template/runtime/wasm/target/wasm32-unknown-unknown/release/node_template_runtime_wasm.compact.wasm
-
Click
submit
to broadcast the new runtime to other users. -
Refresh the page to reload the RPC bindings.
-
Now you could call the dispatchable functions or check the state with our new
poe
module!
- How to migrate the blockchain state with on_initialize function
- When need to use purge-chain for the upgrade
- Substrate Tutorials
- Substrate Collectables Workshop
- A brief summary of everything Substrate and Polkadot
- Clone and follow instruction from the Substrate Package
- Join and ask questions in the Substrate Technical channel on Riot
- Explore and read the Substrate Runtime Module Library
- How to correctly upgrade a runtime on Substrate node?