A UTXO chain implementation on Substrate, with two self-guided workshops. Original UXTO inspiration by Dmitriy Kashitsyn.
Substrate Version: 2.0.0-rc6
. For educational purposes only.
Installation: Setting up Rust & Substrate dependencies
UI Demo: Demo of UTXO implementation in a simple UI
Beginner Workshop: A self guided, 1 hour workshop that familiarizes you with Substrate.
Advanced Workshop: A self guided, 2 hour video tutorial, that teaches you how to build a UTXO blockchain from scratch.
Helpful Resources: Additional supporting documentation and references for troubleshooting.
curl https://sh.rustup.rs -sSf | sh
# On Windows, download and run rustup-init.exe
# from https://rustup.rs instead
rustup update nightly
rustup target add wasm32-unknown-unknown --toolchain nightly
rustup update stable
Clone your copy of the workshop codebase
git clone https://github.com/substrate-developer-hub/utxo-workshop.git
In this UI demo, you will interact with the UTXO blockchain via the Polkadot UI.
The following example takes you through a scenario where:
Compile and build a release node
cargo build --release
Start a node. The --dev
flag will start a single mining node, and the --tmp
flag will start it in a new temporary directory.
./target/release/utxo-workshop --dev --tmp
In the console note the helper printouts. In particular, notice the default account Alice
already has 100 UTXO
within the genesis block.
Open Polkadot JS making sure the client is connected to your local node by going to Settings > General and selecting Local Node
in the remote node
dropdown.
Declare custom datatypes in PolkadotJS as the frontend cannot automatically detect this information. To do this, go to Settings > Developer tab and paste in the following JSON:
{
"Address": "AccountId",
"LookupSource": "AccountId",
"Value": "u128",
"TransactionInput": {
"outpoint": "Hash",
"sigscript": "H512"
},
"TransactionOutput": {
"value": "Value",
"pubkey": "Hash"
},
"Transaction": {
"inputs": "Vec<TransactionInput>",
"outputs": "Vec<TransactionOutput>"
},
"Difficulty": "U256",
"DifficultyAndTimestamp": {
"difficulty": "Difficulty",
"timestamp": "Moment"
},
"Public": "H256"
}
Confirm that Alice already has 100 UTXO at genesis. In Chain State
> Storage
, select utxo
. Input the hash 0x76584168d10a20084082ed80ec71e2a783abbb8dd6eb9d4893b089228498e9ff
. Click the +
notation to query blockchain state.
Notice that:
100
Spend Alice's UTXO, giving 50 to Bob. In the Extrinsics
tab, invoke the spend
function from the utxo
pallet, using Alice as the transaction sender. Use the following input parameters:
0x76584168d10a20084082ed80ec71e2a783abbb8dd6eb9d4893b089228498e9ff
0x6ceab99702c60b111c12c2867679c5555c00dcd4d6ab40efa01e3a65083bfb6c6f5c1ed3356d7141ec61894153b8ba7fb413bf1e990ed99ff6dee5da1b24fd83
50
0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48
Send as an unsigned
transaction. With UTXO blockchains, the proof is already in the sigscript
input.
Verify that your transaction succeeded. In Chain State
, look up the newly created UTXO hash: 0xdbc75ab8ee9b83dcbcea4695f9c42754d94e92c3c397d63b1bc627c2a2ef94e6
to verify that a new UTXO of 50, belonging to Bob, now exists! Also you can verify that Alice's original UTXO has been spent and no longer exists in UtxoStore.
Coming soon: A video walkthrough of the above demo.
Estimated time: 2 hours
In this workshop you will:
Your challenge is to fix the code such that:
utxo.rs
pass, ensuring secure transactionsworkshop
branch. The Master
branch has the solutions, so don't peek!git fetch origin workshop:workshop
git checkout workshop
cargo test -p utxo-runtime
.compiling utxo-runtime v2.0.0 (/Users/nicole/Desktop/utxo-workshop/runtime)
error[E0433]: failed to resolve: use of undeclared type or module `H512`
--> /Users/nicole/Desktop/utxo-workshop/runtime/src/utxo.rs:236:31
|
236 | input.sigscript = H512::zero();
| ^^^^ use of undeclared type or module `H512`
...
Your first task: fix all the compiler errors! Hint: Look for the TODO
comments in utxo.rs
to see where to fix errors.
Once your code compiles, it's now time to fix the 8
failing tests!
failures:
utxo::tests::attack_by_double_counting_input
utxo::tests::attack_by_double_generating_output
utxo::tests::attack_by_over_spending
utxo::tests::attack_by_overflowing_value
utxo::tests::attack_by_permanently_sinking_outputs
utxo::tests::attack_with_empty_transactions
utxo::tests::attack_with_invalid_signature
utxo::tests::test_simple_transaction
utxo.rs
, edit the logic in validate_transaction()
function to make all tests pass.running 8 tests
test utxo::tests::attack_by_overflowing_value ... ok
test utxo::tests::attack_by_double_counting_input ... ok
test utxo::tests::attack_by_double_generating_output ... ok
test utxo::tests::attack_by_over_spending ... ok
test utxo::tests::attack_with_empty_transactions ... ok
test utxo::tests::attack_with_invalid_signature ... ok
test utxo::tests::attack_by_permanently_sinking_outputs ... ok
test utxo::tests::test_simple_transaction ... ok
VIDEO TUTORIALS COMING SOON
Estimated time: 2 hours
In this workshop, you will implement this UTXO project from scratch using Substrate.
You will learn:
Checkout the startercode
branch to get the boilerplate for this workshop.
git fetch origin startercode:startercode
git checkout startercode