Repository files navigation

Build A Blockchain with Rust

English | 简体中文

Table of Contents

Intro

This project aims to demonstrate the basic principles of blockchain through a distributed ledger. The main features include:

  • HTTP JSON API provides users with interfaces such as transfer and some query apis;
  • P2P Protocol is used for interaction between nodes, and data is serialized/deserialized by protobuf. The functions include peer discovery, transaction broadcast, block broadcast, and block synchronization;
  • PoW is used as the consensus mechanism;
  • Sled, an embedded key-value database, is used as the storage backend;
  • For the convenience of demonstration, there is a wallet in each node that stores the users' private keys, so that the node can sign the transaction on behalf of users.

Architecture

See 01 | Architecture for details.

From a holistic perspective, this project is a workspace, consisting of three crates: tinychain, tinyp2p, and wallet.

  • tinychain: core business.
  • tinyp2p: a tinychain-specific p2p protocol based on rust-libp2p.
  • wallet: user private key management.

tinychain | Dependency Inversion

See 01 | Architecture for details.

In tinychain, it is divided into three layers according to responsibilities:

  • Network Layer: responsible for interacting with the outside world, including processing HTTP requests and interacting with other peers.
  • Biz Layer: based on the principle of Dependency Inversion, it defines the behavior (traits) of the network and data layers, getting rid of the dependency on them.
    • trait PeerClient: the network needs to implement this trait to send data to other nodes.
    • trait State: the data needs to implement this trait to save the local state.
  • Data Layer: responsible for saving the state.

tinychain::biz | Read/Write Separation

See 09 | Biz Layer: How to Do Read/Write Separation? for details.

The biz layer achieves lock-free programming through read/write separation. That is to say, any thread can "read", but only one thread can "write". In this project, there are two main write operations: (1) Adding user transfer data to the transaction pool; (2) Adding blocks to the database. From the above figure, only the Miner thread has write permission. When other threads need to write, they send the data to the Miner to write via the channel.

tinyp2p | CSP Concurrency Model

See 07 | tinyp2p: A CSP Concurrency Model for details.

  • p2p_client is used to process user requests. In p2p_client, the request is converted to cmd and sent to the channel.
  • A background thread exclusively owns mut p2p_server, and gets cmd from the channel one by one to execute.
  • Users can register event_handlers in p2p_server. When data is received from a remote node, event_handlers are called to process the data.

Demo

See 10 | Data Layer & Demo for details.

  1. View the commands: RUST_LOG=info ./target/debug/tinychain

  2. Create an account: RUST_LOG=info ./target/debug/tinychain new-account

  3. Query account balance and block information

About

Build A Blockchain with Rust

Topics

Resources

Stars

31 stars

Watchers

2 watching

Forks

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Build A Blockchain with Rust

English | 简体中文

Table of Contents

Intro

This project aims to demonstrate the basic principles of blockchain through a distributed ledger. The main features include:

  • HTTP JSON API provides users with interfaces such as transfer and some query apis;
  • P2P Protocol is used for interaction between nodes, and data is serialized/deserialized by protobuf. The functions include peer discovery, transaction broadcast, block broadcast, and block synchronization;
  • PoW is used as the consensus mechanism;
  • Sled, an embedded key-value database, is used as the storage backend;
  • For the convenience of demonstration, there is a wallet in each node that stores the users' private keys, so that the node can sign the transaction on behalf of users.

Architecture

See 01 | Architecture for details.

From a holistic perspective, this project is a workspace, consisting of three crates: tinychain, tinyp2p, and wallet.

  • tinychain: core business.
  • tinyp2p: a tinychain-specific p2p protocol based on rust-libp2p.
  • wallet: user private key management.

tinychain | Dependency Inversion

See 01 | Architecture for details.

In tinychain, it is divided into three layers according to responsibilities:

  • Network Layer: responsible for interacting with the outside world, including processing HTTP requests and interacting with other peers.
  • Biz Layer: based on the principle of Dependency Inversion, it defines the behavior (traits) of the network and data layers, getting rid of the dependency on them.
    • trait PeerClient: the network needs to implement this trait to send data to other nodes.
    • trait State: the data needs to implement this trait to save the local state.
  • Data Layer: responsible for saving the state.

tinychain::biz | Read/Write Separation

See 09 | Biz Layer: How to Do Read/Write Separation? for details.

The biz layer achieves lock-free programming through read/write separation. That is to say, any thread can "read", but only one thread can "write". In this project, there are two main write operations: (1) Adding user transfer data to the transaction pool; (2) Adding blocks to the database. From the above figure, only the Miner thread has write permission. When other threads need to write, they send the data to the Miner to write via the channel.

tinyp2p | CSP Concurrency Model

See 07 | tinyp2p: A CSP Concurrency Model for details.

  • p2p_client is used to process user requests. In p2p_client, the request is converted to cmd and sent to the channel.
  • A background thread exclusively owns mut p2p_server, and gets cmd from the channel one by one to execute.
  • Users can register event_handlers in p2p_server. When data is received from a remote node, event_handlers are called to process the data.

Demo

See 10 | Data Layer & Demo for details.

  1. View the commands: RUST_LOG=info ./target/debug/tinychain

  2. Create an account: RUST_LOG=info ./target/debug/tinychain new-account

  3. Query account balance and block information

About

Build A Blockchain with Rust

Topics

Resources

Stars

31 stars

Watchers

2 watching

Forks

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Build A Blockchain with Rust

English | 简体中文

Table of Contents

Intro

This project aims to demonstrate the basic principles of blockchain through a distributed ledger. The main features include:

  • HTTP JSON API provides users with interfaces such as transfer and some query apis;
  • P2P Protocol is used for interaction between nodes, and data is serialized/deserialized by protobuf. The functions include peer discovery, transaction broadcast, block broadcast, and block synchronization;
  • PoW is used as the consensus mechanism;
  • Sled, an embedded key-value database, is used as the storage backend;
  • For the convenience of demonstration, there is a wallet in each node that stores the users' private keys, so that the node can sign the transaction on behalf of users.

Architecture

See 01 | Architecture for details.

From a holistic perspective, this project is a workspace, consisting of three crates: tinychain, tinyp2p, and wallet.

  • tinychain: core business.
  • tinyp2p: a tinychain-specific p2p protocol based on rust-libp2p.
  • wallet: user private key management.

tinychain | Dependency Inversion

See 01 | Architecture for details.

In tinychain, it is divided into three layers according to responsibilities:

  • Network Layer: responsible for interacting with the outside world, including processing HTTP requests and interacting with other peers.
  • Biz Layer: based on the principle of Dependency Inversion, it defines the behavior (traits) of the network and data layers, getting rid of the dependency on them.
    • trait PeerClient: the network needs to implement this trait to send data to other nodes.
    • trait State: the data needs to implement this trait to save the local state.
  • Data Layer: responsible for saving the state.

tinychain::biz | Read/Write Separation

See 09 | Biz Layer: How to Do Read/Write Separation? for details.

The biz layer achieves lock-free programming through read/write separation. That is to say, any thread can "read", but only one thread can "write". In this project, there are two main write operations: (1) Adding user transfer data to the transaction pool; (2) Adding blocks to the database. From the above figure, only the Miner thread has write permission. When other threads need to write, they send the data to the Miner to write via the channel.

tinyp2p | CSP Concurrency Model

See 07 | tinyp2p: A CSP Concurrency Model for details.

  • p2p_client is used to process user requests. In p2p_client, the request is converted to cmd and sent to the channel.
  • A background thread exclusively owns mut p2p_server, and gets cmd from the channel one by one to execute.
  • Users can register event_handlers in p2p_server. When data is received from a remote node, event_handlers are called to process the data.

Demo

See 10 | Data Layer & Demo for details.

  1. View the commands: RUST_LOG=info ./target/debug/tinychain

  2. Create an account: RUST_LOG=info ./target/debug/tinychain new-account

  3. Query account balance and block information

About

Build A Blockchain with Rust

Topics

Resources

Stars

31 stars

Watchers

2 watching

Forks

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Build A Blockchain with Rust

English | 简体中文

Table of Contents

Intro

This project aims to demonstrate the basic principles of blockchain through a distributed ledger. The main features include:

  • HTTP JSON API provides users with interfaces such as transfer and some query apis;
  • P2P Protocol is used for interaction between nodes, and data is serialized/deserialized by protobuf. The functions include peer discovery, transaction broadcast, block broadcast, and block synchronization;
  • PoW is used as the consensus mechanism;
  • Sled, an embedded key-value database, is used as the storage backend;
  • For the convenience of demonstration, there is a wallet in each node that stores the users' private keys, so that the node can sign the transaction on behalf of users.

Architecture

See 01 | Architecture for details.

From a holistic perspective, this project is a workspace, consisting of three crates: tinychain, tinyp2p, and wallet.

  • tinychain: core business.
  • tinyp2p: a tinychain-specific p2p protocol based on rust-libp2p.
  • wallet: user private key management.

tinychain | Dependency Inversion

See 01 | Architecture for details.

In tinychain, it is divided into three layers according to responsibilities:

  • Network Layer: responsible for interacting with the outside world, including processing HTTP requests and interacting with other peers.
  • Biz Layer: based on the principle of Dependency Inversion, it defines the behavior (traits) of the network and data layers, getting rid of the dependency on them.
    • trait PeerClient: the network needs to implement this trait to send data to other nodes.
    • trait State: the data needs to implement this trait to save the local state.
  • Data Layer: responsible for saving the state.

tinychain::biz | Read/Write Separation

See 09 | Biz Layer: How to Do Read/Write Separation? for details.

The biz layer achieves lock-free programming through read/write separation. That is to say, any thread can "read", but only one thread can "write". In this project, there are two main write operations: (1) Adding user transfer data to the transaction pool; (2) Adding blocks to the database. From the above figure, only the Miner thread has write permission. When other threads need to write, they send the data to the Miner to write via the channel.

tinyp2p | CSP Concurrency Model

See 07 | tinyp2p: A CSP Concurrency Model for details.

  • p2p_client is used to process user requests. In p2p_client, the request is converted to cmd and sent to the channel.
  • A background thread exclusively owns mut p2p_server, and gets cmd from the channel one by one to execute.
  • Users can register event_handlers in p2p_server. When data is received from a remote node, event_handlers are called to process the data.

Demo

See 10 | Data Layer & Demo for details.

  1. View the commands: RUST_LOG=info ./target/debug/tinychain

  2. Create an account: RUST_LOG=info ./target/debug/tinychain new-account

  3. Query account balance and block information

About

Build A Blockchain with Rust

Topics

Resources

Stars

31 stars

Watchers

2 watching

Forks

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Build A Blockchain with Rust

English | 简体中文

Table of Contents

Intro

This project aims to demonstrate the basic principles of blockchain through a distributed ledger. The main features include:

  • HTTP JSON API provides users with interfaces such as transfer and some query apis;
  • P2P Protocol is used for interaction between nodes, and data is serialized/deserialized by protobuf. The functions include peer discovery, transaction broadcast, block broadcast, and block synchronization;
  • PoW is used as the consensus mechanism;
  • Sled, an embedded key-value database, is used as the storage backend;
  • For the convenience of demonstration, there is a wallet in each node that stores the users' private keys, so that the node can sign the transaction on behalf of users.

Architecture

See 01 | Architecture for details.

From a holistic perspective, this project is a workspace, consisting of three crates: tinychain, tinyp2p, and wallet.

  • tinychain: core business.
  • tinyp2p: a tinychain-specific p2p protocol based on rust-libp2p.
  • wallet: user private key management.

tinychain | Dependency Inversion

See 01 | Architecture for details.

In tinychain, it is divided into three layers according to responsibilities:

  • Network Layer: responsible for interacting with the outside world, including processing HTTP requests and interacting with other peers.
  • Biz Layer: based on the principle of Dependency Inversion, it defines the behavior (traits) of the network and data layers, getting rid of the dependency on them.
    • trait PeerClient: the network needs to implement this trait to send data to other nodes.
    • trait State: the data needs to implement this trait to save the local state.
  • Data Layer: responsible for saving the state.

tinychain::biz | Read/Write Separation

See 09 | Biz Layer: How to Do Read/Write Separation? for details.

The biz layer achieves lock-free programming through read/write separation. That is to say, any thread can "read", but only one thread can "write". In this project, there are two main write operations: (1) Adding user transfer data to the transaction pool; (2) Adding blocks to the database. From the above figure, only the Miner thread has write permission. When other threads need to write, they send the data to the Miner to write via the channel.

tinyp2p | CSP Concurrency Model

See 07 | tinyp2p: A CSP Concurrency Model for details.

  • p2p_client is used to process user requests. In p2p_client, the request is converted to cmd and sent to the channel.
  • A background thread exclusively owns mut p2p_server, and gets cmd from the channel one by one to execute.
  • Users can register event_handlers in p2p_server. When data is received from a remote node, event_handlers are called to process the data.

Demo

See 10 | Data Layer & Demo for details.

  1. View the commands: RUST_LOG=info ./target/debug/tinychain

  2. Create an account: RUST_LOG=info ./target/debug/tinychain new-account

  3. Query account balance and block information

About

Build A Blockchain with Rust

Topics

Resources

Stars

31 stars

Watchers

2 watching

Forks

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Build A Blockchain with Rust

English | 简体中文

Table of Contents

Intro

This project aims to demonstrate the basic principles of blockchain through a distributed ledger. The main features include:

  • HTTP JSON API provides users with interfaces such as transfer and some query apis;
  • P2P Protocol is used for interaction between nodes, and data is serialized/deserialized by protobuf. The functions include peer discovery, transaction broadcast, block broadcast, and block synchronization;
  • PoW is used as the consensus mechanism;
  • Sled, an embedded key-value database, is used as the storage backend;
  • For the convenience of demonstration, there is a wallet in each node that stores the users' private keys, so that the node can sign the transaction on behalf of users.

Architecture

See 01 | Architecture for details.

From a holistic perspective, this project is a workspace, consisting of three crates: tinychain, tinyp2p, and wallet.

  • tinychain: core business.
  • tinyp2p: a tinychain-specific p2p protocol based on rust-libp2p.
  • wallet: user private key management.

tinychain | Dependency Inversion

See 01 | Architecture for details.

In tinychain, it is divided into three layers according to responsibilities:

  • Network Layer: responsible for interacting with the outside world, including processing HTTP requests and interacting with other peers.
  • Biz Layer: based on the principle of Dependency Inversion, it defines the behavior (traits) of the network and data layers, getting rid of the dependency on them.
    • trait PeerClient: the network needs to implement this trait to send data to other nodes.
    • trait State: the data needs to implement this trait to save the local state.
  • Data Layer: responsible for saving the state.

tinychain::biz | Read/Write Separation

See 09 | Biz Layer: How to Do Read/Write Separation? for details.

The biz layer achieves lock-free programming through read/write separation. That is to say, any thread can "read", but only one thread can "write". In this project, there are two main write operations: (1) Adding user transfer data to the transaction pool; (2) Adding blocks to the database. From the above figure, only the Miner thread has write permission. When other threads need to write, they send the data to the Miner to write via the channel.

tinyp2p | CSP Concurrency Model

See 07 | tinyp2p: A CSP Concurrency Model for details.

  • p2p_client is used to process user requests. In p2p_client, the request is converted to cmd and sent to the channel.
  • A background thread exclusively owns mut p2p_server, and gets cmd from the channel one by one to execute.
  • Users can register event_handlers in p2p_server. When data is received from a remote node, event_handlers are called to process the data.

Demo

See 10 | Data Layer & Demo for details.

  1. View the commands: RUST_LOG=info ./target/debug/tinychain

  2. Create an account: RUST_LOG=info ./target/debug/tinychain new-account

  3. Query account balance and block information

About

Build A Blockchain with Rust

Topics

Resources

Stars

31 stars

Watchers

2 watching

Forks

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Build A Blockchain with Rust

English | 简体中文

Table of Contents

Intro

This project aims to demonstrate the basic principles of blockchain through a distributed ledger. The main features include:

  • HTTP JSON API provides users with interfaces such as transfer and some query apis;
  • P2P Protocol is used for interaction between nodes, and data is serialized/deserialized by protobuf. The functions include peer discovery, transaction broadcast, block broadcast, and block synchronization;
  • PoW is used as the consensus mechanism;
  • Sled, an embedded key-value database, is used as the storage backend;
  • For the convenience of demonstration, there is a wallet in each node that stores the users' private keys, so that the node can sign the transaction on behalf of users.

Architecture

See 01 | Architecture for details.

From a holistic perspective, this project is a workspace, consisting of three crates: tinychain, tinyp2p, and wallet.

  • tinychain: core business.
  • tinyp2p: a tinychain-specific p2p protocol based on rust-libp2p.
  • wallet: user private key management.

tinychain | Dependency Inversion

See 01 | Architecture for details.

In tinychain, it is divided into three layers according to responsibilities:

  • Network Layer: responsible for interacting with the outside world, including processing HTTP requests and interacting with other peers.
  • Biz Layer: based on the principle of Dependency Inversion, it defines the behavior (traits) of the network and data layers, getting rid of the dependency on them.
    • trait PeerClient: the network needs to implement this trait to send data to other nodes.
    • trait State: the data needs to implement this trait to save the local state.
  • Data Layer: responsible for saving the state.

tinychain::biz | Read/Write Separation

See 09 | Biz Layer: How to Do Read/Write Separation? for details.

The biz layer achieves lock-free programming through read/write separation. That is to say, any thread can "read", but only one thread can "write". In this project, there are two main write operations: (1) Adding user transfer data to the transaction pool; (2) Adding blocks to the database. From the above figure, only the Miner thread has write permission. When other threads need to write, they send the data to the Miner to write via the channel.

tinyp2p | CSP Concurrency Model

See 07 | tinyp2p: A CSP Concurrency Model for details.

  • p2p_client is used to process user requests. In p2p_client, the request is converted to cmd and sent to the channel.
  • A background thread exclusively owns mut p2p_server, and gets cmd from the channel one by one to execute.
  • Users can register event_handlers in p2p_server. When data is received from a remote node, event_handlers are called to process the data.

Demo

See 10 | Data Layer & Demo for details.

  1. View the commands: RUST_LOG=info ./target/debug/tinychain

  2. Create an account: RUST_LOG=info ./target/debug/tinychain new-account

  3. Query account balance and block information

About

Build A Blockchain with Rust

Topics

Resources

Stars

31 stars

Watchers

2 watching

Forks

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Build A Blockchain with Rust

English | 简体中文

Table of Contents

Intro

This project aims to demonstrate the basic principles of blockchain through a distributed ledger. The main features include:

  • HTTP JSON API provides users with interfaces such as transfer and some query apis;
  • P2P Protocol is used for interaction between nodes, and data is serialized/deserialized by protobuf. The functions include peer discovery, transaction broadcast, block broadcast, and block synchronization;
  • PoW is used as the consensus mechanism;
  • Sled, an embedded key-value database, is used as the storage backend;
  • For the convenience of demonstration, there is a wallet in each node that stores the users' private keys, so that the node can sign the transaction on behalf of users.

Architecture

See 01 | Architecture for details.

From a holistic perspective, this project is a workspace, consisting of three crates: tinychain, tinyp2p, and wallet.

  • tinychain: core business.
  • tinyp2p: a tinychain-specific p2p protocol based on rust-libp2p.
  • wallet: user private key management.

tinychain | Dependency Inversion

See 01 | Architecture for details.

In tinychain, it is divided into three layers according to responsibilities:

  • Network Layer: responsible for interacting with the outside world, including processing HTTP requests and interacting with other peers.
  • Biz Layer: based on the principle of Dependency Inversion, it defines the behavior (traits) of the network and data layers, getting rid of the dependency on them.
    • trait PeerClient: the network needs to implement this trait to send data to other nodes.
    • trait State: the data needs to implement this trait to save the local state.
  • Data Layer: responsible for saving the state.

tinychain::biz | Read/Write Separation

See 09 | Biz Layer: How to Do Read/Write Separation? for details.

The biz layer achieves lock-free programming through read/write separation. That is to say, any thread can "read", but only one thread can "write". In this project, there are two main write operations: (1) Adding user transfer data to the transaction pool; (2) Adding blocks to the database. From the above figure, only the Miner thread has write permission. When other threads need to write, they send the data to the Miner to write via the channel.

tinyp2p | CSP Concurrency Model

See 07 | tinyp2p: A CSP Concurrency Model for details.

  • p2p_client is used to process user requests. In p2p_client, the request is converted to cmd and sent to the channel.
  • A background thread exclusively owns mut p2p_server, and gets cmd from the channel one by one to execute.
  • Users can register event_handlers in p2p_server. When data is received from a remote node, event_handlers are called to process the data.

Demo

See 10 | Data Layer & Demo for details.

  1. View the commands: RUST_LOG=info ./target/debug/tinychain

  2. Create an account: RUST_LOG=info ./target/debug/tinychain new-account

  3. Query account balance and block information

About

Build A Blockchain with Rust

Topics

Resources

Stars

31 stars

Watchers

2 watching

Forks

Used by

Contributors

Languages