From e64c7a6dbbe3230814e0f2b619106ee028e67b45 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 16 Sep 2023 03:38:07 +0000 Subject: [PATCH] deploy: f46c70a7b9fb58bad54da7a7b47e87e6574f959f --- 404.html | 4 ++-- assets/js/{176b9270.44274b31.js => 176b9270.7e62e9ca.js} | 2 +- assets/js/2c43fa15.207825b9.js | 1 + assets/js/2c43fa15.31f9975a.js | 1 - assets/js/{4b2e3693.91b3b02e.js => 4b2e3693.e95acd7d.js} | 2 +- assets/js/{5e2b223b.15433e20.js => 5e2b223b.a4c94edd.js} | 2 +- assets/js/{6d9f7284.2f0c9ec9.js => 6d9f7284.323f24f9.js} | 2 +- assets/js/8af0162e.56b325a5.js | 1 + assets/js/8af0162e.755af75f.js | 1 - assets/js/{98916265.fb9290c4.js => 98916265.77c49894.js} | 2 +- assets/js/{c4f5d8e4.1547c3df.js => c4f5d8e4.9f338d1a.js} | 2 +- assets/js/{e9813fd7.b7353df6.js => e9813fd7.3a0b3c40.js} | 2 +- assets/js/{ffbe244f.7b20f12d.js => ffbe244f.afde17d8.js} | 2 +- .../{runtime~main.6eb3c6f5.js => runtime~main.8ba77859.js} | 2 +- docs/basics/communitynodes/index.html | 4 ++-- docs/basics/concepts/cell-model/index.html | 6 +++--- docs/basics/concepts/ckb-vm/index.html | 4 ++-- docs/basics/concepts/consensus/index.html | 4 ++-- docs/basics/concepts/cryptowallet/index.html | 4 ++-- docs/basics/concepts/economics/index.html | 4 ++-- docs/basics/concepts/nervos-blockchain/index.html | 4 ++-- docs/basics/faq/address/index.html | 4 ++-- docs/basics/faq/general/index.html | 4 ++-- docs/basics/glossary/index.html | 6 +++--- docs/basics/guides/ckb-on-windows/index.html | 4 ++-- docs/basics/guides/crypto wallets/bitpie/index.html | 4 ++-- docs/basics/guides/crypto wallets/imtoken/index.html | 4 ++-- docs/basics/guides/crypto wallets/neuron/index.html | 4 ++-- docs/basics/guides/crypto wallets/portalwallet/index.html | 4 ++-- docs/basics/guides/crypto wallets/safepal/index.html | 4 ++-- docs/basics/guides/devchain/index.html | 6 +++--- docs/basics/guides/get-ckb/index.html | 4 ++-- docs/basics/guides/mainnet/index.html | 4 ++-- docs/basics/guides/mining-ckb/index.html | 4 ++-- docs/basics/guides/monitor-nodes/index.html | 4 ++-- docs/basics/guides/run-ckb-with-docker/index.html | 4 ++-- docs/basics/guides/testnet/index.html | 4 ++-- docs/basics/introduction/index.html | 4 ++-- docs/basics/tools/index.html | 4 ++-- docs/essays/ckb-core-dev/index.html | 6 +++--- docs/essays/debug/index.html | 4 ++-- docs/essays/dependencies/index.html | 4 ++-- docs/essays/developer-materials-guide/index.html | 4 ++-- docs/essays/faq/index.html | 4 ++-- docs/essays/integrity-check/index.html | 4 ++-- docs/essays/introduction/index.html | 4 ++-- docs/essays/lifecycle/index.html | 4 ++-- docs/essays/mint-sudt-via-contract/index.html | 4 ++-- docs/essays/polyjuice/index.html | 6 +++--- docs/essays/pprof/index.html | 4 ++-- docs/essays/pw-lock/index.html | 4 ++-- docs/essays/rfcs/index.html | 4 ++-- docs/essays/rules/index.html | 4 ++-- docs/essays/tx-confirmation/index.html | 4 ++-- docs/essays/tx-pool/index.html | 4 ++-- docs/essays/upgradability/index.html | 4 ++-- docs/essays/workflow/index.html | 4 ++-- docs/integrate/introduction/index.html | 4 ++-- docs/integrate/qa/index.html | 6 +++--- docs/integrate/sdk/index.html | 4 ++-- docs/labs/capsule-dynamic-loading-tutorial/index.html | 4 ++-- docs/labs/capsule-exec/index.html | 4 ++-- docs/labs/introduction/index.html | 4 ++-- docs/labs/lumos-nervosdao/index.html | 6 +++--- docs/labs/sudtbycapsule/index.html | 6 +++--- docs/reference/cell/index.html | 6 +++--- docs/reference/halving/index.html | 4 ++-- docs/reference/introduction/index.html | 4 ++-- docs/reference/rpc/index.html | 4 ++-- docs/reference/script/index.html | 4 ++-- docs/reference/transaction/index.html | 4 ++-- index.html | 6 +++--- search/index.html | 4 ++-- 73 files changed, 141 insertions(+), 141 deletions(-) rename assets/js/{176b9270.44274b31.js => 176b9270.7e62e9ca.js} (99%) create mode 100644 assets/js/2c43fa15.207825b9.js delete mode 100644 assets/js/2c43fa15.31f9975a.js rename assets/js/{4b2e3693.91b3b02e.js => 4b2e3693.e95acd7d.js} (75%) rename assets/js/{5e2b223b.15433e20.js => 5e2b223b.a4c94edd.js} (95%) rename assets/js/{6d9f7284.2f0c9ec9.js => 6d9f7284.323f24f9.js} (99%) create mode 100644 assets/js/8af0162e.56b325a5.js delete mode 100644 assets/js/8af0162e.755af75f.js rename assets/js/{98916265.fb9290c4.js => 98916265.77c49894.js} (99%) rename assets/js/{c4f5d8e4.1547c3df.js => c4f5d8e4.9f338d1a.js} (85%) rename assets/js/{e9813fd7.b7353df6.js => e9813fd7.3a0b3c40.js} (68%) rename assets/js/{ffbe244f.7b20f12d.js => ffbe244f.afde17d8.js} (99%) rename assets/js/{runtime~main.6eb3c6f5.js => runtime~main.8ba77859.js} (55%) diff --git a/404.html b/404.html index a2df58dd5..eee6c950d 100644 --- a/404.html +++ b/404.html @@ -14,13 +14,13 @@ Page Not Found | Nervos CKB - +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

- + \ No newline at end of file diff --git a/assets/js/176b9270.44274b31.js b/assets/js/176b9270.7e62e9ca.js similarity index 99% rename from assets/js/176b9270.44274b31.js rename to assets/js/176b9270.7e62e9ca.js index ccf6cf436..a1bb6ae22 100644 --- a/assets/js/176b9270.44274b31.js +++ b/assets/js/176b9270.7e62e9ca.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[7818],{3905:(e,t,a)=>{a.d(t,{Zo:()=>k,kt:()=>p});var l=a(7294);function n(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function i(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,l)}return a}function o(e){for(var t=1;t=0||(n[a]=e[a]);return n}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(l=0;l=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(n[a]=e[a])}return n}var s=l.createContext({}),u=function(e){var t=l.useContext(s),a=t;return e&&(a="function"==typeof e?e(t):o(o({},t),e)),a},k=function(e){var t=u(e.components);return l.createElement(s.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return l.createElement(l.Fragment,{},t)}},h=l.forwardRef((function(e,t){var a=e.components,n=e.mdxType,i=e.originalType,s=e.parentName,k=r(e,["components","mdxType","originalType","parentName"]),h=u(a),p=n,d=h["".concat(s,".").concat(p)]||h[p]||c[p]||i;return a?l.createElement(d,o(o({ref:t},k),{},{components:a})):l.createElement(d,o({ref:t},k))}));function p(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var i=a.length,o=new Array(i);o[0]=h;var r={};for(var s in t)hasOwnProperty.call(t,s)&&(r[s]=t[s]);r.originalType=e,r.mdxType="string"==typeof e?e:n,o[1]=r;for(var u=2;u{a.r(t),a.d(t,{assets:()=>h,contentTitle:()=>k,default:()=>m,frontMatter:()=>u,metadata:()=>c,toc:()=>p});var l=a(7462),n=a(3366),i=(a(7294),a(3905)),o=a(4996),r=a(9960),s=["components"],u={id:"glossary",title:"Glossary"},k=void 0,c={unversionedId:"basics/glossary",id:"basics/glossary",title:"Glossary",description:"Glossary Sections",source:"@site/docs/basics/glossary.md",sourceDirName:"basics",slug:"/basics/glossary",permalink:"/docs/basics/glossary",draft:!1,editUrl:"https://github.com/nervosnetwork/docs-new/tree/develop/website/docs/basics/glossary.md",tags:[],version:"current",frontMatter:{id:"glossary",title:"Glossary"},sidebar:"Basics",previous:{title:"Community Nodes",permalink:"/docs/basics/communitynodes"},next:{title:"General FAQ",permalink:"/docs/basics/faq/general"}},h={},p=[{value:"Glossary Sections",id:"glossary-sections",level:2},{value:"General Glossary",id:"general-glossary",level:2},{value:"Account",id:"account",level:3},{value:"Address",id:"address",level:3},{value:"Synonyms",id:"synonyms",level:4},{value:"Asset",id:"asset",level:3},{value:"Synonyms",id:"synonyms-1",level:4},{value:"Block",id:"block",level:3},{value:"See Also",id:"see-also",level:4},{value:"Block Height",id:"block-height",level:3},{value:"Synonyms",id:"synonyms-2",level:4},{value:"See Also",id:"see-also-1",level:4},{value:"Block Interval",id:"block-interval",level:3},{value:"Synonyms",id:"synonyms-3",level:4},{value:"See Also",id:"see-also-2",level:4},{value:"Block Propagation",id:"block-propagation",level:3},{value:"Synonyms",id:"synonyms-4",level:4},{value:"See Also",id:"see-also-3",level:4},{value:"Block Reward",id:"block-reward",level:3},{value:"See Also",id:"see-also-4",level:4},{value:"Block Time",id:"block-time",level:3},{value:"Synonyms",id:"synonyms-5",level:4},{value:"Blockchain",id:"blockchain",level:3},{value:"See Also",id:"see-also-5",level:4},{value:"BLS Signature",id:"bls-signature",level:3},{value:"See Also",id:"see-also-6",level:4},{value:"Broadcast",id:"broadcast",level:3},{value:"See Also",id:"see-also-7",level:4},{value:"Capacity",id:"capacity",level:3},{value:"Synonyms",id:"synonyms-6",level:4},{value:"See Also",id:"see-also-8",level:4},{value:"Cell",id:"cell",level:3},{value:"Synonyms",id:"synonyms-7",level:4},{value:"See Also",id:"see-also-9",level:4},{value:"Cell Model",id:"cell-model",level:3},{value:"See Also",id:"see-also-10",level:4},{value:"Censorship Resistance",id:"censorship-resistance",level:3},{value:"Chain",id:"chain",level:3},{value:"Synonyms",id:"synonyms-8",level:4},{value:"CKB",id:"ckb",level:3},{value:"Synonyms",id:"synonyms-9",level:4},{value:"CKByte",id:"ckbyte",level:3},{value:"Synonyms",id:"synonyms-10",level:4},{value:"Not To Be Confused With",id:"not-to-be-confused-with",level:4},{value:"CKB-VM",id:"ckb-vm",level:3},{value:"See Also",id:"see-also-11",level:4},{value:"Code Hash",id:"code-hash",level:3},{value:"See Also",id:"see-also-12",level:4},{value:"Cold Storage",id:"cold-storage",level:3},{value:"See Also",id:"see-also-13",level:4},{value:"Cold Wallet",id:"cold-wallet",level:3},{value:"See Also",id:"see-also-14",level:4},{value:"Commit",id:"commit",level:3},{value:"Commit-Chain",id:"commit-chain",level:3},{value:"Commit Reward",id:"commit-reward",level:3},{value:"Common Knowledge Base",id:"common-knowledge-base",level:3},{value:"Synonyms",id:"synonyms-11",level:4},{value:"Not To Be Confused With",id:"not-to-be-confused-with-1",level:4},{value:"See Also",id:"see-also-15",level:4},{value:"Common Knowledge Byte",id:"common-knowledge-byte",level:3},{value:"Synonyms",id:"synonyms-12",level:4},{value:"Not To Be Confused With",id:"not-to-be-confused-with-2",level:4},{value:"See Also",id:"see-also-16",level:4},{value:"Confirmation",id:"confirmation",level:3},{value:"See Also",id:"see-also-17",level:4},{value:"Consensus",id:"consensus",level:3},{value:"See Also",id:"see-also-18",level:4},{value:"Consume",id:"consume",level:3},{value:"Contract Account",id:"contract-account",level:3},{value:"See Also",id:"see-also-19",level:4},{value:"Cryptocurrency",id:"cryptocurrency",level:3},{value:"See Also",id:"see-also-20",level:4},{value:"Cryptographic Signature",id:"cryptographic-signature",level:3},{value:"Synonyms",id:"synonyms-13",level:4},{value:"Cryptography",id:"cryptography",level:3},{value:"See Also",id:"see-also-21",level:4},{value:"Cycles",id:"cycles",level:3},{value:"See Also",id:"see-also-22",level:4},{value:"DAO",id:"dao",level:3},{value:"See Also",id:"see-also-23",level:4},{value:"DApp",id:"dapp",level:3},{value:"Data",id:"data",level:3},{value:"See Also",id:"see-also-24",level:4},{value:"Decentralization",id:"decentralization",level:3},{value:"See Also",id:"see-also-25",level:4},{value:"DeFi",id:"defi",level:3},{value:"Digital Asset",id:"digital-asset",level:3},{value:"Synonyms",id:"synonyms-14",level:4},{value:"Digital Currency",id:"digital-currency",level:3},{value:"See Also",id:"see-also-26",level:4},{value:"Distributed",id:"distributed",level:3},{value:"See Also",id:"see-also-27",level:4},{value:"Double-Spending",id:"double-spending",level:3},{value:"See Also",id:"see-also-28",level:4},{value:"Epoch",id:"epoch",level:3},{value:"See Also",id:"see-also-29",level:4},{value:"Fee",id:"fee",level:3},{value:"See Also",id:"see-also-30",level:4},{value:"Fee Rate",id:"fee-rate",level:3},{value:"See Also",id:"see-also-31",level:4},{value:"First-Class Assets",id:"first-class-assets",level:3},{value:"See Also",id:"see-also-32",level:4},{value:"Fork",id:"fork",level:3},{value:"Full Node",id:"full-node",level:3},{value:"See Also",id:"see-also-33",level:4},{value:"Full Payload Format",id:"full-payload-format",level:3},{value:"See Also",id:"see-also-34",level:4},{value:"Fungible Token",id:"fungible-token",level:3},{value:"See Also",id:"see-also-35",level:4},{value:"Gas Limit",id:"gas-limit",level:3},{value:"See Also",id:"see-also-36",level:4},{value:"Hard-Fork",id:"hard-fork",level:3},{value:"Hardware Wallet",id:"hardware-wallet",level:3},{value:"See Also",id:"see-also-37",level:4},{value:"Hash",id:"hash",level:3},{value:"Hash Rate",id:"hash-rate",level:3},{value:"See Also",id:"see-also-38",level:4},{value:"Height",id:"height",level:3},{value:"Synonyms",id:"synonyms-15",level:4},{value:"Light Client",id:"light-client",level:3},{value:"Light Node",id:"light-node",level:3},{value:"See Also",id:"see-also-39",level:4},{value:"Mempool",id:"mempool",level:3},{value:"See Also",id:"see-also-40",level:4},{value:"Metadata",id:"metadata",level:3},{value:"See Also",id:"see-also-41",level:4},{value:"Micro-State",id:"micro-state",level:3},{value:"Synonyms",id:"synonyms-16",level:4},{value:"See Also",id:"see-also-42",level:4},{value:"Miner",id:"miner",level:3},{value:"See Also",id:"see-also-43",level:4},{value:"Miner Fee",id:"miner-fee",level:3},{value:"Synonyms",id:"synonyms-17",level:4},{value:"Mining",id:"mining",level:3},{value:"See Also",id:"see-also-44",level:4},{value:"Mining Node",id:"mining-node",level:3},{value:"See Also",id:"see-also-45",level:4},{value:"Mining Reward",id:"mining-reward",level:3},{value:"See Also",id:"see-also-46",level:4},{value:"Multisig",id:"multisig",level:3},{value:"Native Token",id:"native-token",level:3},{value:"See Also",id:"see-also-47",level:4},{value:"NC-MAX",id:"nc-max",level:3},{value:"See Also",id:"see-also-48",level:4},{value:"Neighbor",id:"neighbor",level:3},{value:"See Also",id:"see-also-49",level:4},{value:"Nervos Blockchain",id:"nervos-blockchain",level:3},{value:"Synonyms",id:"synonyms-18",level:4},{value:"Nervos DAO",id:"nervos-dao",level:3},{value:"See Also",id:"see-also-50",level:4},{value:"Network Hash Rate",id:"network-hash-rate",level:3},{value:"See Also",id:"see-also-51",level:4},{value:"Node",id:"node",level:3},{value:"See Also",id:"see-also-52",level:4},{value:"Nonce",id:"nonce",level:3},{value:"See Also",id:"see-also-53",level:4},{value:"Non-Fungible Token",id:"non-fungible-token",level:3},{value:"See Also",id:"see-also-54",level:4},{value:"Open Source",id:"open-source",level:3},{value:"See Also",id:"see-also-55",level:4},{value:"P2P",id:"p2p",level:3},{value:"Synonyms",id:"synonyms-19",level:4},{value:"Paper Wallet",id:"paper-wallet",level:3},{value:"See Also",id:"see-also-56",level:4},{value:"Payment Address",id:"payment-address",level:3},{value:"Synonyms",id:"synonyms-20",level:4},{value:"Payment Channel",id:"payment-channel",level:3},{value:"See Also",id:"see-also-57",level:4},{value:"Peer to Peer",id:"peer-to-peer",level:3},{value:"Synonyms",id:"synonyms-21",level:4},{value:"See Also",id:"see-also-58",level:4},{value:"Private Key",id:"private-key",level:3},{value:"See Also",id:"see-also-59",level:4},{value:"Proof of Work",id:"proof-of-work",level:3},{value:"See Also",id:"see-also-60",level:4},{value:"Proof of Stake",id:"proof-of-stake",level:3},{value:"See Also",id:"see-also-61",level:4},{value:"Propagation",id:"propagation",level:3},{value:"Synonyms",id:"synonyms-22",level:4},{value:"Public Key",id:"public-key",level:3},{value:"See Also",id:"see-also-62",level:4},{value:"Reward",id:"reward",level:3},{value:"See Also",id:"see-also-63",level:4},{value:"Signature",id:"signature",level:3},{value:"Synonyms",id:"synonyms-23",level:4},{value:"Smart Contract",id:"smart-contract",level:3},{value:"State",id:"state",level:3},{value:"See Also",id:"see-also-64",level:4},{value:"State Bloat",id:"state-bloat",level:3},{value:"State Channel",id:"state-channel",level:3},{value:"Tip",id:"tip",level:3},{value:"Synonyms",id:"synonyms-24",level:4},{value:"Tip Block",id:"tip-block",level:3},{value:"Synonyms",id:"synonyms-25",level:4},{value:"See Also",id:"see-also-65",level:4},{value:"Transaction",id:"transaction",level:3},{value:"See Also",id:"see-also-66",level:4},{value:"Transaction Fee",id:"transaction-fee",level:3},{value:"Synonyms",id:"synonyms-26",level:4},{value:"See Also",id:"see-also-67",level:4},{value:"Token",id:"token",level:3},{value:"See Also",id:"see-also-68",level:4},{value:"Turing Complete",id:"turing-complete",level:3},{value:"UDT",id:"udt",level:3},{value:"Synonyms",id:"synonyms-27",level:4},{value:"Unconfirmed",id:"unconfirmed",level:3},{value:"Synonyms",id:"synonyms-28",level:4},{value:"See Also",id:"see-also-69",level:4},{value:"Unconfirmed Transaction",id:"unconfirmed-transaction",level:3},{value:"Synonyms",id:"synonyms-29",level:4},{value:"See Also",id:"see-also-70",level:4},{value:"User-Defined Token",id:"user-defined-token",level:3},{value:"Synonyms",id:"synonyms-30",level:4},{value:"See Also",id:"see-also-71",level:4},{value:"Wallet",id:"wallet",level:3},{value:"See Also",id:"see-also-72",level:4},{value:"Economics Glossary",id:"economics-glossary",level:2},{value:"Base Issuance",id:"base-issuance",level:3},{value:"See Also",id:"see-also-73",level:4},{value:"Base Reward",id:"base-reward",level:3},{value:"See Also",id:"see-also-74",level:4},{value:"Commit Reward",id:"commit-reward-1",level:3},{value:"See Also",id:"see-also-75",level:4},{value:"Economic Abstraction",id:"economic-abstraction",level:3},{value:"Fiat Currency",id:"fiat-currency",level:3},{value:"See Also",id:"see-also-76",level:4},{value:"Heavy Asset Problem",id:"heavy-asset-problem",level:3},{value:"See Also",id:"see-also-77",level:4},{value:"Liquidity",id:"liquidity",level:3},{value:"See Also",id:"see-also-78",level:4},{value:"Proposal Reward",id:"proposal-reward",level:3},{value:"See Also",id:"see-also-79",level:4},{value:"Secondary Issuance",id:"secondary-issuance",level:3},{value:"See Also",id:"see-also-80",level:4},{value:"Secondary Reward",id:"secondary-reward",level:3},{value:"See Also",id:"see-also-81",level:4},{value:"Selfish Mining Attack",id:"selfish-mining-attack",level:3},{value:"See Also",id:"see-also-82",level:4},{value:"Starving Layer 1 Problem",id:"starving-layer-1-problem",level:3},{value:"See Also",id:"see-also-83",level:4},{value:"State Rent",id:"state-rent",level:3},{value:"See Also",id:"see-also-84",level:4},{value:"Store of Assets",id:"store-of-assets",level:3},{value:"See Also",id:"see-also-85",level:4},{value:"Store of Value",id:"store-of-value",level:3},{value:"See Also",id:"see-also-86",level:4},{value:"Tail Emission",id:"tail-emission",level:3},{value:"See Also",id:"see-also-87",level:4},{value:"Targeted Inflation",id:"targeted-inflation",level:3},{value:"See Also",id:"see-also-88",level:4},{value:"Tragedy of the Commons",id:"tragedy-of-the-commons",level:3},{value:"See Also",id:"see-also-89",level:4},{value:"Tragedy of the Security Commons",id:"tragedy-of-the-security-commons",level:3},{value:"See Also",id:"see-also-90",level:4},{value:"Tragedy of the Storage Commons",id:"tragedy-of-the-storage-commons",level:3},{value:"See Also",id:"see-also-91",level:4},{value:"Technical Glossary",id:"technical-glossary",level:2},{value:"Active Cell",id:"active-cell",level:3},{value:"Synonyms",id:"synonyms-31",level:4},{value:"See Also",id:"see-also-92",level:4},{value:"Aggron",id:"aggron",level:3},{value:"Synonyms",id:"synonyms-32",level:4},{value:"Not To Be Confused With",id:"not-to-be-confused-with-3",level:4},{value:"Animagus",id:"animagus",level:3},{value:"See Also",id:"see-also-93",level:4},{value:"Args",id:"args",level:3},{value:"See Also",id:"see-also-94",level:4},{value:"Axon",id:"axon",level:3},{value:"See Also",id:"see-also-95",level:4},{value:"Blake2b",id:"blake2b",level:3},{value:"See Also",id:"see-also-96",level:4},{value:"Block Subsidy",id:"block-subsidy",level:3},{value:"Synonyms",id:"synonyms-33",level:4},{value:"Boxer",id:"boxer",level:3},{value:"See Also",id:"see-also-97",level:4},{value:"block_version",id:"block_version",level:3},{value:"See Also",id:"see-also-98",level:4},{value:"Cell Collection",id:"cell-collection",level:3},{value:"See Also",id:"see-also-99",level:4},{value:"Cellbase",id:"cellbase",level:3},{value:"See Also",id:"see-also-100",level:4},{value:"cellbase_maturity",id:"cellbase_maturity",level:3},{value:"See Also",id:"see-also-101",level:4},{value:"cell_deps",id:"cell_deps",level:3},{value:"See Also",id:"see-also-102",level:4},{value:"Ckbhash",id:"ckbhash",level:3},{value:"See Also",id:"see-also-103",level:4},{value:"CKB Merkle Tree",id:"ckb-merkle-tree",level:3},{value:"See Also",id:"see-also-104",level:4},{value:"Code Hash",id:"code-hash-1",level:3},{value:"See Also",id:"see-also-105",level:4},{value:"Commit",id:"commit-1",level:3},{value:"See Also",id:"see-also-106",level:4},{value:"Commitment Zone",id:"commitment-zone",level:3},{value:"See Also",id:"see-also-107",level:4},{value:"Consume",id:"consume-1",level:3},{value:"See Also",id:"see-also-108",level:4},{value:"Crypto Primitives",id:"crypto-primitives",level:3},{value:"See Also",id:"see-also-109",level:4},{value:"dao_type_hash",id:"dao_type_hash",level:3},{value:"See Also",id:"see-also-110",level:4},{value:"Data",id:"data-1",level:3},{value:"See Also",id:"see-also-111",level:4},{value:"Dead Cell",id:"dead-cell",level:3},{value:"Synonyms",id:"synonyms-34",level:4},{value:"See Also",id:"see-also-112",level:4},{value:"Dep Group",id:"dep-group",level:3},{value:"See Also",id:"see-also-113",level:4},{value:"Dep Type",id:"dep-type",level:3},{value:"See Also",id:"see-also-114",level:4},{value:"Deps",id:"deps",level:3},{value:"Synonyms",id:"synonyms-35",level:4},{value:"Dependencies",id:"dependencies",level:3},{value:"Synonyms",id:"synonyms-36",level:4},{value:"See Also",id:"see-also-115",level:4},{value:"Duktape",id:"duktape",level:3},{value:"See Also",id:"see-also-116",level:4},{value:"Difficulty",id:"difficulty",level:3},{value:"See Also",id:"see-also-117",level:4},{value:"Diviner",id:"diviner",level:3},{value:"See Also",id:"see-also-118",level:4},{value:"Eaglesong",id:"eaglesong",level:3},{value:"See Also",id:"see-also-119",level:4},{value:"epoch_duration_target",id:"epoch_duration_target",level:3},{value:"See Also",id:"see-also-120",level:4},{value:"ERC20",id:"erc20",level:3},{value:"See Also",id:"see-also-121",level:4},{value:"ERC721",id:"erc721",level:3},{value:"See Also",id:"see-also-122",level:4},{value:"ERC777",id:"erc777",level:3},{value:"See Also",id:"see-also-123",level:4},{value:"ERC1155",id:"erc1155",level:3},{value:"See Also",id:"see-also-124",level:4},{value:"Full Address",id:"full-address",level:3},{value:"See Also",id:"see-also-125",level:4},{value:"Generator",id:"generator",level:3},{value:"Genesis Block",id:"genesis-block",level:3},{value:"See Also",id:"see-also-126",level:4},{value:"genesis_hash",id:"genesis_hash",level:3},{value:"See Also",id:"see-also-127",level:4},{value:"Godwoken",id:"godwoken",level:3},{value:"See Also",id:"see-also-128",level:4},{value:"Governance Script",id:"governance-script",level:3},{value:"See Also",id:"see-also-129",level:4},{value:"Governance Script Hash",id:"governance-script-hash",level:3},{value:"Synonyms",id:"synonyms-37",level:4},{value:"See Also",id:"see-also-130",level:4},{value:"Historical Cell",id:"historical-cell",level:3},{value:"Synonyms",id:"synonyms-38",level:4},{value:"See Also",id:"see-also-131",level:4},{value:"Inbound Connection",id:"inbound-connection",level:3},{value:"See Also",id:"see-also-132",level:4},{value:"Indexer",id:"indexer",level:3},{value:"See Also",id:"see-also-133",level:4},{value:"initial_primary_epoch_reward",id:"initial_primary_epoch_reward",level:3},{value:"See Also",id:"see-also-134",level:4},{value:"Input",id:"input",level:3},{value:"See Also",id:"see-also-135",level:4},{value:"Keyper",id:"keyper",level:3},{value:"See Also",id:"see-also-136",level:4},{value:"Late Spawning",id:"late-spawning",level:3},{value:"See Also",id:"see-also-137",level:4},{value:"Layer 1",id:"layer-1",level:3},{value:"See Also",id:"see-also-138",level:4},{value:"Layer 2",id:"layer-2",level:3},{value:"See Also",id:"see-also-139",level:4},{value:"Lina",id:"lina",level:3},{value:"Synonyms",id:"synonyms-39",level:4},{value:"Not To Be Confused With",id:"not-to-be-confused-with-4",level:4},{value:"See Also",id:"see-also-140",level:4},{value:"Live Cell",id:"live-cell",level:3},{value:"Synonyms",id:"synonyms-40",level:4},{value:"See Also",id:"see-also-141",level:4},{value:"Lock",id:"lock",level:3},{value:"See Also",id:"see-also-142",level:4},{value:"Lock Script",id:"lock-script",level:3},{value:"See Also",id:"see-also-143",level:4},{value:"Lock Script Hash",id:"lock-script-hash",level:3},{value:"See Also",id:"see-also-144",level:4},{value:"Mainnet",id:"mainnet",level:3},{value:"Synonyms",id:"synonyms-41",level:4},{value:"Not To Be Confused With",id:"not-to-be-confused-with-5",level:4},{value:"max_block_bytes",id:"max_block_bytes",level:3},{value:"max_block_cycles",id:"max_block_cycles",level:3},{value:"See Also",id:"see-also-145",level:4},{value:"max_block_proposals_limit",id:"max_block_proposals_limit",level:3},{value:"See Also",id:"see-also-146",level:4},{value:"max_uncles_num",id:"max_uncles_num",level:3},{value:"See Also",id:"see-also-147",level:4},{value:"median_time_block_count",id:"median_time_block_count",level:3},{value:"Minting",id:"minting",level:3},{value:"See Also",id:"see-also-148",level:4},{value:"Molecule",id:"molecule",level:3},{value:"See Also",id:"see-also-149",level:4},{value:"Muta",id:"muta",level:3},{value:"See Also",id:"see-also-150",level:4},{value:"Nervos CKB",id:"nervos-ckb",level:3},{value:"Synonyms",id:"synonyms-42",level:4},{value:"See Also",id:"see-also-151",level:4},{value:"Off-Chain Computation",id:"off-chain-computation",level:3},{value:"See Also",id:"see-also-152",level:4},{value:"Off-Chain Scaling",id:"off-chain-scaling",level:3},{value:"See Also",id:"see-also-153",level:4},{value:"Off-Chain State",id:"off-chain-state",level:3},{value:"See Also",id:"see-also-154",level:4},{value:"On-Chain Computation",id:"on-chain-computation",level:3},{value:"See Also",id:"see-also-155",level:4},{value:"On-Chain Scaling",id:"on-chain-scaling",level:3},{value:"See Also",id:"see-also-156",level:4},{value:"On-Chain State",id:"on-chain-state",level:3},{value:"See Also",id:"see-also-157",level:4},{value:"On-Chain Verification",id:"on-chain-verification",level:3},{value:"See Also",id:"see-also-158",level:4},{value:"Open Transaction",id:"open-transaction",level:3},{value:"See Also",id:"see-also-159",level:4},{value:"Optimistic Rollup",id:"optimistic-rollup",level:3},{value:"See Also",id:"see-also-160",level:4},{value:"Orphan",id:"orphan",level:3},{value:"Synonyms",id:"synonyms-43",level:4},{value:"Orphan Block",id:"orphan-block",level:3},{value:"Synonyms",id:"synonyms-44",level:4},{value:"See Also",id:"see-also-161",level:4},{value:"Orphan Rate",id:"orphan-rate",level:3},{value:"See Also",id:"see-also-162",level:4},{value:"orphan_rate_target",id:"orphan_rate_target",level:3},{value:"See Also",id:"see-also-163",level:4},{value:"Orphan Transactions",id:"orphan-transactions",level:3},{value:"See Also",id:"see-also-164",level:4},{value:"Outbound Connection",id:"outbound-connection",level:3},{value:"See Also",id:"see-also-165",level:4},{value:"Outpoint",id:"outpoint",level:3},{value:"See Also",id:"see-also-166",level:4},{value:"Output",id:"output",level:3},{value:"See Also",id:"see-also-167",level:4},{value:"Overlord",id:"overlord",level:3},{value:"See Also",id:"see-also-168",level:4},{value:"P2WSH",id:"p2wsh",level:3},{value:"permanent_difficulty_in_dummy",id:"permanent_difficulty_in_dummy",level:3},{value:"See Also",id:"see-also-169",level:4},{value:"Polyjuice",id:"polyjuice",level:3},{value:"See Also",id:"see-also-170",level:4},{value:"primary_epoch_reward_halving_interval",id:"primary_epoch_reward_halving_interval",level:3},{value:"See Also",id:"see-also-171",level:4},{value:"Proposal Zone",id:"proposal-zone",level:3},{value:"See Also",id:"see-also-172",level:4},{value:"Propose",id:"propose",level:3},{value:"See Also",id:"see-also-173",level:4},{value:"proposer_reward_ratio",id:"proposer_reward_ratio",level:3},{value:"See Also",id:"see-also-174",level:4},{value:"RISC-V",id:"risc-v",level:3},{value:"See Also",id:"see-also-175",level:4},{value:"Schnorr Signature",id:"schnorr-signature",level:3},{value:"See Also",id:"see-also-176",level:4},{value:"Script",id:"script",level:3},{value:"See Also",id:"see-also-177",level:4},{value:"secondary_epoch_reward",id:"secondary_epoch_reward",level:3},{value:"See also",id:"see-also-178",level:4},{value:"secp256k1_blake160_sighash_all_type_hash",id:"secp256k1_blake160_sighash_all_type_hash",level:3},{value:"secp256k1_blake160_multisig_all_type_hash",id:"secp256k1_blake160_multisig_all_type_hash",level:3},{value:"Seed Cell",id:"seed-cell",level:3},{value:"See Also",id:"see-also-179",level:4},{value:"Shannon",id:"shannon",level:3},{value:"See Also",id:"see-also-180",level:4},{value:"Short Address",id:"short-address",level:3},{value:"Synonyms",id:"synonyms-45",level:4},{value:"See Also",id:"see-also-181",level:4},{value:"Simple UDT",id:"simple-udt",level:3},{value:"Synonyms",id:"synonyms-46",level:4},{value:"See Also",id:"see-also-182",level:4},{value:"Since",id:"since",level:3},{value:"See Also",id:"see-also-183",level:4},{value:"SPV",id:"spv",level:3},{value:"See Also",id:"see-also-184",level:4},{value:"SPV Wallet",id:"spv-wallet",level:3},{value:"See Also",id:"see-also-185",level:4},{value:"SUDT",id:"sudt",level:3},{value:"Synonyms",id:"synonyms-47",level:4},{value:"Testnet",id:"testnet",level:3},{value:"Synonyms",id:"synonyms-48",level:4},{value:"Not To Be Confused With",id:"not-to-be-confused-with-6",level:4},{value:"Transaction Confirmation Number",id:"transaction-confirmation-number",level:3},{value:"See Also",id:"see-also-186",level:4},{value:"Transaction Hash",id:"transaction-hash",level:3},{value:"See Also",id:"see-also-187",level:4},{value:"Transaction Witness Hash",id:"transaction-witness-hash",level:3},{value:"See Also",id:"see-also-188",level:4},{value:"Transaction Root",id:"transaction-root",level:3},{value:"See Also",id:"see-also-189",level:4},{value:"tx_proposal_window",id:"tx_proposal_window",level:3},{value:"tx_version",id:"tx_version",level:3},{value:"type_id",id:"type_id",level:3},{value:"See Also",id:"see-also-190",level:4},{value:"type_id_code_hash",id:"type_id_code_hash",level:3},{value:"See Also",id:"see-also-191",level:4},{value:"Type Script",id:"type-script",level:3},{value:"See Also",id:"see-also-192",level:4},{value:"Type Script Hash",id:"type-script-hash",level:3},{value:"See Also",id:"see-also-193",level:4},{value:"Uncle",id:"uncle",level:3},{value:"See Also",id:"see-also-194",level:4},{value:"Synonyms",id:"synonyms-49",level:4},{value:"See Also",id:"see-also-195",level:4},{value:"Uncle Rate",id:"uncle-rate",level:3},{value:"See Also",id:"see-also-196",level:4},{value:"Validator",id:"validator",level:3},{value:"See Also",id:"see-also-197",level:4},{value:"Witness",id:"witness",level:3},{value:"See Also",id:"see-also-198",level:4},{value:"Zk-SNARK",id:"zk-snark",level:3},{value:"See Also",id:"see-also-199",level:4},{value:"Zk-STARK",id:"zk-stark",level:3},{value:"See Also",id:"see-also-200",level:4}],d={toc:p};function m(e){var t=e.components,a=(0,n.Z)(e,s);return(0,i.kt)("wrapper",(0,l.Z)({},d,a,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"glossary-sections"},"Glossary Sections"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#general-glossary"},"General Glossary")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#economics-glossary"},"Economics Glossary")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#technical-glossary"},"Technical Glossary"))),(0,i.kt)("hr",null),(0,i.kt)("h2",{id:"general-glossary"},"General Glossary"),(0,i.kt)("h3",{id:"account"},"Account"),(0,i.kt)("p",null,"A kind of basic object in distributed ledger used to keep the balance and other information of users."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"address"},"Address"),(0,i.kt)("p",null,"A label consists of string of letters and numbers that anonymously represents user's identity on chain. Crypto assets can be sent to and/or from addresses."),(0,i.kt)("h4",{id:"synonyms"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#payment-address"},"Payment Address"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"asset"},"Asset"),(0,i.kt)("p",null,"A piece of data that has value or that represents an entity having value."),(0,i.kt)("h4",{id:"synonyms-1"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#digital-asset"},"Digital Asset")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"block"},"Block"),(0,i.kt)("p",null,"A grouping of transactions, marked with a timestamp, and a fingerprint of the previous block. The block header is hashed to produce a proof of work, thereby validating the transactions. Valid blocks are added to the main blockchain by network consensus."),(0,i.kt)("h4",{id:"see-also"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blockchain"},"Blockchain")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#confirmation"},"Confirmation")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"block-height"},"Block Height"),(0,i.kt)("p",null,"Block height is the total number of blocks that have been confirmed on the blockchain, also used to identify a unique block when specifying a particular block height, as there is always an exact block at any block height."),(0,i.kt)("h4",{id:"synonyms-2"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#height"},"Height"))),(0,i.kt)("h4",{id:"see-also-1"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blockchain"},"Blockchain")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#confirmation"},"Confirmation"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"block-interval"},"Block Interval"),(0,i.kt)("p",null,"Also known as ",(0,i.kt)("a",{parentName:"p",href:"#block-time"},"Block Time"),". Block interval is the length of time it takes to create a new block in a cryptocurrency blockchain. Block interval is the measure of the time it takes the miners or validators within a network to verify transactions within one block and produce a new block in that blockchain. The block interval is variable on Nervos blockchain."),(0,i.kt)("p",null,"The block interval on the Bitcoin blockchain is approximately every 10 minutes. The block interval on Nervos is variable, but is usually under 10 seconds."),(0,i.kt)("h4",{id:"synonyms-3"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block-time"},"Block Time"))),(0,i.kt)("h4",{id:"see-also-2"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blockchain"},"Blockchain"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"block-propagation"},"Block Propagation"),(0,i.kt)("p",null,"The process of synchronizing a new block to the majority of full nodes in the network. Block propagation is a well-known bottleneck that prevents Bitcoin from scaling. "),(0,i.kt)("p",null,"Block propagation time is an average time that is needed for the new block to reach the majority of nodes in the network. Long block propagation delay reduces the node's resistance against 51% attacks."),(0,i.kt)("h4",{id:"synonyms-4"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#propagation"},"Propagation"))),(0,i.kt)("h4",{id:"see-also-3"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#broadcast"},"Broadcast")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#full-node"},"Full Node"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"block-reward"},"Block Reward"),(0,i.kt)("p",null,"The amount of cryptocurrency credited to a miner's account after the miner successfully adds a block of transactions to the blockchain. "),(0,i.kt)("p",null,"In Nervos CKB, block rewards are the CKBytes credited to a miner's account after a block is successfully added to CKB by the miner."),(0,i.kt)("h4",{id:"see-also-4"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block-subsidy"},"Block Subsidy"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"block-time"},"Block Time"),(0,i.kt)("p",null,"Alternatively referred to as ",(0,i.kt)("a",{parentName:"p",href:"#block-interval"},"Block Interval"),"."),(0,i.kt)("h4",{id:"synonyms-5"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block-interval"},"Block Interval"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"blockchain"},"Blockchain"),(0,i.kt)("p",null,"A data structure maintaining a growing list of records, organized as a chain of blocks. Each block, apart from the first one, is cryptographically linked to the previous block, thus creating a chain-like structure. "),(0,i.kt)("p",null,"The cryptographic link ensures any party with the last block can verify that none of the historical data is modified after the creation of this block."),(0,i.kt)("h4",{id:"see-also-5"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"bls-signature"},"BLS Signature"),(0,i.kt)("p",null,"A cryptographic signature scheme for signing and verification. BLS is short for Boneh\u2013Lynn\u2013Shacham."),(0,i.kt)("h4",{id:"see-also-6"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Boneh%E2%80%93Lynn%E2%80%93Shacham"},"Boneh\u2013Lynn\u2013Shacham on Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"broadcast"},"Broadcast"),(0,i.kt)("p",null,"Blocks are sent to all nodes in a blockchain network."),(0,i.kt)("h4",{id:"see-also-7"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blockchain"},"Blockchain")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#node"},"Node"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"capacity"},"Capacity"),(0,i.kt)("p",null,"The maximum space (in bytes) that a cell can occupy on the Nervos CKB."),(0,i.kt)("h4",{id:"synonyms-6"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte"))),(0,i.kt)("h4",{id:"see-also-8"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckb"},"CKB")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-base"},"Common Knowledge Base")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-byte"},"Common Knowledge Byte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-blockchain"},"Nervos Blockchain"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cell"},"Cell"),(0,i.kt)("p",null,"All data on Nervos CKB is stored in cells. Cells are the primary state units in CKB, within them users can include arbitrary states. "),(0,i.kt)("p",null,"A cell has 4 fields: ",(0,i.kt)("inlineCode",{parentName:"p"},"capacity"),", ",(0,i.kt)("inlineCode",{parentName:"p"},"data"),", ",(0,i.kt)("inlineCode",{parentName:"p"},"type")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"lock"),"."),(0,i.kt)("h4",{id:"synonyms-7"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#micro-state"},"Micro-State"))),(0,i.kt)("h4",{id:"see-also-9"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#data"},"Data")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock"},"Lock")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script"},"Type Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#dead-cell"},"Dead Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#live-cell"},"Live Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)(r.Z,{to:(0,o.Z)("/docs/basics/concepts/cell-model"),mdxType:"Link"},"Cell Model in Key Concepts")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://developer.bitcoin.org/glossary.html"},"UTXO on Bitcoin.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cell-model"},"Cell Model"),(0,i.kt)("p",null,"A representation of how state is managed on Nervos CKB. The cell model is a more generic state model than either Bitcoin's UTXO or Ethereum's account model. "),(0,i.kt)("p",null,"The cell model is a new construction that combines many of the advantages of Ethereum's account model with the asset ownership and proof-based verification properties of Bitcoin's UTXO model."),(0,i.kt)("h4",{id:"see-also-10"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script"},"Type Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)(r.Z,{to:(0,o.Z)("/docs/basics/concepts/cell-model"),mdxType:"Link"},"Cell Model in Key Concepts")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://medium.com/nervosnetwork/https-medium-com-nervosnetwork-cell-model-7323fca57571"},"Cell Model on the Nervos Blog")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://developer.bitcoin.org/glossary.html"},"UTXO on Bitcoin.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"censorship-resistance"},"Censorship Resistance"),(0,i.kt)("p",null,"Censorship resistance in blockchain generally means that it is difficult for a malicious party to prevent the blockchain from confirming a set of transactions generated by honest users."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"chain"},"Chain"),(0,i.kt)("p",null,"A shorthand name for blockchain."),(0,i.kt)("h4",{id:"synonyms-8"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blockchain"},"Blockchain"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"ckb"},"CKB"),(0,i.kt)("p",null,"An abbreviation which can have different meanings depending on the context:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Common Knowledge Base - The layer 1 blockchain of the Nervos Network."),(0,i.kt)("li",{parentName:"ul"},"Common Knowledge Byte - The native token of the Nervos Common Knowledge Base.")),(0,i.kt)("h4",{id:"synonyms-9"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-base"},"Common Knowledge Base")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-byte"},"Common Knowledge Byte"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"ckbyte"},"CKByte"),(0,i.kt)("p",null,"A shorthand name for Common Knowledge Byte."),(0,i.kt)("p",null,"CKByte is also sometimes shortened to CKB. Exchanges often use CKB as the ticker symbol."),(0,i.kt)("h4",{id:"synonyms-10"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckb"},"CKB")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-byte"},"Common Knowledge Byte"))),(0,i.kt)("h4",{id:"not-to-be-confused-with"},"Not To Be Confused With"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-base"},"Common Knowledge Base"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"ckb-vm"},"CKB-VM"),(0,i.kt)("p",null,"CKB VM is a crypto-agnostic virtual machine, a RISC-V instruction set based VM for executing both on-chain and off-chain code."),(0,i.kt)("h4",{id:"see-also-11"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#risc-v"},"RISC-V")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#script"},"Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Virtual_machine"},"Virtual Machine on Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"code-hash"},"Code Hash"),(0,i.kt)("p",null,"A field in a cell which contains a hash value that can refer to a specific piece of data, or a specific cell referenced by Type ID."),(0,i.kt)("h4",{id:"see-also-12"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-id"},"Type ID"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cold-storage"},"Cold Storage"),(0,i.kt)("p",null,"A method of securing funds by placing them in a cold wallet; a type of wallet that is never connected to the internet."),(0,i.kt)("h4",{id:"see-also-13"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cold-wallet"},"Cold Wallet")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#hardware-wallet"},"Hardware Wallet")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#wallet"},"Wallet"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cold-wallet"},"Cold Wallet"),(0,i.kt)("p",null,"A wallet that is used to secure assets offline. This wallet is permanently disconnected from the internet, and not vulnerable to attacks which rely on an active internet connection."),(0,i.kt)("h4",{id:"see-also-14"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cold-storage"},"Cold Storage")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#wallet"},"Wallet"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"commit"},"Commit"),(0,i.kt)("p",null,"Nervos CKB's consensus algorithm, ",(0,i.kt)("a",{parentName:"p",href:"#nc-max"},"NC-Max")," consensus, has two phases: ",(0,i.kt)("strong",{parentName:"p"},"propose")," and ",(0,i.kt)("strong",{parentName:"p"},"commit"),". Commit is the process of including a valid proposed transaction into a new block."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"commit-chain"},"Commit-Chain"),(0,i.kt)("p",null,"A scheme that enables the off-chain processing of transactions by one or more operators with on-chain state update commitments that do not contain per-transaction data."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"commit-reward"},"Commit Reward"),(0,i.kt)("p",null,"A reward paid to miners in CKBytes on inclusion of previously proposed transactions."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"common-knowledge-base"},"Common Knowledge Base"),(0,i.kt)("p",null,"A layer 1 proof of work blockchain that provides a foundation of decentralized trust for the Nervos Network."),(0,i.kt)("h4",{id:"synonyms-11"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckb"},"CKB")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-ckb"},"Nervos CKB"))),(0,i.kt)("h4",{id:"not-to-be-confused-with-1"},"Not To Be Confused With"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-byte"},"Common Knowledge Byte"))),(0,i.kt)("h4",{id:"see-also-15"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://www.nervos.org/ckb/"},"Nervos CKB on Nervos.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"common-knowledge-byte"},"Common Knowledge Byte"),(0,i.kt)("p",null,"The native token of the Nervos layer 1 blockchain, the Common Knowledge Base."),(0,i.kt)("p",null,"Common Knowledge Byte is often abbreviated as CKByte or CKB."),(0,i.kt)("p",null,"Owning a CKByte entitles the holder to store one byte of data on the Nervos CKB blockchain."),(0,i.kt)("h4",{id:"synonyms-12"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckb"},"CKB")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte"))),(0,i.kt)("h4",{id:"not-to-be-confused-with-2"},"Not To Be Confused With"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-base"},"Common Knowledge Base"))),(0,i.kt)("h4",{id:"see-also-16"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#capacity"},"Capacity")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-ckb"},"Nervos CKB")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#shannon"},"Shannon"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"confirmation"},"Confirmation"),(0,i.kt)("p",null,"A process where a transaction has been accepted and verified by the network and included in a block."),(0,i.kt)("h4",{id:"see-also-17"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#unconfirmed"},"Unconfirmed"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"consensus"},"Consensus"),(0,i.kt)("p",null,"An algorithm executed among a number of distributed participants, ensuring that all participants faithfully executing this algorithm can reach agreement on some data value even if the other participants are faulty or malicious."),(0,i.kt)("h4",{id:"see-also-18"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nc-max"},"NC-MAX"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"consume"},"Consume"),(0,i.kt)("p",null,"The process of using a live cell as an input to a transaction. The consumption processes indicate that live cell turns into a dead cell."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"contract-account"},"Contract Account"),(0,i.kt)("p",null,"An account containing code that executes automatically whenever it receives an event from another account."),(0,i.kt)("h4",{id:"see-also-19"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#account"},"Account"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cryptocurrency"},"Cryptocurrency"),(0,i.kt)("p",null,"A cryptocurrency is a digital or virtual currency that is secured by blockchain and cryptography, which makes it nearly impossible to counterfeit or double-spend."),(0,i.kt)("h4",{id:"see-also-20"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#digital-currency"},"Digital Currency")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#fiat-currency"},"Fiat Currency"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cryptographic-signature"},"Cryptographic Signature"),(0,i.kt)("p",null,"A concise piece of proof data. Cryptographic signature schemes are a fundamental component of cryptocurrency networks that verify the integrity and non-repudiation of transaction messages across the network."),(0,i.kt)("h4",{id:"synonyms-13"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#private-key"},"Private Key")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#signature"},"Signature"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cryptography"},"Cryptography"),(0,i.kt)("p",null,"Cryptography is the practice and study of techniques for secure communication in the presence of adversarial behavior."),(0,i.kt)("h4",{id:"see-also-21"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Cryptography"},"Cryptography at Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cycles"},"Cycles"),(0,i.kt)("p",null,"The number of RISC-V computational cycles required by a script to execute. It's a metric used to prevent malicious behavior such as infinite loops, that's why it is called cycles. "),(0,i.kt)("p",null,"This is a similar concept to Ethereum's Gas, we set cycles to ensure optimal performance and security. Scripts must stay within cycle limits, otherwise the block will be rejected by CKB nodes."),(0,i.kt)("h4",{id:"see-also-22"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://docs.nervos.org/docs/essays/faq/#estimate-cycles"},"Estimate cycles")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#max_block_cycles"},"Max_block_cycles")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0014-vm-cycle-limits/0014-vm-cycle-limits.md"},"Rules for calculating cycles in RFC on Nervos Network Github")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#script"},"Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#risc-v"},"RISC-V")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://ethereum.org/en/glossary/#gas"},"Ethereum's Gas"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"dao"},"DAO"),(0,i.kt)("p",null,"A decentralized autonomous organization (DAO) is an organization represented by rules encoded as a computer program that is transparent, controlled by the organization members and not influenced by a centralized entity, in other words they are member-owned communities without centralized leadership. A DAO's financial transaction record and program rules are maintained on a blockchain."),(0,i.kt)("h4",{id:"see-also-23"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Decentralized_autonomous_organization"},"DAO on Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"dapp"},"DApp"),(0,i.kt)("p",null,"Decentralized application. At a minimum, it is a smart contract and a web user interface. In a broader sense, DApps are web applications that are built on top of open, decentralized, peer-to-peer infrastructure services. Additionally, many DApps include decentralized storage and/or a message protocol and platform."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"data"},"Data"),(0,i.kt)("p",null,"In cell model, ",(0,i.kt)("inlineCode",{parentName:"p"},"data")," is a field in a cell which can store arbitrary bytes."),(0,i.kt)("h4",{id:"see-also-24"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell-model"},"Cell Model"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"decentralization"},"Decentralization"),(0,i.kt)("p",null,"In blockchain, decentralization refers to the transfer of control and decision-making from a centralized entity (individual, organization, or group thereof) to a distributed network."),(0,i.kt)("h4",{id:"see-also-25"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#distributed"},"Distributed")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Decentralization"},"Decentralization on Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"defi"},"DeFi"),(0,i.kt)("p",null,'Short for "decentralized finance", a broad category of DApps aiming to provide financial services backed by the blockchain, without any intermediaries, so anyone with an internet connection can participate.'),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"digital-asset"},"Digital Asset"),(0,i.kt)("p",null,"A digital asset is an individual piece of data that has value, or represents another entity that has value."),(0,i.kt)("p",null,"Digital assets are most commonly represented as tokens, which may be used as digital currency or represent physical items such as real estate."),(0,i.kt)("h4",{id:"synonyms-14"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#asset"},"Asset")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"digital-currency"},"Digital Currency"),(0,i.kt)("p",null,"A type of currency that primarily exists digitally over the internet. Physical representations of the currency, in the form of cards, bills, or coins, may exist, but are secondary mediums."),(0,i.kt)("h4",{id:"see-also-26"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cryptocurrency"},"Cryptocurrency"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"distributed"},"Distributed"),(0,i.kt)("p",null,"A system where components are spread across multiple nodes to parallelize workloads, add redundancy, or eliminate single points of failure."),(0,i.kt)("h4",{id:"see-also-27"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#decentralization"},"Decentralization"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"double-spending"},"Double-Spending"),(0,i.kt)("p",null,"Double-spending is the risk that a digital token is spent twice or more. In the context of blockchain, it happens when the transaction spending a digital token is cancelled after confirmation, and the same token is spent in another transaction."),(0,i.kt)("h4",{id:"see-also-28"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#confirmation"},"Confirmation")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cryptocurrency"},"Cryptocurrency")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"epoch"},"Epoch"),(0,i.kt)("p",null,"An epoch is a period of time for a set of blocks. "),(0,i.kt)("p",null,"In Nervos, the PoW difficulty changes on a new epoch. All the blocks in the same epoch share the same difficulty target. The difficulty adjustment algorithm aims to stabilize the orphan block rate at 2.5% and the epoch duration at 4 hours."),(0,i.kt)("h4",{id:"see-also-29"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"fee"},"Fee"),(0,i.kt)("p",null,"The sender of a transaction often includes a fee to the network for processing the requested transaction. There's no minimum fee rate set in consensus, but there's a minimum fee rate 1,000 Shannons/KB in CKB's ",(0,i.kt)("a",{parentName:"p",href:"#p2p"},"P2P")," network. (1 Shannon = 10",(0,i.kt)("sup",null,"-8")," CKB)"),(0,i.kt)("h4",{id:"see-also-30"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#shannon"},"Shannon")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#fee-rate"},"Fee rate")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/ckb/tree/develop/rpc#error-poolrejectedtransactionbyminfeerate"},"Fee rate in RFC on Nervos Network Github"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"fee-rate"},"Fee Rate"),(0,i.kt)("p",null,"A tip per byte that a user offers to the miners for including his transaction in a block on the blockchain."),(0,i.kt)("p",null,"This is a same concept to Bitcoin's ",(0,i.kt)("a",{parentName:"p",href:"https://en.bitcoin.it/wiki/Miner_fees#Feerates"},"Fee Rate(often spelled feerate)"),"."),(0,i.kt)("h4",{id:"see-also-31"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#fee"},"Fee"))),(0,i.kt)("h3",{id:"first-class-assets"},"First-Class Assets"),(0,i.kt)("p",null,"Assets that 1. the asset itself (rather than a reference to the asset) can be passed directly in smart contract interactions, and 2. directly controlled by owners without any intermediaries. "),(0,i.kt)("h4",{id:"see-also-32"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://medium.com/nervosnetwork/first-class-asset-ff4feaf370c4"},"First-Class Asset")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://talk.nervos.org/t/first-class-asset/1293"},"Introduction to First-Class Asset"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"fork"},"Fork"),(0,i.kt)("p",null,"A change in protocol causing the creation of an alternative chain, or a temporal divergence in two potential block paths during mining."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"full-node"},"Full Node"),(0,i.kt)("p",null,"A full node is an essential component of the CKB network. It stores and syncs the entire blockchain, verifies the validity of blocks and transactions, and enforces the network's consensus rules."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"ckb init --chain mainnet && ckb run\n")),(0,i.kt)("h4",{id:"see-also-33"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#node"},"Node")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#light-node"},"Light Node")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mining-node"},"Mining Node"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"full-payload-format"},"Full Payload Format"),(0,i.kt)("p",null,"The deprecated full payload format directly encodes all data field of lock script. The encode rule of deprecated full payload format is ",(0,i.kt)("a",{parentName:"p",href:"https://en.bitcoin.it/wiki/Bech32"},"Bech32"),"."),(0,i.kt)("h4",{id:"see-also-34"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"fungible-token"},"Fungible Token"),(0,i.kt)("p",null,"A fungible token can be fiat currencies like the dollar or a cryptocurrency like Bitcoin. "),(0,i.kt)("p",null,"Fungible tokens or assets are divisible and non-unique."),(0,i.kt)("h4",{id:"see-also-35"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#non-fungible-token"},"Non-Fungible Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#user-defined-token"},"User-Defined Token"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"gas-limit"},"Gas Limit"),(0,i.kt)("p",null,"The maximum amount of gas a transaction or block may consume."),(0,i.kt)("h4",{id:"see-also-36"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://ethereum.org/en/glossary/#gas"},"Ethereum's Gas"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"hard-fork"},"Hard-Fork"),(0,i.kt)("p",null,"A permanent divergence in the blockchain; also known as a hard-forking change. One commonly occurs when nonupgraded nodes can\u2019t validate blocks created by upgraded nodes that follow newer consensus rules. Not to be confused with a fork, soft fork, software fork, or Git fork."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"hardware-wallet"},"Hardware Wallet"),(0,i.kt)("p",null,"A hardware wallet is a form of cold wallet. A hardware wallet is a cryptocurrency wallet that stores the user's private keys (a critical piece of information used to authorize outgoing transactions on the blockchain network) in a secure hardware device."),(0,i.kt)("h4",{id:"see-also-37"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cold-storage"},"Cold Storage")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cold-wallet"},"Cold Wallet")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#private-key"},"Private Key")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#wallet"},"Wallet"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"hash"},"Hash"),(0,i.kt)("p",null,"A fixed-length fingerprint of variable-size input, produced by a hash function."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"hash-rate"},"Hash Rate"),(0,i.kt)("p",null,'Hash rate is a measure of the computational power per second used when mining. These operations are known as "hashing".'),(0,i.kt)("h4",{id:"see-also-38"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#miner"},"Miner")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#network-hash-rate"},"Network Hash Rate"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"height"},"Height"),(0,i.kt)("p",null,"A shorthand name for block height."),(0,i.kt)("h4",{id:"synonyms-15"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block-height"},"Block Height"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"light-client"},"Light Client"),(0,i.kt)("p",null,"As a low-resource node, a light client allows users to sync with a blockchain in a cryptographically secure manner without having to store the whole blockchain."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"light-node"},"Light Node"),(0,i.kt)("p",null,"A light node downloads only the headers of the blockchain, conserving resources. It relies on other nodes for full transaction data and is a lightweight option for network participation."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"ckb-light-client run --config-file ./testnet.toml\n")),(0,i.kt)("h4",{id:"see-also-39"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#node"},"Node")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#full-node"},"Full Node")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mining-node"},"Mining Node"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"mempool"},"Mempool"),(0,i.kt)("p",null,'Short for "memory pool". A waiting area on full nodes for transactions that have been broadcasted to the network but have not yet been confirmed on the blockchain.'),(0,i.kt)("h4",{id:"see-also-40"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#confirmation"},"Confirmation")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"metadata"},"Metadata"),(0,i.kt)("p",null,"Metadata is data that provides information about other data. ",(0,i.kt)("inlineCode",{parentName:"p"},"capacity"),", ",(0,i.kt)("inlineCode",{parentName:"p"},"type")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"lock")," in cells are metadata, they occupy cell capacity and incur a state cost as well."),(0,i.kt)("h4",{id:"see-also-41"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#capacity"},"Capacity")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock"},"Lock")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script"},"Type Script"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"micro-state"},"Micro-State"),(0,i.kt)("p",null,"A small piece of state that is isolated and often able to be acted upon independently without knowing the total state of the network."),(0,i.kt)("p",null,"On Nervos, micro-state is represented by a Cell."),(0,i.kt)("h4",{id:"synonyms-16"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell"))),(0,i.kt)("h4",{id:"see-also-42"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#state"},"State"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"miner"},"Miner"),(0,i.kt)("p",null,"A network node that finds valid proof of work for new blocks, by repeated hashing."),(0,i.kt)("h4",{id:"see-also-43"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proof-of-work"},"Proof of Work"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"miner-fee"},"Miner Fee"),(0,i.kt)("p",null,"Another term for transaction fee."),(0,i.kt)("h4",{id:"synonyms-17"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction-fee"},"Transaction Fee"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"mining"},"Mining"),(0,i.kt)("p",null,"Mining is the process by which a blockchain node get new token reward by verifying new transactions, finding valid proof of work and creating new blocks."),(0,i.kt)("h4",{id:"see-also-44"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blockchain"},"Blockchain")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mining-reward"},"Mining Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proof-of-work"},"Proof of Work"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"mining-node"},"Mining Node"),(0,i.kt)("p",null,"Mining nodes create new blocks by solving computational puzzles. They contribute to the network's security and consensus by actively validating and adding blocks to the blockchain."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"ckb init --chain mainnet && ckb miner\n")),(0,i.kt)("h4",{id:"see-also-45"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#consensus"},"Consensus")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#miner"},"Miner")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mining"},"Mining")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proof-of-work"},"Proof of Work")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#full-node"},"Full Node")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#light-node"},"Light Node"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"mining-reward"},"Mining Reward"),(0,i.kt)("p",null,"Native tokens paid to miners as a reward for providing the necessary computing resources for mining."),(0,i.kt)("h4",{id:"see-also-46"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#miner"},"Miner")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mining"},"Mining")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#native-token"},"Native Token"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"multisig"},"Multisig"),(0,i.kt)("p",null,"The term multisig stands for multi-signature, which is a specific type of digital signatures that can be created through the combination of multiple unique signatures."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"native-token"},"Native Token"),(0,i.kt)("p",null,"The token issued as reward to a blockchain's consensus nodes. Nervos CKB's native token is CKByte."),(0,i.kt)("h4",{id:"see-also-47"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"nc-max"},"NC-MAX"),(0,i.kt)("p",null,"Nervos CKB's consensus algorithm, which follows NC's backbone protocol. The main innovation here is a two-step transaction confirmation mechanism"),(0,i.kt)("h4",{id:"see-also-48"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#consensus"},"Consensus")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-blockchain"},"Nervos Blockchain")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://eprint.iacr.org/2020/1101"},"NC-MAC"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"neighbor"},"Neighbor"),(0,i.kt)("p",null,"A node that is directly connected to another node in the blockchain peer to peer network."),(0,i.kt)("h4",{id:"see-also-49"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#node"},"Node")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#peer-to-peer"},"Peer to Peer"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"nervos-blockchain"},"Nervos Blockchain"),(0,i.kt)("p",null,"The layer 1 blockchain of the Nervos Network known as the Common Knowledge Base."),(0,i.kt)("h4",{id:"synonyms-18"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-base"},"Common Knowledge Base")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#layer-1"},"Layer 1")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-ckb"},"Nervos CKB"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"nervos-dao"},"Nervos DAO"),(0,i.kt)("p",null,'Nervos DAO enable users to lock CKBytes to get compensation from Nervos CKB secondary issuance. This process is similar to staking on other platforms. Nervos DAO provides a "virtual hardcap" for CKByte holders to insulate them from inflation.'),(0,i.kt)("h4",{id:"see-also-50"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#dao"},"DAO")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#secondary-issuance"},"Secondary Issuance")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://medium.com/nervosnetwork/nervos-dao-explained-95e33898b1c"},"Nervos DAO Explained on the Nervos Blog")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0015-ckb-cryptoeconomics/0015-ckb-cryptoeconomics.md"},"Nervos DAO in RFC on Nervos Network Github")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://explorer.nervos.org/charts/inflation-rate"},"Inflation Rate Chart"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"network-hash-rate"},"Network Hash Rate"),(0,i.kt)("p",null,"A measurement of the total computational processing power which is dedicated to providing security to the network."),(0,i.kt)("h4",{id:"see-also-51"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#hash-rate"},"Hash Rate")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#miner"},"Miner"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"node"},"Node"),(0,i.kt)("p",null,"A software client that participates in the network."),(0,i.kt)("h4",{id:"see-also-52"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#full-node"},"Full Node")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#light-node"},"Light Node")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mining-node"},"Mining Node"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"nonce"},"Nonce"),(0,i.kt)("p",null,"In cryptography, a value that can only be used once. Nonce can refer to two things in blockchain context: 1. a proof-of-work nonce is the random value in a block satisfying the proof of work requirement; 2. an account nonce is a transaction counter in each account, which is used to prevent replay attacks."),(0,i.kt)("h4",{id:"see-also-53"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proof-of-work"},"Proof of Work"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"non-fungible-token"},"Non-Fungible Token"),(0,i.kt)("p",null,"Non-fungible tokens or NFTs are cryptographic assets on a blockchain with unique identification codes and metadata that distinguish them from each other."),(0,i.kt)("h4",{id:"see-also-54"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#fungible-token"},"Fungible Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#user-defined-token"},"User-Defined Token"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"open-source"},"Open Source"),(0,i.kt)("p",null,"A piece of software where source code is freely available for examination or alteration by any third-party."),(0,i.kt)("h4",{id:"see-also-55"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://opensource.com/resources/what-open-source"},"What is Open Source at OpenSource.com"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"p2p"},"P2P"),(0,i.kt)("p",null,"A shortname name for peer to peer."),(0,i.kt)("h4",{id:"synonyms-19"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#peer-to-peer"},"Peer to Peer"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"paper-wallet"},"Paper Wallet"),(0,i.kt)("p",null,"A form of storing a recovery phrase or private keys offline by printing them on a piece of paper. This document would then be stored by traditional means in a secured location of the user's choosing, such as a safe."),(0,i.kt)("h4",{id:"see-also-56"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#private-key"},"Private Key")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#wallet"},"Wallet"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"payment-address"},"Payment Address"),(0,i.kt)("p",null,"A string of letters and numbers that cryptocurrency and assets can be sent to and from. "),(0,i.kt)("p",null,'Nervos CKB mainnet addresses always begin with the prefix "ckb".'),(0,i.kt)("h4",{id:"synonyms-20"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#address"},"Address"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"payment-channel"},"Payment Channel"),(0,i.kt)("p",null,"A micropayment channel or payment channel is class of techniques designed to allow users to make multiple payment transactions without committing all of the transactions to the layer 1 blockchain. In a typical payment channel, only two transactions are added to the block chain but an unlimited or nearly unlimited number of payments can be made between the participants."),(0,i.kt)("h4",{id:"see-also-57"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#layer-1"},"Layer 1"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"peer-to-peer"},"Peer to Peer"),(0,i.kt)("p",null,"A peer-to-peer (P2P) service is a decentralized platform whereby two individuals interact directly with each other, without intermediation by a third party."),(0,i.kt)("h4",{id:"synonyms-21"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#p2p"},"P2P"))),(0,i.kt)("h4",{id:"see-also-58"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#node"},"Node"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"private-key"},"Private Key"),(0,i.kt)("p",null,"A private key, also known as a secret key, is a variable in cryptography, known only to the owner(s) of the key, that is used with an algorithm to encrypt and decrypt data."),(0,i.kt)("h4",{id:"see-also-59"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#digital-asset"},"Digital Asset")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#paper-wallet"},"Paper Wallet")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#payment-address"},"Payment Address")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#wallet"},"Wallet"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"proof-of-work"},"Proof of Work"),(0,i.kt)("p",null,"PoW asks users to solve a cryptographic puzzle to prove ownershipo of a certain amount of computational resource to participate in the consensus. In general PoW is a more permissionless consensus mechanism than PoS. "),(0,i.kt)("p",null,'In contrast to wildly spread misconception, PoW is not a "waste" of energy and does not induce more carbon emission. PoW is used in the Nervos layer 1 blockchain CKB.'),(0,i.kt)("h4",{id:"see-also-60"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#consensus"},"Consensus")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mining-reward"},"Mining Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proof-of-stake"},"Proof of Stake")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"proof-of-stake"},"Proof of Stake"),(0,i.kt)("p",null,"PoS asks users to prove ownership of a certain amount of cryptocurrency (their \u201cstake\u201d in the network) in order to be able to participate in the consensus. PoS relies on weak-subjectivity due to unsolvable issues like long-range attack. In PoS system the future consensus quorum is decided by existing participants completely. PoS is used in layer 2 protocols on Nervos Network."),(0,i.kt)("h4",{id:"see-also-61"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#consensus"},"Consensus")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mining-reward"},"Mining Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proof-of-work"},"Proof of Work")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"propagation"},"Propagation"),(0,i.kt)("p",null,"A shorthand name for Block Propagation."),(0,i.kt)("h4",{id:"synonyms-22"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block-propagation"},"Block Propagation"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"public-key"},"Public Key"),(0,i.kt)("p",null,"A notion used only in public-key cryptography, a.k.a. asymmetric cryptography. A public key is a piece of information that can be known to others without compromising security. Unique for each user, a public key is associated with a private key known only to the user. The public key can be used to encrypt a message so that it can only be decrypted with the corresponding private key, or to verify that a message is authorized by the user with the corresponding private key."),(0,i.kt)("h4",{id:"see-also-62"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#private-key"},"Private Key"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"reward"},"Reward"),(0,i.kt)("p",null,"An amount of CKBytes included in each new block as a reward by the network to the miner who found the proof-of-work solution."),(0,i.kt)("h4",{id:"see-also-63"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#base-reward"},"Base Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block-reward"},"Block Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#commit-reward"},"Commit Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mining-reward"},"Mining Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proposal-reward"},"Proposal Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#secondary-reward"},"Secondary Reward"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"signature"},"Signature"),(0,i.kt)("p",null,"A shorthand name for cryptographic signature."),(0,i.kt)("h4",{id:"synonyms-23"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cryptographic-signature"},"Cryptographic Signature"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"smart-contract"},"Smart Contract"),(0,i.kt)("p",null,"A smart contract is a self-executing contract with the terms of the agreement between contract creators and contract users being directly written into lines of code. The code and the agreements contained therein exist across a distributed, decentralized blockchain network. Also known as script on Nervos CKB. "),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"state"},"State"),(0,i.kt)("p",null,"Data stored on the blockchain. In most contexts this this means current data and excludes historical data."),(0,i.kt)("h4",{id:"see-also-64"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blockchain"},"Blockchain"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"state-bloat"},"State Bloat"),(0,i.kt)("p",null,"The unlimited increase of state data in Ethereum. State bloat slows down node synchronization, raises the barrier of full node, thus hurts network decentralization."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"state-channel"},"State Channel"),(0,i.kt)("p",null,"A layer 2 solution where a channel is set up between participants, where they can transact freely and cheaply. Only a transaction to set up the channel and close the channel is sent to mainnet. This allows for very high transaction throughput, but does rely on knowing number of participants up front and locking up of funds."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"tip"},"Tip"),(0,i.kt)("p",null,"A shorthand name for tip block."),(0,i.kt)("h4",{id:"synonyms-24"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#tip-block"},"Tip Block"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"tip-block"},"Tip Block"),(0,i.kt)("p",null,"The most recent block to be confirmed in a blockchain. The tip block has the highest block height in the blockchain."),(0,i.kt)("h4",{id:"synonyms-25"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#tip"},"Tip"))),(0,i.kt)("h4",{id:"see-also-65"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block-height"},"Block Height")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blockchain"},"Blockchain"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"transaction"},"Transaction"),(0,i.kt)("p",null,"Transaction is the basic object created and signed by users to interact with distributed ledger. Transactions update ledger state at users requests. A CKB transaction destroys some outputs created in previous transactions and creates some new outputs. We call the transaction output a cell in CKB."),(0,i.kt)("h4",{id:"see-also-66"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blockchain"},"Blockchain")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-blockchain"},"Nervos Blockchain"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"transaction-fee"},"Transaction Fee"),(0,i.kt)("p",null,"A fee which is paid in the native token to miners in exchange for processing a transaction."),(0,i.kt)("h4",{id:"synonyms-26"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#miner-fee"},"Miner Fee"))),(0,i.kt)("h4",{id:"see-also-67"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#miner"},"Miner")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#native-token"},"Native Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"token"},"Token"),(0,i.kt)("p",null,"A \u201ctoken\u201d often refers to non-native token on smart contract platform, such as UDT on Nervos Network or ERC20 on Ethereum."),(0,i.kt)("h4",{id:"see-also-68"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blockchain"},"Blockchain")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#digital-asset"},"Digital Asset")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"turing-complete"},"Turing Complete"),(0,i.kt)("p",null,"Turing Complete refers to a machine that, given enough time and memory along with the necessary instructions, can solve any computational problem, no matter how complex. The term is normally used to describe modern programming languages as most of them are Turing Complete (C++, Python, JavaScript, etc.)."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"udt"},"UDT"),(0,i.kt)("p",null,"Short for User-Defined Token, a customised token created with properties defined by the user. In normal usage, this most commonly refers to fungible tokens."),(0,i.kt)("h4",{id:"synonyms-27"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#user-defined-token"},"User-Defined Token"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"unconfirmed"},"Unconfirmed"),(0,i.kt)("p",null,"The state of a transaction that has not yet been confirmed. An unconfirmed transaction is not finalized and cannot be guaranteed."),(0,i.kt)("h4",{id:"synonyms-28"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#unconfirmed-transaction"},"Unconfirmed Transaction"))),(0,i.kt)("h4",{id:"see-also-69"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#confirmation"},"Confirmation")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"unconfirmed-transaction"},"Unconfirmed Transaction"),(0,i.kt)("p",null,"A transaction that has not yet been confirmed. An unconfirmed transaction is not finalized and cannot be guaranteed."),(0,i.kt)("h4",{id:"synonyms-29"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#unconfirmed"},"Unconfirmed"))),(0,i.kt)("h4",{id:"see-also-70"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#confirmation"},"Confirmation")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"user-defined-token"},"User-Defined Token"),(0,i.kt)("p",null,"A custom token created with properties defined by the user. In normal usage, this most commonly refers to fungible tokens."),(0,i.kt)("p",null,"A User-Defined Token is usually referred to by its abbreviation, UDT."),(0,i.kt)("h4",{id:"synonyms-30"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#fungible-token"},"Fungible Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#udt"},"UDT"))),(0,i.kt)("h4",{id:"see-also-71"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://eips.ethereum.org/EIPS/eip-20"},"ERC20 on Ethereum.org")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://eips.ethereum.org/EIPS/eip-777"},"ERC777 on Ethereum.org")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://talk.nervos.org/t/rfc-simple-udt-draft-spec/4333"},"Simple UDT Draft Spec on Nervos Talk"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"wallet"},"Wallet"),(0,i.kt)("p",null,"User-facing software used to interact with on-chain entities such as assets, smart contracts and dapps. A wallet can include key management itself or delegate key management to external hardware for improved security."),(0,i.kt)("h4",{id:"see-also-72"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#paper-wallet"},"Paper Wallet")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#private-key"},"Private Key")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#payment-address"},"Payment Address")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#digital-asset"},"Digital Asset"))),(0,i.kt)("hr",null),(0,i.kt)("h2",{id:"economics-glossary"},"Economics Glossary"),(0,i.kt)("h3",{id:"base-issuance"},"Base Issuance"),(0,i.kt)("p",null,"Base issuance is the basic CKByte issuance with a fixed and decreasing schedule. Base issuance is awarded to miners as incentives to protect the network and also as an indirect token distribution method."),(0,i.kt)("p",null,"Base issuance is limited to a finite total supply 33.6G (33.6 billion) CKBytes. "),(0,i.kt)("h4",{id:"see-also-73"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#base-reward"},"Base Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#secondary-issuance"},"Secondary Issuance")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#miner"},"Miner")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0015-ckb-cryptoeconomics/0015-ckb-cryptoeconomics.md"},"Crypto-Economics RFC on Nervos Network GitHub"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"base-reward"},"Base Reward"),(0,i.kt)("p",null,"Base reward is the block reward (in CKBytes) to miners generated from the base issuance. Base reward halves approximately every 4 years until eventually reaching 0, like Bitcoin."),(0,i.kt)("h4",{id:"see-also-74"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#base-issuance"},"Base Issuance")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#miner"},"Miner")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"commit-reward-1"},"Commit Reward"),(0,i.kt)("p",null,"A reward paid to miners in CKBytes for committing a previously proposed transaction. After the transaction has been committed it is confirmed."),(0,i.kt)("h4",{id:"see-also-75"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#confirmation"},"Confirmation")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#miner"},"Miner")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"economic-abstraction"},"Economic Abstraction"),(0,i.kt)("p",null,'With proper tool support, users can use tokens other than CKByte (for example, stable coins) to pay transactions fees, a concept known as "Economic Abstraction".'),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"fiat-currency"},"Fiat Currency"),(0,i.kt)("p",null,"Fiat currencies are a medium of exchange established as money, often by government regulation. Fiat money does not have intrinsic value and does not have use value. It has value only because a government maintains its value, or because parties engaging in exchange agree on its value."),(0,i.kt)("h4",{id:"see-also-76"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cryptocurrency"},"Cryptocurrency")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#digital-currency"},"Digital Currency"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"heavy-asset-problem"},"Heavy Asset Problem"),(0,i.kt)("p",null,"A common problem found in multi-asset blockchain platforms where the value of the assets stored on the chain gains significant value but the native token of the chain does not. This raises the incentive to attack the the network, but does not increase the security because the value of the native token is what is used to secure the network."),(0,i.kt)("h4",{id:"see-also-77"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#asset"},"Asset")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#starving-layer-1-problem"},"Starving Layer 1 Problem")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#tragedy-of-the-security-commons"},"Tragedy of the Security Commons"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"liquidity"},"Liquidity"),(0,i.kt)("p",null,"The ability for an asset to be bought or sold easily without causing a significant change in the current market price."),(0,i.kt)("h4",{id:"see-also-78"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#asset"},"Asset"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"proposal-reward"},"Proposal Reward"),(0,i.kt)("p",null,"A reward paid to miners in CKBytes for proposing an unconfirmed transaction."),(0,i.kt)("h4",{id:"see-also-79"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#confirmation"},"Confirmation")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#miner"},"Miner")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"secondary-issuance"},"Secondary Issuance"),(0,i.kt)("p",null,"The creation of new CKBytes that is paid to miners through secondary rewards. Secondary issuance follows a fixed inflation schedule of 1.344 billion CKBytes per year. Nervos DAO stakers are not affected by secondary issuance."),(0,i.kt)("h4",{id:"see-also-80"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#base-issuance"},"Base Issuance")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-dao"},"Nervos DAO")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#secondary-reward"},"Secondary Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#state"},"State")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0015-ckb-cryptoeconomics/0015-ckb-cryptoeconomics.md"},"Crypto-Economics RFC on Nervos Network GitHub"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"secondary-reward"},"Secondary Reward"),(0,i.kt)("p",null,"A subsidy paid to miners in CKBytes for providing the compute and storage requirements required for processing transactions and persisting data on Nervos."),(0,i.kt)("p",null,"Secondary rewards are created from secondary issuance, and continuously pay miners for the verification of transactions and preservation of blockchain state."),(0,i.kt)("h4",{id:"see-also-81"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#miner"},"Miner")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#secondary-issuance"},"Secondary Issuance")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"selfish-mining-attack"},"Selfish Mining Attack"),(0,i.kt)("p",null,"Selfish mining is a concept that was addressed by Cornell University researchers in detail in a 2013 report. In this attack, malicious miners gain unfair block rewards by deliberately orphaning blocks mined by others."),(0,i.kt)("h4",{id:"see-also-82"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf"},"Selfish Mining Related Paper"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"starving-layer-1-problem"},"Starving Layer 1 Problem"),(0,i.kt)("p",null,"A scenario that can arise in multi-layer blockchain platforms where the vast majority of the transaction traffic moves from layer 1 to layer 2, taking the vast majority of transaction fees with it. If layer 1 relies exclusively on transaction fees to support the security of the platform, it may end up not having enough incentives available to properly secure it."),(0,i.kt)("h4",{id:"see-also-83"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#heavy-asset-problem"},"Heavy Asset Problem")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#layer-1"},"Layer 1")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#layer-2"},"Layer 2")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction-fee"},"Transaction Fee"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"state-rent"},"State Rent"),(0,i.kt)("p",null,"A recurring fee that is paid to persist and secure state data. "),(0,i.kt)("p",null,"On Nervos, secondary issuance is used to boost the payment of state rent by users who occupy space on the Nervos blockchain."),(0,i.kt)("h4",{id:"see-also-84"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#secondary-issuance"},"Secondary Issuance")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-blockchain"},"Nervos Blockchain")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0015-ckb-cryptoeconomics/0015-ckb-cryptoeconomics.md"},"Crypto-Economics RFC on Nervos Network GitHub"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"store-of-assets"},"Store of Assets"),(0,i.kt)("p",null,'Similar to the concept of "Store of Value" in the context of Bitcoin, we call the utility "Store of Assets" when a blockchain keeps any crypto-assets securely and censorship-resistantly. Nervos CKB is such a Store of Assets or SoA.'),(0,i.kt)("h4",{id:"see-also-85"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#store-of-value"},"Store of Value"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"store-of-value"},"Store of Value"),(0,i.kt)("p",null,"Assets which can maintain their worth over time without depreciating"),(0,i.kt)("p",null,"A good store of value either match or outpace the inflation rate of fiat currency, and has a reasonable amount of liquidity, allowing the asset to be easily sold."),(0,i.kt)("h4",{id:"see-also-86"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#store-of-assets"},"Store of Assets")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#liquidity"},"Liquidity"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"tail-emission"},"Tail Emission"),(0,i.kt)("p",null,"A type of reward that is paid to miners through a fixed amount of inflation."),(0,i.kt)("h4",{id:"see-also-87"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#secondary-reward"},"Secondary Reward"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"targeted-inflation"},"Targeted Inflation"),(0,i.kt)("p",null,"A form of inflation that only affects a specific subset of users."),(0,i.kt)("p",null,"Nervos uses Secondary Issuance to create targeted inflation on users who occupy space on the Nervos blockchain to pay State Rent. Long-term holders of CKBytes have the option of locking them in the Nervos DAO, which acts and an inflation shelter."),(0,i.kt)("h4",{id:"see-also-88"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#secondary-issuance"},"Secondary Issuance")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-blockchain"},"Nervos Blockchain")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-dao"},"Nervos DAO")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0015-ckb-cryptoeconomics/0015-ckb-cryptoeconomics.md"},"Crypto-Economics RFC on Nervos Network GitHub"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"tragedy-of-the-commons"},"Tragedy of the Commons"),(0,i.kt)("p",null,"A situation in a system where the participants act in accordance with their own self interest and deplete or destroy a shared resource through their collective action."),(0,i.kt)("h4",{id:"see-also-89"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#tragedy-of-the-security-commons"},"Tragedy of the Security Commons")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#tragedy-of-the-storage-commons"},"Tragedy of the Storage Commons"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"tragedy-of-the-security-commons"},"Tragedy of the Security Commons"),(0,i.kt)("p",null,'A situation that can emerge on multi-asset blockchain platforms where asset tokens rely on the storage and security of the blockchain platform, but do not contribute back to the platform. As the number of assets that "ride for free" increases, so does the burden placed on the underlying blockchain platform. If the assets do not contribute to the underlying platform, the available security may not properly support the network.'),(0,i.kt)("h4",{id:"see-also-90"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#heavy-asset-problem"},"Heavy Asset Problem")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#tragedy-of-the-commons"},"Tragedy of the Commons")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#tragedy-of-the-storage-commons"},"Tragedy of the Storage Commons"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"tragedy-of-the-storage-commons"},"Tragedy of the Storage Commons"),(0,i.kt)("p",null,"A situation that can emerge on incentivized blockchain platforms where mining rewards are paid for inclusion of data to the blockchain, but no rewards exist for the long-term persistance of the blockchain data. As the size of the chain grows, so do the costs associated with persisting the data. If there is no direct incentive for persisting data, fewer and fewer nodes will do so. Eventually, too few nodes will be available to properly support the network."),(0,i.kt)("h4",{id:"see-also-91"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#tragedy-of-the-commons"},"Tragedy of the Commons")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#tragedy-of-the-security-commons"},"Tragedy of the Security Commons"))),(0,i.kt)("hr",null),(0,i.kt)("h2",{id:"technical-glossary"},"Technical Glossary"),(0,i.kt)("h3",{id:"active-cell"},"Active Cell"),(0,i.kt)("p",null,"Or live cell, a cell exists in the current CKB state. Only active cells can be used as inputs to new transactions."),(0,i.kt)("h4",{id:"synonyms-31"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#live-cell"},"Live Cell"))),(0,i.kt)("h4",{id:"see-also-92"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#input"},"Input")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"aggron"},"Aggron"),(0,i.kt)("p",null,"The first Nervos CKB testnet corresponding to mainnet Lina."),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"CKB version"),": >= v0.101.0 (latest stable is recommended)"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"Genesis hash"),": 0x10639e0895502b5688a6be8cf69460d76541bfa4821629d86d62ba0aae3f9606"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"Init command"),": ",(0,i.kt)("inlineCode",{parentName:"li"},"ckb init --chain testnet")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"Launched at"),": 2020-05-22 04:00:00 UTC"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"ckb2021 activated at"),": 2021-10-24 03:00:00 UTC")),(0,i.kt)("h4",{id:"synonyms-32"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#testnet"},"Testnet"))),(0,i.kt)("h4",{id:"not-to-be-confused-with-3"},"Not To Be Confused With"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lina"},"Lina")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mainnet"},"Mainnet"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"animagus"},"Animagus"),(0,i.kt)("p",null,"A framework layer that runs on top of Nervos CKB which provides an easy way to query for account balances without having to go through the cell collection process."),(0,i.kt)("h4",{id:"see-also-93"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell-collection"},"Cell Collection")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-ckb"},"Nervos CKB")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://medium.com/nervosnetwork/https-medium-com-nervosnetwork-animagus-part-1-introduction-66fa8ce27ccd-cfb361a7d883"},"Animagus Introduction on the Nervos Blog"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"args"},"Args"),(0,i.kt)("p",null,"Args is short for arguments. Arguments are data provided to the lock script or type script of a cell, similar to args provided to a function or method call."),(0,i.kt)("p",null,"Arguments are stored as part of the Cell when it is created."),(0,i.kt)("h4",{id:"see-also-94"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script"},"Type Script"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"axon"},"Axon"),(0,i.kt)("p",null,"Axon is a chain-based layer 2 protocol and framework with a practical security and economic model. Axon chains allow anyone to stake tokens on CKB to become a validator and participate in consensus."),(0,i.kt)("h4",{id:"see-also-95"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#layer-2"},"Layer 2")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-ckb"},"Nervos CKB"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"blake2b"},"Blake2b"),(0,i.kt)("p",null,"A cryptographic hash function. BLAKE2b (or BLAKE2) is optimized for 64-bit platforms including NEON-enabled ARMs and produces digests of any size between 1 and 64 bytes. BLAKE2b is optimized for 8- to 32-bit platforms, and produces digests of any size between 1 and 32 bytes. CKB uses BLAKE2b as the default hash algorithm."),(0,i.kt)("h4",{id:"see-also-96"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://blake2.net/blake2.pdf"},"Blake2b paper")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbhash"},"Ckbhash")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/BLAKE_(hash_function)"},"Blake Hash Function on Wikipedia")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Hash_function"},"Hash Function on Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"block-subsidy"},"Block Subsidy"),(0,i.kt)("p",null,"A payment that is made in the native currency of the blockchain that is paid to to miners for providing the computational resources create a block and secure the blockchain."),(0,i.kt)("p",null,"The subsidy consists is the portion of the total block reward that is issued out of inflation for creating the block, but does not include any additional transaction fees that may be paid on top."),(0,i.kt)("h4",{id:"synonyms-33"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block-reward"},"Block Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction-fee"},"Transaction Fee"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"boxer"},"Boxer"),(0,i.kt)("p",null,"A lightweight Rust library for verifying the Nervos layer 1 blockchain, the Common Knowledge Base."),(0,i.kt)("h4",{id:"see-also-97"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-base"},"Common Knowledge Base")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/xxuejie/ckb-boxer"},"Boxer on GitHub"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"block_version"},(0,i.kt)("inlineCode",{parentName:"h3"},"block_version")),(0,i.kt)("p",null,"Version of a block. This field is reserved for the system, set to 0 by default."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"pub const BLOCK_VERSION: Version = 0;\n")),(0,i.kt)("h4",{id:"see-also-98"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cell-collection"},"Cell Collection"),(0,i.kt)("p",null,"The process of gathering cells that meet certain criteria."),(0,i.kt)("p",null,"For example: To find the balance of a particular account, all active cells for the address would need to be collected."),(0,i.kt)("h4",{id:"see-also-99"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cellbase"},"Cellbase"),(0,i.kt)("p",null,"The transaction in each block that is responsible for the minting of new CKBytes."),(0,i.kt)("p",null,"This is the equivalent of a coinbase transaction in Bitcoin."),(0,i.kt)("h4",{id:"see-also-100"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://developer.bitcoin.org/glossary.html"},"Coinbase on Bitcoin.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cellbase_maturity"},(0,i.kt)("inlineCode",{parentName:"h3"},"cellbase_maturity")),(0,i.kt)("p",null,'Any referenced cellbase output must meet this requirement in a transaction; otherwise, the transaction is rejected. Cellbase outputs are "locked" and have to wait for 4 epochs (approximately 16 hours) to be confirmed before they become ready to be spent. This restriction is to avoid the risk of later transactions with cellbase root being rollbacked when a soft fork occurs.'),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"pub(crate) const CELLBASE_MATURITY: EpochNumberWithFraction =\nEpochNumberWithFraction::new_unchecked(4, 0, 1);\n")),(0,i.kt)("h4",{id:"see-also-101"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cellbase"},"Cellbase"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cell_deps"},(0,i.kt)("inlineCode",{parentName:"h3"},"cell_deps")),(0,i.kt)("p",null,"Pointers to live cells on the chain that allow scripts in the transaction to access (read-only) referenced live cells."),(0,i.kt)("p",null,"Find more in the essay ",(0,i.kt)("a",{parentName:"p",href:"https://docs.nervos.org/docs/essays/dependencies/#how-dependencies-work"},"Script dependencies"),"."),(0,i.kt)("h4",{id:"see-also-102"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#dependencies"},"Dependencies"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"ckbhash"},"Ckbhash"),(0,i.kt)("p",null,"CKB uses blake2b as the default hash algorithm with the following configurations:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"output digest size in bytes: ",(0,i.kt)("inlineCode",{parentName:"li"},"32")),(0,i.kt)("li",{parentName:"ul"},"personalization: ",(0,i.kt)("inlineCode",{parentName:"li"},"ckb-default-hash"))),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"ckbhash")," is used to denote the blake2b hash with the configurations above, there are example and test vectors in python 3:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-python"},"import hashlib\nimport unittest\n\ndef ckbhash():\n return hashlib.blake2b(digest_size=32, person=b'ckb-default-hash')\n\nclass TestCKBBlake2b(unittest.TestCase):\n\n def test_empty_message(self):\n hasher = ckbhash()\n hasher.update(b'')\n self.assertEqual('44f4c69744d5f8c55d642062949dcae49bc4e7ef43d388c5a12f42b5633d163e', hasher.hexdigest())\n\nif __name__ == '__main__':\n unittest.main()\n")),(0,i.kt)("h4",{id:"see-also-103"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blake2b"},"Blake2b"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"ckb-merkle-tree"},"CKB Merkle Tree"),(0,i.kt)("p",null,"CKB Merkle Tree is a CBMT( ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0006-merkle-tree/0006-merkle-tree.md#complete-binary-merkle-tree"},"Complete Binary Merkle Tree")," ) using following merge function:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"ckbhash(left || right)\n")),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},(0,i.kt)("inlineCode",{parentName:"p"},"ckbhash")," is the hash function, ",(0,i.kt)("inlineCode",{parentName:"p"},"||")," denotes binary concatenation.")),(0,i.kt)("h4",{id:"see-also-104"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0006-merkle-tree/0006-merkle-tree.md"},"Merkle Tree for Static Data")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbhash"},"Ckbhash")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Merkle_tree"},"Merkle Tree on Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"code-hash-1"},"Code Hash"),(0,i.kt)("p",null,"A field in a Cell that contains a hash value which could refer to a specific piece of data, or a specific cell referenced by Type ID."),(0,i.kt)("h4",{id:"see-also-105"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#data"},"Data")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-id"},"Type ID"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"commit-1"},"Commit"),(0,i.kt)("p",null,"The process of taking a proposed transaction and adding it to the blockchain. After the transaction has been committed it is confirmed."),(0,i.kt)("p",null,"Miners are incentivized to commit transactions by being paid a commit reward."),(0,i.kt)("h4",{id:"see-also-106"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#commit-reward"},"Commit Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#confirmation"},"Confirmation")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#propose"},"Propose")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"commitment-zone"},"Commitment Zone"),(0,i.kt)("p",null,"Section of the block that contains transaction commitments. The commitment zone can only contain valid transactions which have appeared in the proposal zone of one of the previous 2 to 10 blocks."),(0,i.kt)("h4",{id:"see-also-107"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proposal-zone"},"Proposal Zone")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"consume-1"},"Consume"),(0,i.kt)("p",null,"The process of using a Live Cell as an input to a transaction."),(0,i.kt)("p",null,"The process of consumption marks the Live Cell as a Dead Cell. This is the equivalent of marking a UTXO as spent in Bitcoin."),(0,i.kt)("h4",{id:"see-also-108"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell-model"},"Cell Model")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#dead-cell"},"Dead Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#live-cell"},"Live Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://developer.bitcoin.org/glossary.html"},"UTXO on Bitcoin.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"crypto-primitives"},"Crypto Primitives"),(0,i.kt)("p",null,"Well-established, low-level cryptographic algorithm commonly used to build out a cryptographic protocol."),(0,i.kt)("h4",{id:"see-also-109"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Cryptographic_primitive"},"Cryptographic Primitive on Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"dao_type_hash"},(0,i.kt)("inlineCode",{parentName:"h3"},"dao_type_hash")),(0,i.kt)("p",null,"NervosDAO\u2019s ",(0,i.kt)("inlineCode",{parentName:"p"},"type_hash"),". "),(0,i.kt)("p",null,"Find more in ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0024-ckb-genesis-script-list/0024-ckb-genesis-script-list.md#ckb-genesis-script-list"},"CKB Genesis Script List"),"."),(0,i.kt)("h4",{id:"see-also-110"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#%60type_hash%60"},(0,i.kt)("inlineCode",{parentName:"a"},"type_hash")))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"data-1"},"Data"),(0,i.kt)("p",null,"In Nervos specific contexts, data may refer to the data structure within a Cell. This structure is used to hold any form of information that needs to be stored on the Nervos blockchain."),(0,i.kt)("p",null,"In more general contexts, data may refer to any form of information."),(0,i.kt)("h4",{id:"see-also-111"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell-model"},"Cell Model"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"dead-cell"},"Dead Cell"),(0,i.kt)("p",null,"A cell that has been used as an input to a previous transaction and is consumed. "),(0,i.kt)("p",null,"A dead cell cannot be used as an input to a new transaction, nor can it be used as a dependency. It is effectively destroyed and removed from the active state of the network."),(0,i.kt)("p",null,'A dead cell is the equivalent of a "spent UTXO" in Bitcoin.'),(0,i.kt)("h4",{id:"synonyms-34"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#historical-cell"},"Historical Cell"))),(0,i.kt)("h4",{id:"see-also-112"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell-model"},"Cell Model")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#consume"},"Consume")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://developer.bitcoin.org/glossary.html"},"UTXO on Bitcoin.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"dep-group"},"Dep Group"),(0,i.kt)("p",null,"A method for referencing multiple dependencies which are commonly used together using a single dependency field."),(0,i.kt)("h4",{id:"see-also-113"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#dep-type"},"Dep Type")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#dependencies"},"Dependencies")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0022-transaction-structure/0022-transaction-structure.md"},"CKB Transaction Structure on GitHub"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"dep-type"},"Dep Type"),(0,i.kt)("p",null,"A field that specifies the type of the dependency."),(0,i.kt)("h4",{id:"see-also-114"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#dep-group"},"Dep Group")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#dependencies"},"Dependencies")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0022-transaction-structure/0022-transaction-structure.md"},"CKB Transaction Structure on GitHub"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"deps"},"Deps"),(0,i.kt)("p",null,"A shorthand name for dependencies."),(0,i.kt)("h4",{id:"synonyms-35"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#dependencies"},"Dependencies"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"dependencies"},"Dependencies"),(0,i.kt)("p",null,"Dependencies are commonly referred to as deps. Dependencies are cells that are referenced in a transaction. Cells that are referenced as dependencies are read-only and made available to any scripts executing within the transaction. Dependencies, or deps, are not consumed. "),(0,i.kt)("h4",{id:"synonyms-36"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#deps"},"Deps"))),(0,i.kt)("h4",{id:"see-also-115"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#consume"},"Consume")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#script"},"Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"duktape"},"Duktape"),(0,i.kt)("p",null,"Duktape is an embeddable Javascript engine, with a focus on portability and compact footprint."),(0,i.kt)("p",null,"Duktape is used to run JavaScript based smart contracts on Nervos."),(0,i.kt)("h4",{id:"see-also-116"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://duktape.org/"},"Duktape Official Website"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"difficulty"},"Difficulty"),(0,i.kt)("p",null,"A measurement of how difficult it is to solve the ",(0,i.kt)("a",{parentName:"p",href:"#proof-of-work"},"Proof of Work")," cryptographic puzzle required to create a block."),(0,i.kt)("p",null,"Networks automatically adjust the difficulty to control the speed at which blocks are generated as mining participants enter and exit the network."),(0,i.kt)("h4",{id:"see-also-117"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proof-of-work"},"Proof of Work"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"diviner"},"Diviner"),(0,i.kt)("p",null,"A deterministic testing framework for Rust."),(0,i.kt)("h4",{id:"see-also-118"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/xxuejie/diviner"},"Diviner on GitHub"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"eaglesong"},"Eaglesong"),(0,i.kt)("p",null,"Eaglesong is a new hash function developed specifically for Nervos CKB proof-of-work, which is also suitable in other use cases in which a secure hash function is needed. "),(0,i.kt)("h4",{id:"see-also-119"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0010-eaglesong/0010-eaglesong.md"},"Eaglesong RFC on the Nervos Github")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://medium.com/nervosnetwork/the-proof-of-work-function-of-nervos-ckb-3cc8364464d9"},"Introducing Eaglesong, Nervos\u2019s New Hash Function for CKB Proof-of-Work"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"epoch_duration_target"},(0,i.kt)("inlineCode",{parentName:"h3"},"epoch_duration_target")),(0,i.kt)("p",null,"The estimated epoch duration specified by NC-Max. Set as 4 hours in CKB. "),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"pub(crate) const DEFAULT_EPOCH_DURATION_TARGET: u64 = 4 * 60 * 60; // 4 hours, unit: second\n")),(0,i.kt)("h4",{id:"see-also-120"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#epoch"},"Epoch")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nc-max"},"NC-Max"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"erc20"},"ERC20"),(0,i.kt)("p",null,"An Ethereum token standard for basic fungible tokens."),(0,i.kt)("p",null,"An SUDT on Nervos is the equivalent of Ethereum tokens standards ERC20 or ERC777."),(0,i.kt)("h4",{id:"see-also-121"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#erc777"},"ERC777")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#fungible-token"},"Fungible Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#user-defined-token"},"User-Defined Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://eips.ethereum.org/EIPS/eip-20"},"ERC20 on Ethereum.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"erc721"},"ERC721"),(0,i.kt)("p",null,"An Ethereum token standard for non-fungible tokens."),(0,i.kt)("h4",{id:"see-also-122"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#non-fungible-token"},"Non-Fungible Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://eips.ethereum.org/EIPS/eip-721"},"ERC721 on Ethereum.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"erc777"},"ERC777"),(0,i.kt)("p",null,"An updated Ethereum token standard for basic fungible tokens that is backwards compatible with ERC20."),(0,i.kt)("p",null,"An SUDT on Nervos is the equivalent of Ethereum tokens standards ERC20 or ERC777."),(0,i.kt)("h4",{id:"see-also-123"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#erc20"},"ERC20")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#fungible-token"},"Fungible Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#user-defined-token"},"User-Defined Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://eips.ethereum.org/EIPS/eip-777"},"ERC777 on Ethereum.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"erc1155"},"ERC1155"),(0,i.kt)("p",null,"An Ethereum token standard that supports the creation any number of fungible or non-fungible tokens on a single contract."),(0,i.kt)("h4",{id:"see-also-124"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#fungible-token"},"Fungible Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#non-fungible-token"},"Non-Fungible Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#user-defined-token"},"User-Defined Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://eips.ethereum.org/EIPS/eip-1155"},"ERC1155 on Ethereum.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"full-address"},"Full Address"),(0,i.kt)("p",null,"An address format used on Nervos that includes the full code hash of the lock script associated."),(0,i.kt)("h4",{id:"see-also-125"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#address"},"Address")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#short-address"},"Short Address"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"generator"},"Generator"),(0,i.kt)("p",null,"A program used to create transactions that can be broadcast to the Nervos CKB network. "),(0,i.kt)("p",null,"Generators run locally on the client side (off-chain). They utilize user input and existing cells as program inputs, to create new cells with new states as output."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"genesis-block"},"Genesis Block"),(0,i.kt)("p",null,"The first block in the blockchain, used to initialize the global state. The genesis block is unique because it does not contain a reference to the previous block because it is the first."),(0,i.kt)("h4",{id:"see-also-126"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blockchain"},"Blockchain"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"genesis_hash"},(0,i.kt)("inlineCode",{parentName:"h3"},"genesis_hash")),(0,i.kt)("p",null,"Hash of CKB genesis block. CKB Genesis Block was created in a decentralized manner that encourages everyone to generate a unique genesis block verifiably through the ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/genesis-block-generator/blob/master/spec.md"},"Genesis Block Generator"),". Nodes thus created and activated can be connected to any other node across the network to form a decentralized Common Knowledge Base."),(0,i.kt)("p",null,"The genesis block contains two main components:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/ckb-system-scripts/blob/v0.5.4/c/dao.c"},"System script")),(0,i.kt)("li",{parentName:"ul"},"Token pre-allocation based on the Nervos Foundation\u2018s ",(0,i.kt)("a",{parentName:"li",href:"https://medium.com/nervosnetwork/nervos-ckb-official-public-sale-announcement-431438f4cc39#:~:text=Key%20details%20of%20the%20Nervos%20Public%20Sale&text=The%20initial%20total%20supply%20of,be%201%20CKB%20%3D%200.01%20USD."},"announcement"),".")),(0,i.kt)("h4",{id:"see-also-127"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#genesis-block"},"Genesis block"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"godwoken"},"Godwoken"),(0,i.kt)("p",null,"Godwoken is a layer 2 rollup framework for Nervos CKB. It provides scaling capability, as well as an abstract account model to CKB."),(0,i.kt)("h4",{id:"see-also-128"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/godwoken"},"Godwoken on GitHub")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://docs.godwoken.io/"},"Godwoken Documentation Site"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"governance-script"},"Governance Script"),(0,i.kt)("p",null,"A type script which defines the monetary policy of a User Defined Token (UDT)."),(0,i.kt)("h4",{id:"see-also-129"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#governance-script-hash"},"Governance Script Hash")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#udt"},"UDT")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#user-defined-token"},"User Defined Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script"},"Type Script"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"governance-script-hash"},"Governance Script Hash"),(0,i.kt)("p",null,"A Blake2b hash of a type script which is used as an identifier for the script when referenced by a cell."),(0,i.kt)("h4",{id:"synonyms-37"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script-hash"},"Type Script Hash"))),(0,i.kt)("h4",{id:"see-also-130"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#governance-script"},"Governance Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#udt"},"UDT")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#user-defined-token"},"User Defined Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script"},"Type Script"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"historical-cell"},"Historical Cell"),(0,i.kt)("p",null,"An alternative term for ",(0,i.kt)("a",{parentName:"p",href:"#dead-cell"},"Dead Cell"),"."),(0,i.kt)("h4",{id:"synonyms-38"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#dead-cell"},"Dead Cell"))),(0,i.kt)("h4",{id:"see-also-131"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell-model"},"Cell Model"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"inbound-connection"},"Inbound Connection"),(0,i.kt)("p",null,"Inbound connection means it is initiated by the remote peer; and the connection itself is outgoing connection when we switch the subject to the remote peer."),(0,i.kt)("h4",{id:"see-also-132"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#outbound-connection"},"Outbound Connection"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"indexer"},"Indexer"),(0,i.kt)("p",null,"An application or library to trace live cells that comply with criteria specified by the developer or user."),(0,i.kt)("h4",{id:"see-also-133"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#live-cell"},"Live Cell"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"initial_primary_epoch_reward"},(0,i.kt)("inlineCode",{parentName:"h3"},"initial_primary_epoch_reward")),(0,i.kt)("p",null,"Incentives paid to miners in CKBytes by epoch in CKB base issuance. Under CKB's consensus, block interval is uncertain, while epoch can be fixed at approximately 4 hours, so reward issuance is determined by epoch. Each epoch issues 1_917_808_21917808 Shannons of CKBytes, whose total amount is fixed but halves every 4 years. "),(0,i.kt)("p",null,"The initial base issuance is 4.2 billion CKBytes per year. Similar to Bitcoin, the base issuance halves approximately every 4 years until it stops."),(0,i.kt)("p",null,"To calculate, ",(0,i.kt)("a",{parentName:"p",href:"https://docs.nervos.org/docs/basics/glossary/#block-reward"},"block reward")," = ",(0,i.kt)("inlineCode",{parentName:"p"},"initial_primary_epoch_reward")," / epoch_length (the number of blocks in the epoch)."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"pub(crate) const INITIAL_PRIMARY_EPOCH_REWARD: Capacity = Capacity::shannons(1_917_808_21917808);\n")),(0,i.kt)("h4",{id:"see-also-134"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block-reward"},"Block Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#epoch"},"Epoch")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#%60secondary_epoch_reward%60"},(0,i.kt)("inlineCode",{parentName:"a"},"secondary_epoch_reward"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#%60primary_epoch_reward_havling_interval%60"},(0,i.kt)("inlineCode",{parentName:"a"},"primary_epoch_reward_havling_interval")))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"input"},"Input"),(0,i.kt)("p",null,"A live cell that is used in a transaction. If the transaction is accepted by the network, the live cell gets consumed as input and labeled as a dead cell."),(0,i.kt)("h4",{id:"see-also-135"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#consume"},"Consume")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#dead-cell"},"Dead Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#live-cell"},"Live Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"keyper"},"Keyper"),(0,i.kt)("p",null,"A specification of how to manage wallet Lock Scripts which apply to a specific user."),(0,i.kt)("h4",{id:"see-also-136"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/ququzone/keyper"},"Keyper on GitHub"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"late-spawning"},"Late Spawning"),(0,i.kt)("p",null,"When a node joins a blockchain network for the first time after the network has already been in operation for a period of time."),(0,i.kt)("p",null,"A network is said to support late spawning if that participant can download and verify the entire blockchain without having to trust any of the participants in the network to feed them unaltered data."),(0,i.kt)("h4",{id:"see-also-137"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#genesis-block"},"Genesis Block"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"layer-1"},"Layer 1"),(0,i.kt)("p",null,"Layer 1 of a decentralized ecosystem is the underlying blockchain architecture."),(0,i.kt)("p",null,"A proof of work blockchain known as the Common Knowledge Base (CKB) that serves as the base layer for the Nervos Network. "),(0,i.kt)("h4",{id:"see-also-138"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckb"},"CKB")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-base"},"Common Knowledge Base")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#layer-2"},"Layer 2"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"layer-2"},"Layer 2"),(0,i.kt)("p",null,"Layer 2 refers to a secondary framework or protocol that is built on top of an existing blockchain system. "),(0,i.kt)("p",null,"The main goal of these protocols is to solve the transaction speed and scaling difficulties that are being faced by the major cryptocurrency networks."),(0,i.kt)("h4",{id:"see-also-139"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#layer-1"},"Layer 1"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"lina"},"Lina"),(0,i.kt)("p",null,"The name of public mainnet of the Nervos CKB."),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"CKB version"),": >= v0.25.2 (latest stable is recommended)"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"Genesis hash"),": 0x92b197aa1fba0f63633922c61c92375c9c074a93e85963554f5499fe1450d0e5"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"Init command"),": ",(0,i.kt)("inlineCode",{parentName:"li"},"ckb init --chain mainnet")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"Launched at"),": 2019-11-15 21:11:00 UTC")),(0,i.kt)("h4",{id:"synonyms-39"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mainnet"},"Mainnet"))),(0,i.kt)("h4",{id:"not-to-be-confused-with-4"},"Not To Be Confused With"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#aggron"},"Aggron")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#testnet"},"Testnet"))),(0,i.kt)("h4",{id:"see-also-140"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-ckb"},"Nervos CKB"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"live-cell"},"Live Cell"),(0,i.kt)("p",null,"A cell that has not been consumed and is available for use."),(0,i.kt)("p",null,"This is similar to an unspent transaction output (UTXO) in Bitcoin."),(0,i.kt)("h4",{id:"synonyms-40"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#active-cell"},"Active Cell"))),(0,i.kt)("h4",{id:"see-also-141"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell-model"},"Cell Model")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://developer.bitcoin.org/glossary.html"},"UTXO on Bitcoin.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"lock"},"Lock"),(0,i.kt)("p",null,"A script that represents the ownership of a cell. A user successfully unlocks a cell and is able to consume it if the cell's lock script exits normally. "),(0,i.kt)("h4",{id:"see-also-142"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script"))),(0,i.kt)("h3",{id:"lock-script"},"Lock Script"),(0,i.kt)("p",null,"A script that enforces access and ownership of a cell. This script controls who has permission to use the cell as an input. Lock scripts accept user generated proofs or witnesses and including transaction as inputs."),(0,i.kt)("h4",{id:"see-also-143"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script"},"Type Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#script"},"Script"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"lock-script-hash"},"Lock Script Hash"),(0,i.kt)("p",null,"A ",(0,i.kt)("a",{parentName:"p",href:"#blake2b"},"Blake2b")," hash of a lock script which is used as an identifier for the script when referenced by a cell."),(0,i.kt)("h4",{id:"see-also-144"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"mainnet"},"Mainnet"),(0,i.kt)("p",null,'Short for "main network", the running Nervos CKB public blockchain. The name of the Nervos CKB Mainnet is ',(0,i.kt)("a",{parentName:"p",href:"#lina"},"Lina"),"."),(0,i.kt)("h4",{id:"synonyms-41"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckb"},"CKB")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-base"},"Common Knowledge Base")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lina"},"Lina")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-ckb"},"Nervos CKB"))),(0,i.kt)("h4",{id:"not-to-be-confused-with-5"},"Not To Be Confused With"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#aggron"},"Aggron")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#testnet"},"Testnet"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"max_block_bytes"},(0,i.kt)("inlineCode",{parentName:"h3"},"max_block_bytes")),(0,i.kt)("p",null,"The maximum transaction size limit allowed in a block in bytes. Estimated based on the size consumed by 1000 2-in-2-out secp256k1 transactions."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"pub const MAX_BLOCK_BYTES: u64 = TWO_IN_TWO_OUT_BYTES * TWO_IN_TWO_OUT_COUNT;\n")),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"max_block_cycles"},(0,i.kt)("inlineCode",{parentName:"h3"},"max_block_cycles")),(0,i.kt)("p",null,"The maximum transaction cycle limit allowed in a block. Estimated based on the cycles consumed by 1000 2-in-2-out secp256k1 transactions."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"/// cycles of a typical two-in-two-out tx.\npub const TWO_IN_TWO_OUT_CYCLES: Cycle = 3_500_000;\n\n/// count of two-in-two-out txs a block should capable to package.\nconst TWO_IN_TWO_OUT_COUNT: u64 = 1_000;\npub(crate) const MAX_BLOCK_CYCLES: u64 = TWO_IN_TWO_OUT_CYCLES * TWO_IN_TWO_OUT_COUNT;\n")),(0,i.kt)("h4",{id:"see-also-145"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cycles"},"Cycles"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"max_block_proposals_limit"},(0,i.kt)("inlineCode",{parentName:"h3"},"max_block_proposals_limit")),(0,i.kt)("p",null,"The maximum amount of proposals contained in one block. The default value starts from 1.5."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"TWO_IN_TWO_OUT_COUNT\npub const MAX_BLOCK_PROPOSALS_LIMIT: u64 = 1_500;\n")),(0,i.kt)("h4",{id:"see-also-146"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proposal-zone"},"Proposal Zone"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"max_uncles_num"},(0,i.kt)("inlineCode",{parentName:"h3"},"max_uncles_num")),(0,i.kt)("p",null,"The maximum number (Uint64) of uncle blocks allowed for one block. Set as 2 by default."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"const MAX_UNCLE_NUM: usize = 2;\n")),(0,i.kt)("h4",{id:"see-also-147"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#uncle"},"Uncle"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"median_time_block_count"},(0,i.kt)("inlineCode",{parentName:"h3"},"median_time_block_count")),(0,i.kt)("p",null,"A timestamp is valid only when it is greater than the median timestamp of the previous 37 blocks."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"const MEDIAN_TIME_BLOCK_COUNT: usize = 37;\n")),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"minting"},"Minting"),(0,i.kt)("p",null,"The process of creating of new tokens."),(0,i.kt)("h4",{id:"see-also-148"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"molecule"},"Molecule"),(0,i.kt)("p",null,"A serialization framework for encoding data widely used on the Nervos Network."),(0,i.kt)("h4",{id:"see-also-149"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0008-serialization/0008-serialization.md"},"Molecule Specification")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/molecule"},"Molecule on Github")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/ckb/tree/develop/util/types/schemas"},"Molecule Schema used in CKB"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"muta"},"Muta"),(0,i.kt)("p",null,"A highly customizable, high-performance blockchain framework designed to support proof of stake, BFT consensus and smart contracts."),(0,i.kt)("h4",{id:"see-also-150"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/muta"},"Muta on GitHub")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proof-of-stake"},"Proof of Stake"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"nervos-ckb"},"Nervos CKB"),(0,i.kt)("p",null,"The layer 1 blockchain of the Nervos Network, the Common Knowledge Base."),(0,i.kt)("p",null,"Nervos CKB is often referred to as the Nervos Blockchain."),(0,i.kt)("h4",{id:"synonyms-42"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckb"},"CKB")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-base"},"Common Knowledge Base")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-blockchain"},"Nervos Blockchain"))),(0,i.kt)("h4",{id:"see-also-151"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#layer-1"},"Layer 1"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"off-chain-computation"},"Off-Chain Computation"),(0,i.kt)("p",null,"A programming model where all computation is done off-chain to reduce the burden on the nodes in the network and provide higher levels of scalability. Nervos uses off-chain computation and on-chain verification."),(0,i.kt)("h4",{id:"see-also-152"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#on-chain-computation"},"On-Chain Computation")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#on-chain-verification"},"On-Chain Verification"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"off-chain-scaling"},"Off-Chain Scaling"),(0,i.kt)("p",null,"Off-chain scaling is the approach that only using the blockchain as a secure asset and settlement platform in conjunction with transferring almost all transactions off the blockchain."),(0,i.kt)("h4",{id:"see-also-153"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#on-chain-scaling"},"On-Chain Scaling"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"off-chain-state"},"Off-Chain State"),(0,i.kt)("p",null,"The data of an application that is not stored on the blockchain, or is not accessible by on-chain smart contracts."),(0,i.kt)("h4",{id:"see-also-154"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#on-chain-state"},"On-Chain State"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"on-chain-computation"},"On-Chain Computation"),(0,i.kt)("p",null,"A programming model where all computation by smart contracts is done on-chain by every node on the network simultaneously."),(0,i.kt)("p",null,"Ethereum uses on-chain computation."),(0,i.kt)("h4",{id:"see-also-155"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#off-chain-computation"},"Off-Chain Computation"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"on-chain-scaling"},"On-Chain Scaling"),(0,i.kt)("p",null,"On-chain scaling solution refer to extending the throughput of the consensus process, or increasing network throughput as node number increases."),(0,i.kt)("h4",{id:"see-also-156"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#off-chain-scaling"},"Off-chain Scaling"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"on-chain-state"},"On-Chain State"),(0,i.kt)("p",null,"The data of an application that is stored on the blockchain and is accessible by on-chain smart contracts."),(0,i.kt)("p",null,"Nervos provides on-chain state for all smart contracts."),(0,i.kt)("h4",{id:"see-also-157"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#off-chain-state"},"Off-Chain State"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"on-chain-verification"},"On-Chain Verification"),(0,i.kt)("p",null,"A programming model where all computation is done off-chain to reduce the burden on the nodes in the network, but verification of the resulting data is done on-chain to enforce the smart contract rules created by the developer."),(0,i.kt)("p",null,"Nervos uses off-chain computation and on-chain verification."),(0,i.kt)("h4",{id:"see-also-158"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#on-chain-computation"},"On-Chain Computation"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"open-transaction"},"Open Transaction"),(0,i.kt)("p",null,"A signed piece of a transaction that is incomplete and invalid on its own. When combined with other signed transaction pieces can form a complete transaction which can be processed."),(0,i.kt)("p",null,"One use of open transactions is to create the functionality required for a trustless decentalized exchange."),(0,i.kt)("h4",{id:"see-also-159"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cryptographic-signature"},"Cryptographic Signature")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"optimistic-rollup"},"Optimistic Rollup"),(0,i.kt)("p",null,"A rollup of transactions that use fraud proofs to offer increased layer 2 transaction throughput while using the security and data availability provided by layer 1."),(0,i.kt)("h4",{id:"see-also-160"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#layer-1"},"Layer 1")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#layer-2"},"Layer 2"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"orphan"},"Orphan"),(0,i.kt)("p",null,"A shorthand name for Orphan Block."),(0,i.kt)("h4",{id:"synonyms-43"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan-block"},"Orphan Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#uncle"},"Uncle"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"orphan-block"},"Orphan Block"),(0,i.kt)("p",null,"An orphan block is a valid block that is not included in the main fork due to, for example, a lag within the network itself. There can be two miners who solve a block simultaneously in NC-Max. They are non-main-chain blocks, also known as stale blocks."),(0,i.kt)("p",null,"In Nervos, orphan blocks are better described as Uncles."),(0,i.kt)("h4",{id:"synonyms-44"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan"},"Orphan")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#uncle"},"Uncle"))),(0,i.kt)("h4",{id:"see-also-161"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nc-max"},"NC-Max")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan-rate"},"Orphan Rate"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"orphan-rate"},"Orphan Rate"),(0,i.kt)("p",null,"A measure of the speed at which Orphan blocks occur within the blockchain network."),(0,i.kt)("h4",{id:"see-also-162"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan-block"},"Orphan Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#%60orphan_rate_target%60"},(0,i.kt)("inlineCode",{parentName:"a"},"orphan_rate_target")))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"orphan_rate_target"},(0,i.kt)("inlineCode",{parentName:"h3"},"orphan_rate_target")),(0,i.kt)("p",null,"The estimated orphan block rate specified in NC-max. Set as 2.5% in CKB."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"// o_ideal = 1/40 = 2.5%\npub(crate) const DEFAULT_ORPHAN_RATE_TARGET: (u32, u32) = (1, 40);\n")),(0,i.kt)("h4",{id:"see-also-163"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan-rate"},"Orphan Rate")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan-block"},"Orphan Block"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"orphan-transactions"},"Orphan Transactions"),(0,i.kt)("p",null,"Orphan transactions are those whose parental transactions are missing at the time that they are processed. These transactions are not propagated to other nodes until all of their missing parents are received, and they thus end up languishing in a local buffer until evicted or their parents are found."),(0,i.kt)("h4",{id:"see-also-164"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan-block"},"Orphan Block"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"outbound-connection"},"Outbound Connection"),(0,i.kt)("p",null,'Also knowns as "outgoing connection".'),(0,i.kt)("p",null,"A TCP connection is outgoing for the node if it was initiated (sent the TCP SYN packet) by the node in the context."),(0,i.kt)("h4",{id:"see-also-165"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#inbound-connection"},"Inbound Connection"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"outpoint"},"Outpoint"),(0,i.kt)("p",null,"A particular output Cell in a transaction."),(0,i.kt)("h4",{id:"see-also-166"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#output"},"Output")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"output"},"Output"),(0,i.kt)("p",null,"A live cell that is created in a transaction."),(0,i.kt)("h4",{id:"see-also-167"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#live-cell"},"Live Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"overlord"},"Overlord"),(0,i.kt)("p",null,"A byzantine fault tollerant consensus algorithm designed by Nervos for Huobi which can support thousands of transactions per second."),(0,i.kt)("h4",{id:"see-also-168"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://medium.com/nervosnetwork/overlord-a-new-consensus-algorithm-3cc51690d269"},"Overlord on Medium"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"p2wsh"},"P2WSH"),(0,i.kt)("p",null,"A Pay-to-Witness-Script-Hash (P2WSH) is a type of Bitcoin transaction similar to a ",(0,i.kt)("a",{parentName:"p",href:"https://en.bitcoin.it/wiki/Pay_to_script_hash"},"P2SH")," transaction in most ways, except that it uses ",(0,i.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/SegWit"},"SegWit"),"."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"permanent_difficulty_in_dummy"},(0,i.kt)("inlineCode",{parentName:"h3"},"permanent_difficulty_in_dummy")),(0,i.kt)("p",null,"Keeps the difficulty permanent if PoW is dummy when dev-chain disables NC-MAX difficulty adjustment. As ",(0,i.kt)("inlineCode",{parentName:"p"},"boolean"),", it can be enabled through configuration."),(0,i.kt)("h4",{id:"see-also-169"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#difficulty"},"Difficulty"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"polyjuice"},"Polyjuice"),(0,i.kt)("p",null,"Polyjuice provides an Ethereum compatible runtime on Godwoken."),(0,i.kt)("h4",{id:"see-also-170"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#godwoken"},"Godwoken")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/polyjuice"},"Polyjuice on GitHub"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"primary_epoch_reward_halving_interval"},(0,i.kt)("inlineCode",{parentName:"h3"},"primary_epoch_reward_halving_interval")),(0,i.kt)("p",null,"The halving cycle of epoch reward in CKB base issuance, typically every four years. The mining reward halves when the halving interval occurs."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"pub(crate) const DEFAULT_PRIMARY_EPOCH_REWARD_HALVING_INTERVAL: EpochNumber =\n4 * 365 * 24 * 60 * 60 / DEFAULT_EPOCH_DURATION_TARGET; // every 4 years\n")),(0,i.kt)("h4",{id:"see-also-171"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#%60initial_primary_epoch_reward%60"},(0,i.kt)("inlineCode",{parentName:"a"},"initial_primary_epoch_reward")))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"proposal-zone"},"Proposal Zone"),(0,i.kt)("p",null,"Section of the block that contains transaction proposals."),(0,i.kt)("h4",{id:"see-also-172"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#commitment-zone"},"Commitment Zone")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#propose"},"Propose"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"propose"},"Propose"),(0,i.kt)("p",null,"The process of taking an unconfirmed transaction out of the mempool and proposing it for commitment. A transaction is not confirmed until after it has been committed."),(0,i.kt)("p",null,"Miners are incentivized to propose transactions by being paid a proposal reward."),(0,i.kt)("h4",{id:"see-also-173"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#commit"},"Commit")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#confirmation"},"Confirmation")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mempool"},"Mempool")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proposal-reward"},"Proposal Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proposal-zone"},"Proposal Zone")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"proposer_reward_ratio"},(0,i.kt)("inlineCode",{parentName:"h3"},"proposer_reward_ratio")),(0,i.kt)("p",null,"The reward ratio from transaction fees for miners who submit proposals specified by NC-Max. It is set as 40% in CKB, meaning the miner who first submits the transaction proposal will be rewarded with 40% of the transaction fee."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"const PROPOSER_REWARD_RATIO: Ratio = Ratio::new(4, 10);\n")),(0,i.kt)("h4",{id:"see-also-174"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proposal-reward"},"Proposal Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nc-max"},"NC-Max"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"risc-v"},"RISC-V"),(0,i.kt)("p",null,"An open standard instruction set architecture (ISA) for general computing."),(0,i.kt)("p",null,"RISC-V is the instruction set used by the CKB-VM."),(0,i.kt)("h4",{id:"see-also-175"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckb-vm"},"CKB-VM")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/RISC-V"},"RISC-V on Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"schnorr-signature"},"Schnorr Signature"),(0,i.kt)("p",null,"A cryptographic signature scheme for signing and verification."),(0,i.kt)("h4",{id:"see-also-176"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Schnorr_signature"},"Schnorr Signature on Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"script"},"Script"),(0,i.kt)("p",null,"A program that executes on the CKB-VM. A Script can be one of two types:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Lock Script - Used to control ownership and access to a Cell."),(0,i.kt)("li",{parentName:"ul"},"Type Script - Used to control how a Cell is used in a transaction.")),(0,i.kt)("p",null,"A script is a binary executable in the ELF format for the RISC-V architecture, a program that runs on the CKB-VM."),(0,i.kt)("h4",{id:"see-also-177"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#risc-v"},"CKB-VM")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#risc-v"},"RISC-V")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script"},"Type Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Executable_and_Linkable_Format"},"ELF on Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"secondary_epoch_reward"},(0,i.kt)("inlineCode",{parentName:"h3"},"secondary_epoch_reward")),(0,i.kt)("p",null,"The secondary reward per epoch. Issued according to CKB\u2019s tokenomics detailed in ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0015-ckb-cryptoeconomics/0015-ckb-cryptoeconomics.md"},"RFC0015"),". "),(0,i.kt)("p",null,"Secondary issuance is designed to collect state rent, and has an issuance amount that is constant over time. After base issuance stops, there will only be secondary issuance."),(0,i.kt)("p",null,"Secondary issuance has two parts. One is a fixed amount of base incentive (approximately 134.4 million CKBytes per year), while the other varies according to the number of CKBytes currently occupied."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"pub(crate) const DEFAULT_SECONDARY_EPOCH_REWARD: Capacity = Capacity::shannons(613_698_63013698);\n")),(0,i.kt)("h4",{id:"see-also-178"},"See also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#%60initial_primary_epoch_reward%60"},(0,i.kt)("inlineCode",{parentName:"a"},"initial_primary_epoch_reward"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#secondary-reward"},"Secondary Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#secondary-issuance"},"Secondary Issuance"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"secp256k1_blake160_sighash_all_type_hash"},(0,i.kt)("inlineCode",{parentName:"h3"},"secp256k1_blake160_sighash_all_type_hash")),(0,i.kt)("p",null,"Type hash of ",(0,i.kt)("inlineCode",{parentName:"p"},"secp256k1_blake160_sighash_all")," in ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0024-ckb-genesis-script-list/0024-ckb-genesis-script-list.md#ckb-genesis-script-list"},"CKB genesis scripts"),"."),(0,i.kt)("p",null,"Find more details ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0024-ckb-genesis-script-list/0024-ckb-genesis-script-list.md#secp256k1blake160"},"here"),"."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"secp256k1_blake160_multisig_all_type_hash"},(0,i.kt)("inlineCode",{parentName:"h3"},"secp256k1_blake160_multisig_all_type_hash")),(0,i.kt)("p",null,"Type hash of ",(0,i.kt)("inlineCode",{parentName:"p"},"secp256k1_blake160_multisig_all")," in ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0024-ckb-genesis-script-list/0024-ckb-genesis-script-list.md#ckb-genesis-script-list"},"CKB genesis scripts"),"."),(0,i.kt)("p",null,"Find more details ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0024-ckb-genesis-script-list/0024-ckb-genesis-script-list.md#secp256k1multisig"},"here"),"."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"seed-cell"},"Seed Cell"),(0,i.kt)("p",null,"A design pattern on Nervos from creating unique identifiers used to create unforgeable assets."),(0,i.kt)("h4",{id:"see-also-179"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"shannon"},"Shannon"),(0,i.kt)("p",null,"A fractional denomination of CKBytes. One CKByte is equal to 100,000,000 Shannons."),(0,i.kt)("p",null,"A Shannon is the equivalent of a Bitcoin Satoshi."),(0,i.kt)("h4",{id:"see-also-180"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-byte"},"Common Knowledge Byte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://developer.bitcoin.org/glossary.html"},"Satoshi (denomination) on Bitcoin.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"short-address"},"Short Address"),(0,i.kt)("p",null,"An address format on Nervos that does not include a code hash of the associated lock script, instead using one of the many common lock scripts."),(0,i.kt)("p",null,'The short address format is the most common address format used, and is often referred to as simply "address".'),(0,i.kt)("h4",{id:"synonyms-45"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#address"},"Address"))),(0,i.kt)("h4",{id:"see-also-181"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#code-hash"},"Code Hash")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#full-address"},"Full Address"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"simple-udt"},"Simple UDT"),(0,i.kt)("p",null,"A standard that defines a the most basic implementation of a UDT fungible token on Nervos. "),(0,i.kt)("p",null,"An SUDT on Nervos is the equivalent of Ethereum tokens standards ERC20 or ERC777."),(0,i.kt)("h4",{id:"synonyms-46"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#sudt"},"SUDT"))),(0,i.kt)("h4",{id:"see-also-182"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#udt"},"UDT")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#user-defined-token"},"User-Defined Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://eips.ethereum.org/EIPS/eip-20"},"ERC20 on Ethereum.org")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0025-simple-udt/0025-simple-udt.md"},"Simple UDT RFC on Nervos Nerwork Github"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"since"},"Since"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"since")," is the u64 (unsigned 64-bit integer) field in transaction input for preventing inclusion before a certain block timestamp or a block number."),(0,i.kt)("h4",{id:"see-also-183"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"spv"},"SPV"),(0,i.kt)("p",null,"An abbreviation for Simplified Payment Verification. A protocol for using a blockchain cryptocurrency without having to operate a full node."),(0,i.kt)("p",null,"SPV clients require far less data to be stored, but also must requires the trust of the network clients it is connected to directly."),(0,i.kt)("h4",{id:"see-also-184"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#spv-wallet"},"SPV Wallet")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.bitcoinwiki.org/wiki/Simplified_Payment_Verification"},"Simplified Payment Verification on BitcoinWiki"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"spv-wallet"},"SPV Wallet"),(0,i.kt)("p",null,"A light-weight cryptocurrency wallet that uses the SPV protocol."),(0,i.kt)("h4",{id:"see-also-185"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#spv"},"SPV"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"sudt"},"SUDT"),(0,i.kt)("p",null,"An abbreviation for Simple UDT."),(0,i.kt)("h4",{id:"synonyms-47"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#simple-udt"},"Simple UDT"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"testnet"},"Testnet"),(0,i.kt)("p",null,"Short for \u201ctest network,\u201d a network used to simulate the behavior of the ",(0,i.kt)("a",{parentName:"p",href:"#mainnet"},"Mainnet"),". The name of the Nervos CKB Testnet is ",(0,i.kt)("a",{parentName:"p",href:"#aggron"},"Aggron"),"."),(0,i.kt)("h4",{id:"synonyms-48"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#aggron"},"Aggron"))),(0,i.kt)("h4",{id:"not-to-be-confused-with-6"},"Not To Be Confused With"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lina"},"Lina")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mainnet"},"Mainnet"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"transaction-confirmation-number"},"Transaction Confirmation Number"),(0,i.kt)("p",null,"The number of confirmations required for a transaction to be added to a block. "),(0,i.kt)("p",null,"As permissionless blockchain designs offer only probabilistic finality, a transaction can never be fully confirmed, facing an adversary with infinite computational power. Therefore, users and apps can choose a number they deem secure. We briefly discuss one factor here that influences the level of security: the recent orphan rate. It takes 6 confirmations to fully settle a transaction when the orphan rate is 0, and 24 confirmations when the rate reaches 2.5% to achieve the same level of security (See the rationale and calculation ",(0,i.kt)("a",{parentName:"p",href:"https://docs.nervos.org/docs/essays/tx-confirmation/"},"here"),")."),(0,i.kt)("p",null,"In blockchain settlement assurance, transaction confirmation is one of the variables that cannot be easily quantified (See Nic Carter\u2019s ",(0,i.kt)("a",{parentName:"p",href:"https://medium.com/@nic__carter/its-the-settlement-assurances-stupid-5dcd1c3f4e41"},"article"),"). The exact number is open to adjustment depending on the security level that users desire. Nervos CKB sets a minimum of 15 confirmations, which should be considered conservative."),(0,i.kt)("h4",{id:"see-also-186"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#confirmation"},"Confirmation")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nc-max"},"NC-Max")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan-block"},"Orphan Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan-rate"},"Orphan Rate"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"transaction-hash"},"Transaction Hash"),(0,i.kt)("p",null,"Transaction hash, or Txhash, is the unique identifier of a transaction in a blockchain that acts as a record or proof that the transaction has taken place. To get a transaction hash in CKB, the transaction is serialized via Molecule, then the serialized raw is feed to ckbhash function. Its schema is:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"table Transaction {\n raw: RawTransaction,\n witnesses: BytesVec,\n}\n")),(0,i.kt)("p",null,"Transaction hash is generated by the serialized ",(0,i.kt)("inlineCode",{parentName:"p"},"raw")," structure through ",(0,i.kt)("a",{parentName:"p",href:"#ckbhash"},"ckbhash"),"."),(0,i.kt)("h4",{id:"see-also-187"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction-witness-hash"},"Transaction Witness Hash")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#molecule"},"Molecule")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbhash"},"Ckbhash")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0027-block-structure/0027-block-structure.md#transaction-hash"},"Transaction Hash in RFC on Nervos Network Github"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"transaction-witness-hash"},"Transaction Witness Hash"),(0,i.kt)("p",null,"Transaction witness hash is generated by the serialized transaction through ckbhash. Transaction is serialized via ",(0,i.kt)("a",{parentName:"p",href:"#molecule"},"molecule")," in CKB. Its schema is:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"table Transaction {\n raw: RawTransaction,\n witnesses: BytesVec,\n}\n")),(0,i.kt)("h4",{id:"see-also-188"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction-hash"},"Transaction Hash")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#molecule"},"Molecule")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbhash"},"Ckbhash"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"transaction-root"},"Transaction Root"),(0,i.kt)("p",null,"The field ",(0,i.kt)("inlineCode",{parentName:"p"},"transactions_root")," in header is"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"ckbhash(T || W)\n")),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},(0,i.kt)("inlineCode",{parentName:"p"},"ckbhash")," is the hash function, ",(0,i.kt)("inlineCode",{parentName:"p"},"||")," denotes binary concatenation.")),(0,i.kt)("p",null,"T is the root of a ",(0,i.kt)("a",{parentName:"p",href:"#ckb-merkle-tree"},"CKB Merkle Tree"),", which items are the ",(0,i.kt)("a",{parentName:"p",href:"#transaction-hash"},"transaction hashes")," of all the transactions in the block."),(0,i.kt)("p",null,"W is also the root of a ",(0,i.kt)("a",{parentName:"p",href:"#ckb-merkle-tree"},"CKB Merkle Tree"),", but the items are the ",(0,i.kt)("a",{parentName:"p",href:"#transaction-witness-hash"},"Transaction Witness Hash")," of all the transactions in the block."),(0,i.kt)("h4",{id:"see-also-189"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbhash"},"Ckbhash")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckb-merkle-tree"},"CKB Merkle Tree")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction-witness-hash"},"Transaction Witness Hash"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"tx_proposal_window"},(0,i.kt)("inlineCode",{parentName:"h3"},"tx_proposal_window")),(0,i.kt)("p",null,"Interval for submitting proposals in the second stage specified by NC-Max. Set between 2 and 10 blocks in CKB."),(0,i.kt)("img",{src:(0,o.Z)("img/tx-proposal-window.png")}),(0,i.kt)("p",null,"As shown above, when a transaction is first proposed in Block 13, it can be committed in the window between Block 15 and Block 23."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"pub(crate) const TX_PROPOSAL_WINDOW: ProposalWindow = ProposalWindow(2, 10);\n")),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"tx_version"},(0,i.kt)("inlineCode",{parentName:"h3"},"tx_version")),(0,i.kt)("p",null,"The version of a transaction. This field is set to 0 and is reserved for the system."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"pub const TX_VERSION: Version = 0;\n")),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"type_id"},(0,i.kt)("inlineCode",{parentName:"h3"},"type_id")),(0,i.kt)("p",null,"One of the CKB ",(0,i.kt)("inlineCode",{parentName:"p"},"system_scripts"),". A unique feature of Type ID is that it\u2018s a CKB built-in script directly implemented in Rust. It doesn't run in CKB-VM but can be used in the same way as other ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0024-ckb-genesis-script-list/0024-ckb-genesis-script-list.md#type-id"},"CKB genesis scripts"),"."),(0,i.kt)("p",null,"For a deeper understanding of Type ID, check out this blog post: ",(0,i.kt)("a",{parentName:"p",href:"https://xuejie.space/2020_02_03_introduction_to_ckb_script_programming_type_id/"},"Introduction to CKB Script Programming 6: Type ID")," (also translated into ",(0,i.kt)("a",{parentName:"p",href:"https://talk.nervos.org/t/ckb-type-id/4258"},"Chinese"),")."),(0,i.kt)("h4",{id:"see-also-190"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#script"},"Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script"},"Type Script"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"type_id_code_hash"},(0,i.kt)("inlineCode",{parentName:"h3"},"type_id_code_hash")),(0,i.kt)("p",null,"The ",(0,i.kt)("inlineCode",{parentName:"p"},"code_hash")," of ",(0,i.kt)("inlineCode",{parentName:"p"},"type_id"),". In view of the specificity of ",(0,i.kt)("inlineCode",{parentName:"p"},"type_id"),", ",(0,i.kt)("inlineCode",{parentName:"p"},"type_id_code_hash")," is hard-coded, not the hash of the actual code."),(0,i.kt)("h4",{id:"see-also-191"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#%60type_id%60"},(0,i.kt)("inlineCode",{parentName:"a"},"type_id")))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"type-script"},"Type Script"),(0,i.kt)("p",null,"A script that enforces the rules that must be followed in a transaction for a cell to be consumed as an input or for a cell to be created as an output."),(0,i.kt)("h4",{id:"see-also-192"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#script"},"Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script-hash"},"Type Script Hash"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"type-script-hash"},"Type Script Hash"),(0,i.kt)("p",null,"Or ",(0,i.kt)("inlineCode",{parentName:"p"},"type_hash"),", a Blake2b hash of a Type Script which is used as an identifier for the Script when referenced by a Cell."),(0,i.kt)("p",null,"The two entities in the data structure of CKB\u2019s cell are ",(0,i.kt)("inlineCode",{parentName:"p"},"lock")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"type"),". Type scripts can capture any validation logic needed in the cell transformation."),(0,i.kt)("p",null,"Type scripts can implement economic constructs as well. NervosDAO is completely implemented as a type script with minimal support from the consensus layer."),(0,i.kt)("h4",{id:"see-also-193"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#script"},"Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script"},"Type Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/ckb-system-scripts/blob/66d7da8ec72dffaa7e9c55904833951eca2422a9/c/dao.c"},"NervosDAO"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"uncle"},"Uncle"),(0,i.kt)("p",null,"Or Uncle Block. Uncle blocks are created when two blocks are mined and submitted to the ledger at roughly the same time. Only one can enter the ledger as an included block, and the other does not."),(0,i.kt)("p",null,"Uncles are paid a reduced block reward when they are found and reported."),(0,i.kt)("p",null,"On Nervos, Uncles are tracked by consensus to adjust the block interval of the network."),(0,i.kt)("p",null,"An uncle block has to meet the following conditions:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"An uncle should not be on the main chain; in other words, it should not be an uncle if it includes any block from the main chain."),(0,i.kt)("li",{parentName:"ul"},"Uncle\u2019s block number must be smaller than the block\u2018s number that later includes it."),(0,i.kt)("li",{parentName:"ul"},"Uncle\u2018s parent must be on the main chain, or uncle\u2019s parent must also be an uncle. In other words, uncle must be linkable to the main chain in any way. It can never be a random block that is not on the main chain.")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"- if !snapshot.is_main_chain(&uncle.hash()) // It should not be on the main chain.\n- && !snapshot.is_uncle(&uncle.hash()) // It should not be an uncle twice. \n- && uncle.number() < candidate_number // The block number of the uncle should be smaller than that of any block on the main chain. \n- && (uncles.iter().any(|u| u.hash() == parent_hash) \n|| snapshot.is_main_chain(&parent_hash) // Uncle block should not be parentless. The parent of un uncle must be a block on the main chain or another uncle. \n|| snapshot.is_uncle(&parent_hash))\n")),(0,i.kt)("img",{src:(0,o.Z)("img/uncle_rule.png")}),(0,i.kt)("p",null,"As illustrated above, A is the main chain. B3 can be the uncle of A4 (to be included in A4), since B3 is linked to A2. However, B4 cannot be included in A4, since the uncle\u2019s block number must be smaller than A4, the current block on the main chain."),(0,i.kt)("p",null,"Similarly, B4 can be the uncle of A5 (be included by A5). Although B4\u2018s parent, B3, is not on the main chain, B3 is the uncle of A4. For this reason, B4 is a legal uncle, and B3 cannot be included by A5."),(0,i.kt)("p",null,"C2 and C3 cannot be linked to the main chain as their parent is unknown, therefore, they cannot be uncles."),(0,i.kt)("h4",{id:"see-also-194"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#%60max_uncles_num%60"},(0,i.kt)("inlineCode",{parentName:"a"},"max_uncles_num")))),(0,i.kt)("h4",{id:"synonyms-49"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan-block"},"Orphan Block"))),(0,i.kt)("h4",{id:"see-also-195"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block-interval"},"Block Interval")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan-rate"},"Orphan Rate")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#uncle"},"Uncle"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"uncle-rate"},"Uncle Rate"),(0,i.kt)("h4",{id:"see-also-196"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan-rate"},"Orphan Rate")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#uncle"},"Uncle"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"validator"},"Validator"),(0,i.kt)("p",null,"A script that is used to ensure that the transactions created by the generators are valid. Validators are scripts that run in CKB-VM as either lock scripts or type scripts."),(0,i.kt)("h4",{id:"see-also-197"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckb-vm"},"CKB-VM")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script"},"Type Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"witness"},"Witness"),(0,i.kt)("p",null,"A set of cryptographic proof containing the data required to prove authorization of the resources used in the transaction."),(0,i.kt)("h4",{id:"see-also-198"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"zk-snark"},"Zk-SNARK"),(0,i.kt)("p",null,"A form of cryptographic proof, that when used in cryptocurrencies, allows for privacy features which do not reveal the amounts or participants in transactions."),(0,i.kt)("p",null,"Zk-SNARKs require a trusted setup, but are otherwise trustless."),(0,i.kt)("h4",{id:"see-also-199"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#zk-stark"},"Zk-STARK")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Non-interactive_zero-knowledge_proof"},"Non-interactive zero-knowledge proofs on Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"zk-stark"},"Zk-STARK"),(0,i.kt)("p",null,"A form of cryptographic proof, that when used in cryptocurrencies, allows for privacy features which do not reveal the amounts or participants in transactions."),(0,i.kt)("p",null,"Unlike Zk-SNARKs, Zk-STARKs do not require a trusted setup."),(0,i.kt)("h4",{id:"see-also-200"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#zk-snark"},"Zk-SNARK")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Non-interactive_zero-knowledge_proof"},"Non-interactive zero-knowledge proofs on Wikipedia"))),(0,i.kt)("hr",null))}m.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[7818],{3905:(e,t,a)=>{a.d(t,{Zo:()=>k,kt:()=>p});var l=a(7294);function n(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function i(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,l)}return a}function o(e){for(var t=1;t=0||(n[a]=e[a]);return n}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(l=0;l=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(n[a]=e[a])}return n}var s=l.createContext({}),u=function(e){var t=l.useContext(s),a=t;return e&&(a="function"==typeof e?e(t):o(o({},t),e)),a},k=function(e){var t=u(e.components);return l.createElement(s.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return l.createElement(l.Fragment,{},t)}},h=l.forwardRef((function(e,t){var a=e.components,n=e.mdxType,i=e.originalType,s=e.parentName,k=r(e,["components","mdxType","originalType","parentName"]),h=u(a),p=n,d=h["".concat(s,".").concat(p)]||h[p]||c[p]||i;return a?l.createElement(d,o(o({ref:t},k),{},{components:a})):l.createElement(d,o({ref:t},k))}));function p(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var i=a.length,o=new Array(i);o[0]=h;var r={};for(var s in t)hasOwnProperty.call(t,s)&&(r[s]=t[s]);r.originalType=e,r.mdxType="string"==typeof e?e:n,o[1]=r;for(var u=2;u{a.r(t),a.d(t,{assets:()=>h,contentTitle:()=>k,default:()=>m,frontMatter:()=>u,metadata:()=>c,toc:()=>p});var l=a(7462),n=a(3366),i=(a(7294),a(3905)),o=a(4996),r=a(9960),s=["components"],u={id:"glossary",title:"Glossary"},k=void 0,c={unversionedId:"basics/glossary",id:"basics/glossary",title:"Glossary",description:"Glossary Sections",source:"@site/docs/basics/glossary.md",sourceDirName:"basics",slug:"/basics/glossary",permalink:"/docs/basics/glossary",draft:!1,editUrl:"https://github.com/nervosnetwork/docs-new/tree/develop/website/docs/basics/glossary.md",tags:[],version:"current",frontMatter:{id:"glossary",title:"Glossary"},sidebar:"Basics",previous:{title:"Community Nodes",permalink:"/docs/basics/communitynodes"},next:{title:"General FAQ",permalink:"/docs/basics/faq/general"}},h={},p=[{value:"Glossary Sections",id:"glossary-sections",level:2},{value:"General Glossary",id:"general-glossary",level:2},{value:"Account",id:"account",level:3},{value:"Address",id:"address",level:3},{value:"Synonyms",id:"synonyms",level:4},{value:"Asset",id:"asset",level:3},{value:"Synonyms",id:"synonyms-1",level:4},{value:"Block",id:"block",level:3},{value:"See Also",id:"see-also",level:4},{value:"Block Height",id:"block-height",level:3},{value:"Synonyms",id:"synonyms-2",level:4},{value:"See Also",id:"see-also-1",level:4},{value:"Block Interval",id:"block-interval",level:3},{value:"Synonyms",id:"synonyms-3",level:4},{value:"See Also",id:"see-also-2",level:4},{value:"Block Propagation",id:"block-propagation",level:3},{value:"Synonyms",id:"synonyms-4",level:4},{value:"See Also",id:"see-also-3",level:4},{value:"Block Reward",id:"block-reward",level:3},{value:"See Also",id:"see-also-4",level:4},{value:"Block Time",id:"block-time",level:3},{value:"Synonyms",id:"synonyms-5",level:4},{value:"Blockchain",id:"blockchain",level:3},{value:"See Also",id:"see-also-5",level:4},{value:"BLS Signature",id:"bls-signature",level:3},{value:"See Also",id:"see-also-6",level:4},{value:"Broadcast",id:"broadcast",level:3},{value:"See Also",id:"see-also-7",level:4},{value:"Capacity",id:"capacity",level:3},{value:"Synonyms",id:"synonyms-6",level:4},{value:"See Also",id:"see-also-8",level:4},{value:"Cell",id:"cell",level:3},{value:"Synonyms",id:"synonyms-7",level:4},{value:"See Also",id:"see-also-9",level:4},{value:"Cell Model",id:"cell-model",level:3},{value:"See Also",id:"see-also-10",level:4},{value:"Censorship Resistance",id:"censorship-resistance",level:3},{value:"Chain",id:"chain",level:3},{value:"Synonyms",id:"synonyms-8",level:4},{value:"CKB",id:"ckb",level:3},{value:"Synonyms",id:"synonyms-9",level:4},{value:"CKByte",id:"ckbyte",level:3},{value:"Synonyms",id:"synonyms-10",level:4},{value:"Not To Be Confused With",id:"not-to-be-confused-with",level:4},{value:"CKB-VM",id:"ckb-vm",level:3},{value:"See Also",id:"see-also-11",level:4},{value:"Code Hash",id:"code-hash",level:3},{value:"See Also",id:"see-also-12",level:4},{value:"Cold Storage",id:"cold-storage",level:3},{value:"See Also",id:"see-also-13",level:4},{value:"Cold Wallet",id:"cold-wallet",level:3},{value:"See Also",id:"see-also-14",level:4},{value:"Commit",id:"commit",level:3},{value:"Commit-Chain",id:"commit-chain",level:3},{value:"Commit Reward",id:"commit-reward",level:3},{value:"Common Knowledge Base",id:"common-knowledge-base",level:3},{value:"Synonyms",id:"synonyms-11",level:4},{value:"Not To Be Confused With",id:"not-to-be-confused-with-1",level:4},{value:"See Also",id:"see-also-15",level:4},{value:"Common Knowledge Byte",id:"common-knowledge-byte",level:3},{value:"Synonyms",id:"synonyms-12",level:4},{value:"Not To Be Confused With",id:"not-to-be-confused-with-2",level:4},{value:"See Also",id:"see-also-16",level:4},{value:"Confirmation",id:"confirmation",level:3},{value:"See Also",id:"see-also-17",level:4},{value:"Consensus",id:"consensus",level:3},{value:"See Also",id:"see-also-18",level:4},{value:"Consume",id:"consume",level:3},{value:"Contract Account",id:"contract-account",level:3},{value:"See Also",id:"see-also-19",level:4},{value:"Cryptocurrency",id:"cryptocurrency",level:3},{value:"See Also",id:"see-also-20",level:4},{value:"Cryptographic Signature",id:"cryptographic-signature",level:3},{value:"Synonyms",id:"synonyms-13",level:4},{value:"Cryptography",id:"cryptography",level:3},{value:"See Also",id:"see-also-21",level:4},{value:"Cycles",id:"cycles",level:3},{value:"See Also",id:"see-also-22",level:4},{value:"DAO",id:"dao",level:3},{value:"See Also",id:"see-also-23",level:4},{value:"DApp",id:"dapp",level:3},{value:"Data",id:"data",level:3},{value:"See Also",id:"see-also-24",level:4},{value:"Decentralization",id:"decentralization",level:3},{value:"See Also",id:"see-also-25",level:4},{value:"DeFi",id:"defi",level:3},{value:"Digital Asset",id:"digital-asset",level:3},{value:"Synonyms",id:"synonyms-14",level:4},{value:"Digital Currency",id:"digital-currency",level:3},{value:"See Also",id:"see-also-26",level:4},{value:"Distributed",id:"distributed",level:3},{value:"See Also",id:"see-also-27",level:4},{value:"Double-Spending",id:"double-spending",level:3},{value:"See Also",id:"see-also-28",level:4},{value:"Epoch",id:"epoch",level:3},{value:"See Also",id:"see-also-29",level:4},{value:"Fee",id:"fee",level:3},{value:"See Also",id:"see-also-30",level:4},{value:"Fee Rate",id:"fee-rate",level:3},{value:"See Also",id:"see-also-31",level:4},{value:"First-Class Assets",id:"first-class-assets",level:3},{value:"See Also",id:"see-also-32",level:4},{value:"Fork",id:"fork",level:3},{value:"Full Node",id:"full-node",level:3},{value:"See Also",id:"see-also-33",level:4},{value:"Full Payload Format",id:"full-payload-format",level:3},{value:"See Also",id:"see-also-34",level:4},{value:"Fungible Token",id:"fungible-token",level:3},{value:"See Also",id:"see-also-35",level:4},{value:"Gas Limit",id:"gas-limit",level:3},{value:"See Also",id:"see-also-36",level:4},{value:"Hard-Fork",id:"hard-fork",level:3},{value:"Hardware Wallet",id:"hardware-wallet",level:3},{value:"See Also",id:"see-also-37",level:4},{value:"Hash",id:"hash",level:3},{value:"Hash Rate",id:"hash-rate",level:3},{value:"See Also",id:"see-also-38",level:4},{value:"Height",id:"height",level:3},{value:"Synonyms",id:"synonyms-15",level:4},{value:"Light Client",id:"light-client",level:3},{value:"Light Node",id:"light-node",level:3},{value:"See Also",id:"see-also-39",level:4},{value:"Mempool",id:"mempool",level:3},{value:"See Also",id:"see-also-40",level:4},{value:"Metadata",id:"metadata",level:3},{value:"See Also",id:"see-also-41",level:4},{value:"Micro-State",id:"micro-state",level:3},{value:"Synonyms",id:"synonyms-16",level:4},{value:"See Also",id:"see-also-42",level:4},{value:"Miner",id:"miner",level:3},{value:"See Also",id:"see-also-43",level:4},{value:"Miner Fee",id:"miner-fee",level:3},{value:"Synonyms",id:"synonyms-17",level:4},{value:"Mining",id:"mining",level:3},{value:"See Also",id:"see-also-44",level:4},{value:"Mining Node",id:"mining-node",level:3},{value:"See Also",id:"see-also-45",level:4},{value:"Mining Reward",id:"mining-reward",level:3},{value:"See Also",id:"see-also-46",level:4},{value:"Multisig",id:"multisig",level:3},{value:"Native Token",id:"native-token",level:3},{value:"See Also",id:"see-also-47",level:4},{value:"NC-MAX",id:"nc-max",level:3},{value:"See Also",id:"see-also-48",level:4},{value:"Neighbor",id:"neighbor",level:3},{value:"See Also",id:"see-also-49",level:4},{value:"Nervos Blockchain",id:"nervos-blockchain",level:3},{value:"Synonyms",id:"synonyms-18",level:4},{value:"Nervos DAO",id:"nervos-dao",level:3},{value:"See Also",id:"see-also-50",level:4},{value:"Network Hash Rate",id:"network-hash-rate",level:3},{value:"See Also",id:"see-also-51",level:4},{value:"Node",id:"node",level:3},{value:"See Also",id:"see-also-52",level:4},{value:"Nonce",id:"nonce",level:3},{value:"See Also",id:"see-also-53",level:4},{value:"Non-Fungible Token",id:"non-fungible-token",level:3},{value:"See Also",id:"see-also-54",level:4},{value:"Open Source",id:"open-source",level:3},{value:"See Also",id:"see-also-55",level:4},{value:"P2P",id:"p2p",level:3},{value:"Synonyms",id:"synonyms-19",level:4},{value:"Paper Wallet",id:"paper-wallet",level:3},{value:"See Also",id:"see-also-56",level:4},{value:"Payment Address",id:"payment-address",level:3},{value:"Synonyms",id:"synonyms-20",level:4},{value:"Payment Channel",id:"payment-channel",level:3},{value:"See Also",id:"see-also-57",level:4},{value:"Peer to Peer",id:"peer-to-peer",level:3},{value:"Synonyms",id:"synonyms-21",level:4},{value:"See Also",id:"see-also-58",level:4},{value:"Private Key",id:"private-key",level:3},{value:"See Also",id:"see-also-59",level:4},{value:"Proof of Work",id:"proof-of-work",level:3},{value:"See Also",id:"see-also-60",level:4},{value:"Proof of Stake",id:"proof-of-stake",level:3},{value:"See Also",id:"see-also-61",level:4},{value:"Propagation",id:"propagation",level:3},{value:"Synonyms",id:"synonyms-22",level:4},{value:"Public Key",id:"public-key",level:3},{value:"See Also",id:"see-also-62",level:4},{value:"Reward",id:"reward",level:3},{value:"See Also",id:"see-also-63",level:4},{value:"Signature",id:"signature",level:3},{value:"Synonyms",id:"synonyms-23",level:4},{value:"Smart Contract",id:"smart-contract",level:3},{value:"State",id:"state",level:3},{value:"See Also",id:"see-also-64",level:4},{value:"State Bloat",id:"state-bloat",level:3},{value:"State Channel",id:"state-channel",level:3},{value:"Tip",id:"tip",level:3},{value:"Synonyms",id:"synonyms-24",level:4},{value:"Tip Block",id:"tip-block",level:3},{value:"Synonyms",id:"synonyms-25",level:4},{value:"See Also",id:"see-also-65",level:4},{value:"Transaction",id:"transaction",level:3},{value:"See Also",id:"see-also-66",level:4},{value:"Transaction Fee",id:"transaction-fee",level:3},{value:"Synonyms",id:"synonyms-26",level:4},{value:"See Also",id:"see-also-67",level:4},{value:"Token",id:"token",level:3},{value:"See Also",id:"see-also-68",level:4},{value:"Turing Complete",id:"turing-complete",level:3},{value:"UDT",id:"udt",level:3},{value:"Synonyms",id:"synonyms-27",level:4},{value:"Unconfirmed",id:"unconfirmed",level:3},{value:"Synonyms",id:"synonyms-28",level:4},{value:"See Also",id:"see-also-69",level:4},{value:"Unconfirmed Transaction",id:"unconfirmed-transaction",level:3},{value:"Synonyms",id:"synonyms-29",level:4},{value:"See Also",id:"see-also-70",level:4},{value:"User-Defined Token",id:"user-defined-token",level:3},{value:"Synonyms",id:"synonyms-30",level:4},{value:"See Also",id:"see-also-71",level:4},{value:"Wallet",id:"wallet",level:3},{value:"See Also",id:"see-also-72",level:4},{value:"Economics Glossary",id:"economics-glossary",level:2},{value:"Base Issuance",id:"base-issuance",level:3},{value:"See Also",id:"see-also-73",level:4},{value:"Base Reward",id:"base-reward",level:3},{value:"See Also",id:"see-also-74",level:4},{value:"Commit Reward",id:"commit-reward-1",level:3},{value:"See Also",id:"see-also-75",level:4},{value:"Economic Abstraction",id:"economic-abstraction",level:3},{value:"Fiat Currency",id:"fiat-currency",level:3},{value:"See Also",id:"see-also-76",level:4},{value:"Heavy Asset Problem",id:"heavy-asset-problem",level:3},{value:"See Also",id:"see-also-77",level:4},{value:"Liquidity",id:"liquidity",level:3},{value:"See Also",id:"see-also-78",level:4},{value:"Proposal Reward",id:"proposal-reward",level:3},{value:"See Also",id:"see-also-79",level:4},{value:"Secondary Issuance",id:"secondary-issuance",level:3},{value:"See Also",id:"see-also-80",level:4},{value:"Secondary Reward",id:"secondary-reward",level:3},{value:"See Also",id:"see-also-81",level:4},{value:"Selfish Mining Attack",id:"selfish-mining-attack",level:3},{value:"See Also",id:"see-also-82",level:4},{value:"Starving Layer 1 Problem",id:"starving-layer-1-problem",level:3},{value:"See Also",id:"see-also-83",level:4},{value:"State Rent",id:"state-rent",level:3},{value:"See Also",id:"see-also-84",level:4},{value:"Store of Assets",id:"store-of-assets",level:3},{value:"See Also",id:"see-also-85",level:4},{value:"Store of Value",id:"store-of-value",level:3},{value:"See Also",id:"see-also-86",level:4},{value:"Tail Emission",id:"tail-emission",level:3},{value:"See Also",id:"see-also-87",level:4},{value:"Targeted Inflation",id:"targeted-inflation",level:3},{value:"See Also",id:"see-also-88",level:4},{value:"Tragedy of the Commons",id:"tragedy-of-the-commons",level:3},{value:"See Also",id:"see-also-89",level:4},{value:"Tragedy of the Security Commons",id:"tragedy-of-the-security-commons",level:3},{value:"See Also",id:"see-also-90",level:4},{value:"Tragedy of the Storage Commons",id:"tragedy-of-the-storage-commons",level:3},{value:"See Also",id:"see-also-91",level:4},{value:"Technical Glossary",id:"technical-glossary",level:2},{value:"Active Cell",id:"active-cell",level:3},{value:"Synonyms",id:"synonyms-31",level:4},{value:"See Also",id:"see-also-92",level:4},{value:"Aggron",id:"aggron",level:3},{value:"Synonyms",id:"synonyms-32",level:4},{value:"Not To Be Confused With",id:"not-to-be-confused-with-3",level:4},{value:"Animagus",id:"animagus",level:3},{value:"See Also",id:"see-also-93",level:4},{value:"Args",id:"args",level:3},{value:"See Also",id:"see-also-94",level:4},{value:"Axon",id:"axon",level:3},{value:"See Also",id:"see-also-95",level:4},{value:"Blake2b",id:"blake2b",level:3},{value:"See Also",id:"see-also-96",level:4},{value:"Block Subsidy",id:"block-subsidy",level:3},{value:"Synonyms",id:"synonyms-33",level:4},{value:"Boxer",id:"boxer",level:3},{value:"See Also",id:"see-also-97",level:4},{value:"block_version",id:"block_version",level:3},{value:"See Also",id:"see-also-98",level:4},{value:"Cell Collection",id:"cell-collection",level:3},{value:"See Also",id:"see-also-99",level:4},{value:"Cellbase",id:"cellbase",level:3},{value:"See Also",id:"see-also-100",level:4},{value:"cellbase_maturity",id:"cellbase_maturity",level:3},{value:"See Also",id:"see-also-101",level:4},{value:"cell_deps",id:"cell_deps",level:3},{value:"See Also",id:"see-also-102",level:4},{value:"Ckbhash",id:"ckbhash",level:3},{value:"See Also",id:"see-also-103",level:4},{value:"CKB Merkle Tree",id:"ckb-merkle-tree",level:3},{value:"See Also",id:"see-also-104",level:4},{value:"Code Hash",id:"code-hash-1",level:3},{value:"See Also",id:"see-also-105",level:4},{value:"Commit",id:"commit-1",level:3},{value:"See Also",id:"see-also-106",level:4},{value:"Commitment Zone",id:"commitment-zone",level:3},{value:"See Also",id:"see-also-107",level:4},{value:"Consume",id:"consume-1",level:3},{value:"See Also",id:"see-also-108",level:4},{value:"Crypto Primitives",id:"crypto-primitives",level:3},{value:"See Also",id:"see-also-109",level:4},{value:"dao_type_hash",id:"dao_type_hash",level:3},{value:"See Also",id:"see-also-110",level:4},{value:"Data",id:"data-1",level:3},{value:"See Also",id:"see-also-111",level:4},{value:"Dead Cell",id:"dead-cell",level:3},{value:"Synonyms",id:"synonyms-34",level:4},{value:"See Also",id:"see-also-112",level:4},{value:"Dep Group",id:"dep-group",level:3},{value:"See Also",id:"see-also-113",level:4},{value:"Dep Type",id:"dep-type",level:3},{value:"See Also",id:"see-also-114",level:4},{value:"Deps",id:"deps",level:3},{value:"Synonyms",id:"synonyms-35",level:4},{value:"Dependencies",id:"dependencies",level:3},{value:"Synonyms",id:"synonyms-36",level:4},{value:"See Also",id:"see-also-115",level:4},{value:"Duktape",id:"duktape",level:3},{value:"See Also",id:"see-also-116",level:4},{value:"Difficulty",id:"difficulty",level:3},{value:"See Also",id:"see-also-117",level:4},{value:"Diviner",id:"diviner",level:3},{value:"See Also",id:"see-also-118",level:4},{value:"Eaglesong",id:"eaglesong",level:3},{value:"See Also",id:"see-also-119",level:4},{value:"epoch_duration_target",id:"epoch_duration_target",level:3},{value:"See Also",id:"see-also-120",level:4},{value:"ERC20",id:"erc20",level:3},{value:"See Also",id:"see-also-121",level:4},{value:"ERC721",id:"erc721",level:3},{value:"See Also",id:"see-also-122",level:4},{value:"ERC777",id:"erc777",level:3},{value:"See Also",id:"see-also-123",level:4},{value:"ERC1155",id:"erc1155",level:3},{value:"See Also",id:"see-also-124",level:4},{value:"Full Address",id:"full-address",level:3},{value:"See Also",id:"see-also-125",level:4},{value:"Generator",id:"generator",level:3},{value:"Genesis Block",id:"genesis-block",level:3},{value:"See Also",id:"see-also-126",level:4},{value:"genesis_hash",id:"genesis_hash",level:3},{value:"See Also",id:"see-also-127",level:4},{value:"Godwoken",id:"godwoken",level:3},{value:"See Also",id:"see-also-128",level:4},{value:"Governance Script",id:"governance-script",level:3},{value:"See Also",id:"see-also-129",level:4},{value:"Governance Script Hash",id:"governance-script-hash",level:3},{value:"Synonyms",id:"synonyms-37",level:4},{value:"See Also",id:"see-also-130",level:4},{value:"Historical Cell",id:"historical-cell",level:3},{value:"Synonyms",id:"synonyms-38",level:4},{value:"See Also",id:"see-also-131",level:4},{value:"Inbound Connection",id:"inbound-connection",level:3},{value:"See Also",id:"see-also-132",level:4},{value:"Indexer",id:"indexer",level:3},{value:"See Also",id:"see-also-133",level:4},{value:"initial_primary_epoch_reward",id:"initial_primary_epoch_reward",level:3},{value:"See Also",id:"see-also-134",level:4},{value:"Input",id:"input",level:3},{value:"See Also",id:"see-also-135",level:4},{value:"Keyper",id:"keyper",level:3},{value:"See Also",id:"see-also-136",level:4},{value:"Late Spawning",id:"late-spawning",level:3},{value:"See Also",id:"see-also-137",level:4},{value:"Layer 1",id:"layer-1",level:3},{value:"See Also",id:"see-also-138",level:4},{value:"Layer 2",id:"layer-2",level:3},{value:"See Also",id:"see-also-139",level:4},{value:"Lina",id:"lina",level:3},{value:"Synonyms",id:"synonyms-39",level:4},{value:"Not To Be Confused With",id:"not-to-be-confused-with-4",level:4},{value:"See Also",id:"see-also-140",level:4},{value:"Live Cell",id:"live-cell",level:3},{value:"Synonyms",id:"synonyms-40",level:4},{value:"See Also",id:"see-also-141",level:4},{value:"Lock",id:"lock",level:3},{value:"See Also",id:"see-also-142",level:4},{value:"Lock Script",id:"lock-script",level:3},{value:"See Also",id:"see-also-143",level:4},{value:"Lock Script Hash",id:"lock-script-hash",level:3},{value:"See Also",id:"see-also-144",level:4},{value:"Mainnet",id:"mainnet",level:3},{value:"Synonyms",id:"synonyms-41",level:4},{value:"Not To Be Confused With",id:"not-to-be-confused-with-5",level:4},{value:"max_block_bytes",id:"max_block_bytes",level:3},{value:"max_block_cycles",id:"max_block_cycles",level:3},{value:"See Also",id:"see-also-145",level:4},{value:"max_block_proposals_limit",id:"max_block_proposals_limit",level:3},{value:"See Also",id:"see-also-146",level:4},{value:"max_uncles_num",id:"max_uncles_num",level:3},{value:"See Also",id:"see-also-147",level:4},{value:"median_time_block_count",id:"median_time_block_count",level:3},{value:"Minting",id:"minting",level:3},{value:"See Also",id:"see-also-148",level:4},{value:"Molecule",id:"molecule",level:3},{value:"See Also",id:"see-also-149",level:4},{value:"Muta",id:"muta",level:3},{value:"See Also",id:"see-also-150",level:4},{value:"Nervos CKB",id:"nervos-ckb",level:3},{value:"Synonyms",id:"synonyms-42",level:4},{value:"See Also",id:"see-also-151",level:4},{value:"Off-Chain Computation",id:"off-chain-computation",level:3},{value:"See Also",id:"see-also-152",level:4},{value:"Off-Chain Scaling",id:"off-chain-scaling",level:3},{value:"See Also",id:"see-also-153",level:4},{value:"Off-Chain State",id:"off-chain-state",level:3},{value:"See Also",id:"see-also-154",level:4},{value:"On-Chain Computation",id:"on-chain-computation",level:3},{value:"See Also",id:"see-also-155",level:4},{value:"On-Chain Scaling",id:"on-chain-scaling",level:3},{value:"See Also",id:"see-also-156",level:4},{value:"On-Chain State",id:"on-chain-state",level:3},{value:"See Also",id:"see-also-157",level:4},{value:"On-Chain Verification",id:"on-chain-verification",level:3},{value:"See Also",id:"see-also-158",level:4},{value:"Open Transaction",id:"open-transaction",level:3},{value:"See Also",id:"see-also-159",level:4},{value:"Optimistic Rollup",id:"optimistic-rollup",level:3},{value:"See Also",id:"see-also-160",level:4},{value:"Orphan",id:"orphan",level:3},{value:"Synonyms",id:"synonyms-43",level:4},{value:"Orphan Block",id:"orphan-block",level:3},{value:"Synonyms",id:"synonyms-44",level:4},{value:"See Also",id:"see-also-161",level:4},{value:"Orphan Rate",id:"orphan-rate",level:3},{value:"See Also",id:"see-also-162",level:4},{value:"orphan_rate_target",id:"orphan_rate_target",level:3},{value:"See Also",id:"see-also-163",level:4},{value:"Orphan Transactions",id:"orphan-transactions",level:3},{value:"See Also",id:"see-also-164",level:4},{value:"Outbound Connection",id:"outbound-connection",level:3},{value:"See Also",id:"see-also-165",level:4},{value:"Outpoint",id:"outpoint",level:3},{value:"See Also",id:"see-also-166",level:4},{value:"Output",id:"output",level:3},{value:"See Also",id:"see-also-167",level:4},{value:"Overlord",id:"overlord",level:3},{value:"See Also",id:"see-also-168",level:4},{value:"P2WSH",id:"p2wsh",level:3},{value:"permanent_difficulty_in_dummy",id:"permanent_difficulty_in_dummy",level:3},{value:"See Also",id:"see-also-169",level:4},{value:"Polyjuice",id:"polyjuice",level:3},{value:"See Also",id:"see-also-170",level:4},{value:"primary_epoch_reward_halving_interval",id:"primary_epoch_reward_halving_interval",level:3},{value:"See Also",id:"see-also-171",level:4},{value:"Proposal Zone",id:"proposal-zone",level:3},{value:"See Also",id:"see-also-172",level:4},{value:"Propose",id:"propose",level:3},{value:"See Also",id:"see-also-173",level:4},{value:"proposer_reward_ratio",id:"proposer_reward_ratio",level:3},{value:"See Also",id:"see-also-174",level:4},{value:"RISC-V",id:"risc-v",level:3},{value:"See Also",id:"see-also-175",level:4},{value:"Schnorr Signature",id:"schnorr-signature",level:3},{value:"See Also",id:"see-also-176",level:4},{value:"Script",id:"script",level:3},{value:"See Also",id:"see-also-177",level:4},{value:"secondary_epoch_reward",id:"secondary_epoch_reward",level:3},{value:"See also",id:"see-also-178",level:4},{value:"secp256k1_blake160_sighash_all_type_hash",id:"secp256k1_blake160_sighash_all_type_hash",level:3},{value:"secp256k1_blake160_multisig_all_type_hash",id:"secp256k1_blake160_multisig_all_type_hash",level:3},{value:"Seed Cell",id:"seed-cell",level:3},{value:"See Also",id:"see-also-179",level:4},{value:"Shannon",id:"shannon",level:3},{value:"See Also",id:"see-also-180",level:4},{value:"Short Address",id:"short-address",level:3},{value:"Synonyms",id:"synonyms-45",level:4},{value:"See Also",id:"see-also-181",level:4},{value:"Simple UDT",id:"simple-udt",level:3},{value:"Synonyms",id:"synonyms-46",level:4},{value:"See Also",id:"see-also-182",level:4},{value:"Since",id:"since",level:3},{value:"See Also",id:"see-also-183",level:4},{value:"SPV",id:"spv",level:3},{value:"See Also",id:"see-also-184",level:4},{value:"SPV Wallet",id:"spv-wallet",level:3},{value:"See Also",id:"see-also-185",level:4},{value:"SUDT",id:"sudt",level:3},{value:"Synonyms",id:"synonyms-47",level:4},{value:"Testnet",id:"testnet",level:3},{value:"Synonyms",id:"synonyms-48",level:4},{value:"Not To Be Confused With",id:"not-to-be-confused-with-6",level:4},{value:"Transaction Confirmation Number",id:"transaction-confirmation-number",level:3},{value:"See Also",id:"see-also-186",level:4},{value:"Transaction Hash",id:"transaction-hash",level:3},{value:"See Also",id:"see-also-187",level:4},{value:"Transaction Witness Hash",id:"transaction-witness-hash",level:3},{value:"See Also",id:"see-also-188",level:4},{value:"Transaction Root",id:"transaction-root",level:3},{value:"See Also",id:"see-also-189",level:4},{value:"tx_proposal_window",id:"tx_proposal_window",level:3},{value:"tx_version",id:"tx_version",level:3},{value:"type_id",id:"type_id",level:3},{value:"See Also",id:"see-also-190",level:4},{value:"type_id_code_hash",id:"type_id_code_hash",level:3},{value:"See Also",id:"see-also-191",level:4},{value:"Type Script",id:"type-script",level:3},{value:"See Also",id:"see-also-192",level:4},{value:"Type Script Hash",id:"type-script-hash",level:3},{value:"See Also",id:"see-also-193",level:4},{value:"Uncle",id:"uncle",level:3},{value:"See Also",id:"see-also-194",level:4},{value:"Synonyms",id:"synonyms-49",level:4},{value:"See Also",id:"see-also-195",level:4},{value:"Uncle Rate",id:"uncle-rate",level:3},{value:"See Also",id:"see-also-196",level:4},{value:"Validator",id:"validator",level:3},{value:"See Also",id:"see-also-197",level:4},{value:"Witness",id:"witness",level:3},{value:"See Also",id:"see-also-198",level:4},{value:"Zk-SNARK",id:"zk-snark",level:3},{value:"See Also",id:"see-also-199",level:4},{value:"Zk-STARK",id:"zk-stark",level:3},{value:"See Also",id:"see-also-200",level:4}],d={toc:p};function m(e){var t=e.components,a=(0,n.Z)(e,s);return(0,i.kt)("wrapper",(0,l.Z)({},d,a,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"glossary-sections"},"Glossary Sections"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#general-glossary"},"General Glossary")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#economics-glossary"},"Economics Glossary")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#technical-glossary"},"Technical Glossary"))),(0,i.kt)("hr",null),(0,i.kt)("h2",{id:"general-glossary"},"General Glossary"),(0,i.kt)("h3",{id:"account"},"Account"),(0,i.kt)("p",null,"A kind of basic object in distributed ledger used to keep the balance and other information of users."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"address"},"Address"),(0,i.kt)("p",null,"A label consists of string of letters and numbers that anonymously represents user's identity on chain. Crypto assets can be sent to and/or from addresses."),(0,i.kt)("h4",{id:"synonyms"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#payment-address"},"Payment Address"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"asset"},"Asset"),(0,i.kt)("p",null,"A piece of data that has value or that represents an entity having value."),(0,i.kt)("h4",{id:"synonyms-1"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#digital-asset"},"Digital Asset")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"block"},"Block"),(0,i.kt)("p",null,"A grouping of transactions, marked with a timestamp, and a fingerprint of the previous block. The block header is hashed to produce a proof of work, thereby validating the transactions. Valid blocks are added to the main blockchain by network consensus."),(0,i.kt)("h4",{id:"see-also"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blockchain"},"Blockchain")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#confirmation"},"Confirmation")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"block-height"},"Block Height"),(0,i.kt)("p",null,"Block height is the total number of blocks that have been confirmed on the blockchain, also used to identify a unique block when specifying a particular block height, as there is always an exact block at any block height."),(0,i.kt)("h4",{id:"synonyms-2"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#height"},"Height"))),(0,i.kt)("h4",{id:"see-also-1"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blockchain"},"Blockchain")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#confirmation"},"Confirmation"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"block-interval"},"Block Interval"),(0,i.kt)("p",null,"Also known as ",(0,i.kt)("a",{parentName:"p",href:"#block-time"},"Block Time"),". Block interval is the length of time it takes to create a new block in a cryptocurrency blockchain. Block interval is the measure of the time it takes the miners or validators within a network to verify transactions within one block and produce a new block in that blockchain. The block interval is variable on Nervos blockchain."),(0,i.kt)("p",null,"The block interval on the Bitcoin blockchain is approximately every 10 minutes. The block interval on Nervos is variable, but is usually under 10 seconds."),(0,i.kt)("h4",{id:"synonyms-3"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block-time"},"Block Time"))),(0,i.kt)("h4",{id:"see-also-2"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blockchain"},"Blockchain"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"block-propagation"},"Block Propagation"),(0,i.kt)("p",null,"The process of synchronizing a new block to the majority of full nodes in the network. Block propagation is a well-known bottleneck that prevents Bitcoin from scaling. "),(0,i.kt)("p",null,"Block propagation time is an average time that is needed for the new block to reach the majority of nodes in the network. Long block propagation delay reduces the node's resistance against 51% attacks."),(0,i.kt)("h4",{id:"synonyms-4"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#propagation"},"Propagation"))),(0,i.kt)("h4",{id:"see-also-3"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#broadcast"},"Broadcast")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#full-node"},"Full Node"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"block-reward"},"Block Reward"),(0,i.kt)("p",null,"The amount of cryptocurrency credited to a miner's account after the miner successfully adds a block of transactions to the blockchain. "),(0,i.kt)("p",null,"In Nervos CKB, block rewards are the CKBytes credited to a miner's account after a block is successfully added to CKB by the miner."),(0,i.kt)("h4",{id:"see-also-4"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block-subsidy"},"Block Subsidy"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"block-time"},"Block Time"),(0,i.kt)("p",null,"Alternatively referred to as ",(0,i.kt)("a",{parentName:"p",href:"#block-interval"},"Block Interval"),"."),(0,i.kt)("h4",{id:"synonyms-5"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block-interval"},"Block Interval"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"blockchain"},"Blockchain"),(0,i.kt)("p",null,"A data structure maintaining a growing list of records, organized as a chain of blocks. Each block, apart from the first one, is cryptographically linked to the previous block, thus creating a chain-like structure. "),(0,i.kt)("p",null,"The cryptographic link ensures any party with the last block can verify that none of the historical data is modified after the creation of this block."),(0,i.kt)("h4",{id:"see-also-5"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"bls-signature"},"BLS Signature"),(0,i.kt)("p",null,"A cryptographic signature scheme for signing and verification. BLS is short for Boneh\u2013Lynn\u2013Shacham."),(0,i.kt)("h4",{id:"see-also-6"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Boneh%E2%80%93Lynn%E2%80%93Shacham"},"Boneh\u2013Lynn\u2013Shacham on Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"broadcast"},"Broadcast"),(0,i.kt)("p",null,"Blocks are sent to all nodes in a blockchain network."),(0,i.kt)("h4",{id:"see-also-7"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blockchain"},"Blockchain")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#node"},"Node"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"capacity"},"Capacity"),(0,i.kt)("p",null,"The maximum space (in bytes) that a cell can occupy on the Nervos CKB."),(0,i.kt)("h4",{id:"synonyms-6"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte"))),(0,i.kt)("h4",{id:"see-also-8"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckb"},"CKB")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-base"},"Common Knowledge Base")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-byte"},"Common Knowledge Byte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-blockchain"},"Nervos Blockchain"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cell"},"Cell"),(0,i.kt)("p",null,"All data on Nervos CKB is stored in cells. Cells are the primary state units in CKB, within them users can include arbitrary states. "),(0,i.kt)("p",null,"A cell has 4 fields: ",(0,i.kt)("inlineCode",{parentName:"p"},"capacity"),", ",(0,i.kt)("inlineCode",{parentName:"p"},"data"),", ",(0,i.kt)("inlineCode",{parentName:"p"},"type")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"lock"),"."),(0,i.kt)("h4",{id:"synonyms-7"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#micro-state"},"Micro-State"))),(0,i.kt)("h4",{id:"see-also-9"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#data"},"Data")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock"},"Lock")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script"},"Type Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#dead-cell"},"Dead Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#live-cell"},"Live Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)(r.Z,{to:(0,o.Z)("/docs/basics/concepts/cell-model"),mdxType:"Link"},"Cell Model in Key Concepts")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://developer.bitcoin.org/glossary.html"},"UTXO on Bitcoin.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cell-model"},"Cell Model"),(0,i.kt)("p",null,"A representation of how state is managed on Nervos CKB. The cell model is a more generic state model than either Bitcoin's UTXO or Ethereum's account model. "),(0,i.kt)("p",null,"The cell model is a new construction that combines many of the advantages of Ethereum's account model with the asset ownership and proof-based verification properties of Bitcoin's UTXO model."),(0,i.kt)("h4",{id:"see-also-10"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script"},"Type Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)(r.Z,{to:(0,o.Z)("/docs/basics/concepts/cell-model"),mdxType:"Link"},"Cell Model in Key Concepts")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://medium.com/nervosnetwork/https-medium-com-nervosnetwork-cell-model-7323fca57571"},"Cell Model on the Nervos Blog")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://developer.bitcoin.org/glossary.html"},"UTXO on Bitcoin.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"censorship-resistance"},"Censorship Resistance"),(0,i.kt)("p",null,"Censorship resistance in blockchain generally means that it is difficult for a malicious party to prevent the blockchain from confirming a set of transactions generated by honest users."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"chain"},"Chain"),(0,i.kt)("p",null,"A shorthand name for blockchain."),(0,i.kt)("h4",{id:"synonyms-8"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blockchain"},"Blockchain"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"ckb"},"CKB"),(0,i.kt)("p",null,"An abbreviation which can have different meanings depending on the context:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Common Knowledge Base - The layer 1 blockchain of the Nervos Network."),(0,i.kt)("li",{parentName:"ul"},"Common Knowledge Byte - The native token of the Nervos Common Knowledge Base.")),(0,i.kt)("h4",{id:"synonyms-9"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-base"},"Common Knowledge Base")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-byte"},"Common Knowledge Byte"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"ckbyte"},"CKByte"),(0,i.kt)("p",null,"A shorthand name for Common Knowledge Byte."),(0,i.kt)("p",null,"CKByte is also sometimes shortened to CKB. Exchanges often use CKB as the ticker symbol."),(0,i.kt)("h4",{id:"synonyms-10"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckb"},"CKB")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-byte"},"Common Knowledge Byte"))),(0,i.kt)("h4",{id:"not-to-be-confused-with"},"Not To Be Confused With"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-base"},"Common Knowledge Base"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"ckb-vm"},"CKB-VM"),(0,i.kt)("p",null,"CKB VM is a crypto-agnostic virtual machine, a RISC-V instruction set based VM for executing both on-chain and off-chain code."),(0,i.kt)("h4",{id:"see-also-11"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#risc-v"},"RISC-V")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#script"},"Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Virtual_machine"},"Virtual Machine on Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"code-hash"},"Code Hash"),(0,i.kt)("p",null,"A field in a cell which contains a hash value that can refer to a specific piece of data, or a specific cell referenced by Type ID."),(0,i.kt)("h4",{id:"see-also-12"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-id"},"Type ID"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cold-storage"},"Cold Storage"),(0,i.kt)("p",null,"A method of securing funds by placing them in a cold wallet; a type of wallet that is never connected to the internet."),(0,i.kt)("h4",{id:"see-also-13"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cold-wallet"},"Cold Wallet")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#hardware-wallet"},"Hardware Wallet")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#wallet"},"Wallet"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cold-wallet"},"Cold Wallet"),(0,i.kt)("p",null,"A wallet that is used to secure assets offline. This wallet is permanently disconnected from the internet, and not vulnerable to attacks which rely on an active internet connection."),(0,i.kt)("h4",{id:"see-also-14"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cold-storage"},"Cold Storage")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#wallet"},"Wallet"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"commit"},"Commit"),(0,i.kt)("p",null,"Nervos CKB's consensus algorithm, ",(0,i.kt)("a",{parentName:"p",href:"#nc-max"},"NC-Max")," consensus, has two phases: ",(0,i.kt)("strong",{parentName:"p"},"propose")," and ",(0,i.kt)("strong",{parentName:"p"},"commit"),". Commit is the process of including a valid proposed transaction into a new block."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"commit-chain"},"Commit-Chain"),(0,i.kt)("p",null,"A scheme that enables the off-chain processing of transactions by one or more operators with on-chain state update commitments that do not contain per-transaction data."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"commit-reward"},"Commit Reward"),(0,i.kt)("p",null,"A reward paid to miners in CKBytes on inclusion of previously proposed transactions."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"common-knowledge-base"},"Common Knowledge Base"),(0,i.kt)("p",null,"A layer 1 proof of work blockchain that provides a foundation of decentralized trust for the Nervos Network."),(0,i.kt)("h4",{id:"synonyms-11"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckb"},"CKB")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-ckb"},"Nervos CKB"))),(0,i.kt)("h4",{id:"not-to-be-confused-with-1"},"Not To Be Confused With"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-byte"},"Common Knowledge Byte"))),(0,i.kt)("h4",{id:"see-also-15"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://www.nervos.org/ckb/"},"Nervos CKB on Nervos.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"common-knowledge-byte"},"Common Knowledge Byte"),(0,i.kt)("p",null,"The native token of the Nervos layer 1 blockchain, the Common Knowledge Base."),(0,i.kt)("p",null,"Common Knowledge Byte is often abbreviated as CKByte or CKB."),(0,i.kt)("p",null,"Owning a CKByte entitles the holder to store one byte of data on the Nervos CKB blockchain."),(0,i.kt)("h4",{id:"synonyms-12"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckb"},"CKB")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte"))),(0,i.kt)("h4",{id:"not-to-be-confused-with-2"},"Not To Be Confused With"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-base"},"Common Knowledge Base"))),(0,i.kt)("h4",{id:"see-also-16"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#capacity"},"Capacity")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-ckb"},"Nervos CKB")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#shannon"},"Shannon"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"confirmation"},"Confirmation"),(0,i.kt)("p",null,"A process where a transaction has been accepted and verified by the network and included in a block."),(0,i.kt)("h4",{id:"see-also-17"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#unconfirmed"},"Unconfirmed"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"consensus"},"Consensus"),(0,i.kt)("p",null,"An algorithm executed among a number of distributed participants, ensuring that all participants faithfully executing this algorithm can reach agreement on some data value even if the other participants are faulty or malicious."),(0,i.kt)("h4",{id:"see-also-18"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nc-max"},"NC-MAX"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"consume"},"Consume"),(0,i.kt)("p",null,"The process of using a live cell as an input to a transaction. The consumption processes indicate that live cell turns into a dead cell."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"contract-account"},"Contract Account"),(0,i.kt)("p",null,"An account containing code that executes automatically whenever it receives an event from another account."),(0,i.kt)("h4",{id:"see-also-19"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#account"},"Account"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cryptocurrency"},"Cryptocurrency"),(0,i.kt)("p",null,"A cryptocurrency is a digital or virtual currency that is secured by blockchain and cryptography, which makes it nearly impossible to counterfeit or double-spend."),(0,i.kt)("h4",{id:"see-also-20"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#digital-currency"},"Digital Currency")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#fiat-currency"},"Fiat Currency"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cryptographic-signature"},"Cryptographic Signature"),(0,i.kt)("p",null,"A concise piece of proof data. Cryptographic signature schemes are a fundamental component of cryptocurrency networks that verify the integrity and non-repudiation of transaction messages across the network."),(0,i.kt)("h4",{id:"synonyms-13"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#private-key"},"Private Key")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#signature"},"Signature"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cryptography"},"Cryptography"),(0,i.kt)("p",null,"Cryptography is the practice and study of techniques for secure communication in the presence of adversarial behavior."),(0,i.kt)("h4",{id:"see-also-21"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Cryptography"},"Cryptography at Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cycles"},"Cycles"),(0,i.kt)("p",null,"The number of RISC-V computational cycles required by a script to execute. It's a metric used to prevent malicious behavior such as infinite loops, that's why it is called cycles. "),(0,i.kt)("p",null,"This is a similar concept to Ethereum's Gas, we set cycles to ensure optimal performance and security. Scripts must stay within cycle limits, otherwise the block will be rejected by CKB nodes."),(0,i.kt)("h4",{id:"see-also-22"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://docs.nervos.org/docs/essays/faq/#estimate-cycles"},"Estimate cycles")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#max_block_cycles"},"Max_block_cycles")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0014-vm-cycle-limits/0014-vm-cycle-limits.md"},"Rules for calculating cycles in RFC on Nervos Network Github")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#script"},"Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#risc-v"},"RISC-V")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://ethereum.org/en/glossary/#gas"},"Ethereum's Gas"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"dao"},"DAO"),(0,i.kt)("p",null,"A decentralized autonomous organization (DAO) is an organization represented by rules encoded as a computer program that is transparent, controlled by the organization members and not influenced by a centralized entity, in other words they are member-owned communities without centralized leadership. A DAO's financial transaction record and program rules are maintained on a blockchain."),(0,i.kt)("h4",{id:"see-also-23"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Decentralized_autonomous_organization"},"DAO on Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"dapp"},"DApp"),(0,i.kt)("p",null,"Decentralized application. At a minimum, it is a smart contract and a web user interface. In a broader sense, DApps are web applications that are built on top of open, decentralized, peer-to-peer infrastructure services. Additionally, many DApps include decentralized storage and/or a message protocol and platform."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"data"},"Data"),(0,i.kt)("p",null,"In cell model, ",(0,i.kt)("inlineCode",{parentName:"p"},"data")," is a field in a cell which can store arbitrary bytes."),(0,i.kt)("h4",{id:"see-also-24"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell-model"},"Cell Model"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"decentralization"},"Decentralization"),(0,i.kt)("p",null,"In blockchain, decentralization refers to the transfer of control and decision-making from a centralized entity (individual, organization, or group thereof) to a distributed network."),(0,i.kt)("h4",{id:"see-also-25"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#distributed"},"Distributed")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Decentralization"},"Decentralization on Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"defi"},"DeFi"),(0,i.kt)("p",null,'Short for "decentralized finance", a broad category of DApps aiming to provide financial services backed by the blockchain, without any intermediaries, so anyone with an internet connection can participate.'),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"digital-asset"},"Digital Asset"),(0,i.kt)("p",null,"A digital asset is an individual piece of data that has value, or represents another entity that has value."),(0,i.kt)("p",null,"Digital assets are most commonly represented as tokens, which may be used as digital currency or represent physical items such as real estate."),(0,i.kt)("h4",{id:"synonyms-14"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#asset"},"Asset")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"digital-currency"},"Digital Currency"),(0,i.kt)("p",null,"A type of currency that primarily exists digitally over the internet. Physical representations of the currency, in the form of cards, bills, or coins, may exist, but are secondary mediums."),(0,i.kt)("h4",{id:"see-also-26"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cryptocurrency"},"Cryptocurrency"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"distributed"},"Distributed"),(0,i.kt)("p",null,"A system where components are spread across multiple nodes to parallelize workloads, add redundancy, or eliminate single points of failure."),(0,i.kt)("h4",{id:"see-also-27"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#decentralization"},"Decentralization"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"double-spending"},"Double-Spending"),(0,i.kt)("p",null,"Double-spending is the risk that a digital token is spent twice or more. In the context of blockchain, it happens when the transaction spending a digital token is cancelled after confirmation, and the same token is spent in another transaction."),(0,i.kt)("h4",{id:"see-also-28"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#confirmation"},"Confirmation")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cryptocurrency"},"Cryptocurrency")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"epoch"},"Epoch"),(0,i.kt)("p",null,"An epoch is a period of time for a set of blocks. "),(0,i.kt)("p",null,"In Nervos, the PoW difficulty changes on a new epoch. All the blocks in the same epoch share the same difficulty target. The difficulty adjustment algorithm aims to stabilize the orphan block rate at 2.5% and the epoch duration at 4 hours."),(0,i.kt)("h4",{id:"see-also-29"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"fee"},"Fee"),(0,i.kt)("p",null,"The sender of a transaction often includes a fee to the network for processing the requested transaction. There's no minimum fee rate set in consensus, but there's a minimum fee rate 1,000 Shannons/KB in CKB's ",(0,i.kt)("a",{parentName:"p",href:"#p2p"},"P2P")," network. (1 Shannon = 10",(0,i.kt)("sup",null,"-8")," CKB)"),(0,i.kt)("h4",{id:"see-also-30"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#shannon"},"Shannon")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#fee-rate"},"Fee rate")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/ckb/tree/develop/rpc#error-poolrejectedtransactionbyminfeerate"},"Fee rate in RFC on Nervos Network Github"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"fee-rate"},"Fee Rate"),(0,i.kt)("p",null,"A tip per byte that a user offers to the miners for including his transaction in a block on the blockchain."),(0,i.kt)("p",null,"This is a same concept to Bitcoin's ",(0,i.kt)("a",{parentName:"p",href:"https://en.bitcoin.it/wiki/Miner_fees#Feerates"},"Fee Rate(often spelled feerate)"),"."),(0,i.kt)("h4",{id:"see-also-31"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#fee"},"Fee"))),(0,i.kt)("h3",{id:"first-class-assets"},"First-Class Assets"),(0,i.kt)("p",null,"Assets that 1. the asset itself (rather than a reference to the asset) can be passed directly in smart contract interactions, and 2. directly controlled by owners without any intermediaries. "),(0,i.kt)("h4",{id:"see-also-32"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://medium.com/nervosnetwork/first-class-asset-ff4feaf370c4"},"First-Class Asset")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://talk.nervos.org/t/first-class-asset/1293"},"Introduction to First-Class Asset"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"fork"},"Fork"),(0,i.kt)("p",null,"A change in protocol causing the creation of an alternative chain, or a temporal divergence in two potential block paths during mining."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"full-node"},"Full Node"),(0,i.kt)("p",null,"A full node is an essential component of the CKB network. It stores and syncs the entire blockchain, verifies the validity of blocks and transactions, and enforces the network's consensus rules."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"ckb init --chain mainnet && ckb run\n")),(0,i.kt)("h4",{id:"see-also-33"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#node"},"Node")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#light-node"},"Light Node")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mining-node"},"Mining Node"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"full-payload-format"},"Full Payload Format"),(0,i.kt)("p",null,"The deprecated full payload format directly encodes all data field of lock script. The encode rule of deprecated full payload format is ",(0,i.kt)("a",{parentName:"p",href:"https://en.bitcoin.it/wiki/Bech32"},"Bech32"),"."),(0,i.kt)("h4",{id:"see-also-34"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"fungible-token"},"Fungible Token"),(0,i.kt)("p",null,"A fungible token can be fiat currencies like the dollar or a cryptocurrency like Bitcoin. "),(0,i.kt)("p",null,"Fungible tokens or assets are divisible and non-unique."),(0,i.kt)("h4",{id:"see-also-35"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#non-fungible-token"},"Non-Fungible Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#user-defined-token"},"User-Defined Token"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"gas-limit"},"Gas Limit"),(0,i.kt)("p",null,"The maximum amount of gas a transaction or block may consume."),(0,i.kt)("h4",{id:"see-also-36"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://ethereum.org/en/glossary/#gas"},"Ethereum's Gas"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"hard-fork"},"Hard-Fork"),(0,i.kt)("p",null,"A permanent divergence in the blockchain; also known as a hard-forking change. One commonly occurs when nonupgraded nodes can\u2019t validate blocks created by upgraded nodes that follow newer consensus rules. Not to be confused with a fork, soft fork, software fork, or Git fork."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"hardware-wallet"},"Hardware Wallet"),(0,i.kt)("p",null,"A hardware wallet is a form of cold wallet. A hardware wallet is a cryptocurrency wallet that stores the user's private keys (a critical piece of information used to authorize outgoing transactions on the blockchain network) in a secure hardware device."),(0,i.kt)("h4",{id:"see-also-37"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cold-storage"},"Cold Storage")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cold-wallet"},"Cold Wallet")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#private-key"},"Private Key")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#wallet"},"Wallet"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"hash"},"Hash"),(0,i.kt)("p",null,"A fixed-length fingerprint of variable-size input, produced by a hash function."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"hash-rate"},"Hash Rate"),(0,i.kt)("p",null,'Hash rate is a measure of the computational power per second used when mining. These operations are known as "hashing".'),(0,i.kt)("h4",{id:"see-also-38"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#miner"},"Miner")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#network-hash-rate"},"Network Hash Rate"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"height"},"Height"),(0,i.kt)("p",null,"A shorthand name for block height."),(0,i.kt)("h4",{id:"synonyms-15"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block-height"},"Block Height"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"light-client"},"Light Client"),(0,i.kt)("p",null,"As a low-resource node, a light client allows users to sync with a blockchain in a cryptographically secure manner without having to store the whole blockchain."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"light-node"},"Light Node"),(0,i.kt)("p",null,"A light node downloads only the headers of the blockchain, conserving resources. It relies on other nodes for full transaction data and is a lightweight option for network participation."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"ckb-light-client run --config-file ./testnet.toml\n")),(0,i.kt)("h4",{id:"see-also-39"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#node"},"Node")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#full-node"},"Full Node")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mining-node"},"Mining Node"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"mempool"},"Mempool"),(0,i.kt)("p",null,'Short for "memory pool". A waiting area on full nodes for transactions that have been broadcasted to the network but have not yet been confirmed on the blockchain.'),(0,i.kt)("h4",{id:"see-also-40"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#confirmation"},"Confirmation")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"metadata"},"Metadata"),(0,i.kt)("p",null,"Metadata is data that provides information about other data. ",(0,i.kt)("inlineCode",{parentName:"p"},"capacity"),", ",(0,i.kt)("inlineCode",{parentName:"p"},"type")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"lock")," in cells are metadata, they occupy cell capacity and incur a state cost as well."),(0,i.kt)("h4",{id:"see-also-41"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#capacity"},"Capacity")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock"},"Lock")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script"},"Type Script"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"micro-state"},"Micro-State"),(0,i.kt)("p",null,"A small piece of state that is isolated and often able to be acted upon independently without knowing the total state of the network."),(0,i.kt)("p",null,"On Nervos, micro-state is represented by a Cell."),(0,i.kt)("h4",{id:"synonyms-16"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell"))),(0,i.kt)("h4",{id:"see-also-42"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#state"},"State"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"miner"},"Miner"),(0,i.kt)("p",null,"A network node that finds valid proof of work for new blocks, by repeated hashing."),(0,i.kt)("h4",{id:"see-also-43"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proof-of-work"},"Proof of Work"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"miner-fee"},"Miner Fee"),(0,i.kt)("p",null,"Another term for transaction fee."),(0,i.kt)("h4",{id:"synonyms-17"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction-fee"},"Transaction Fee"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"mining"},"Mining"),(0,i.kt)("p",null,"Mining is the process by which a blockchain node get new token reward by verifying new transactions, finding valid proof of work and creating new blocks."),(0,i.kt)("h4",{id:"see-also-44"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blockchain"},"Blockchain")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mining-reward"},"Mining Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proof-of-work"},"Proof of Work"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"mining-node"},"Mining Node"),(0,i.kt)("p",null,"Mining nodes create new blocks by solving computational puzzles. They contribute to the network's security and consensus by actively validating and adding blocks to the blockchain."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"ckb init --chain mainnet && ckb miner\n")),(0,i.kt)("h4",{id:"see-also-45"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#consensus"},"Consensus")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#miner"},"Miner")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mining"},"Mining")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proof-of-work"},"Proof of Work")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#full-node"},"Full Node")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#light-node"},"Light Node"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"mining-reward"},"Mining Reward"),(0,i.kt)("p",null,"Native tokens paid to miners as a reward for providing the necessary computing resources for mining."),(0,i.kt)("h4",{id:"see-also-46"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#miner"},"Miner")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mining"},"Mining")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#native-token"},"Native Token"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"multisig"},"Multisig"),(0,i.kt)("p",null,"The term multisig stands for multi-signature, which is a specific type of digital signatures that can be created through the combination of multiple unique signatures."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"native-token"},"Native Token"),(0,i.kt)("p",null,"The token issued as reward to a blockchain's consensus nodes. Nervos CKB's native token is CKByte."),(0,i.kt)("h4",{id:"see-also-47"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"nc-max"},"NC-MAX"),(0,i.kt)("p",null,"Nervos CKB's consensus algorithm, which follows NC's backbone protocol. The main innovation here is a two-step transaction confirmation mechanism"),(0,i.kt)("h4",{id:"see-also-48"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#consensus"},"Consensus")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-blockchain"},"Nervos Blockchain")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://eprint.iacr.org/2020/1101"},"NC-MAC"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"neighbor"},"Neighbor"),(0,i.kt)("p",null,"A node that is directly connected to another node in the blockchain peer to peer network."),(0,i.kt)("h4",{id:"see-also-49"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#node"},"Node")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#peer-to-peer"},"Peer to Peer"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"nervos-blockchain"},"Nervos Blockchain"),(0,i.kt)("p",null,"The layer 1 blockchain of the Nervos Network known as the Common Knowledge Base."),(0,i.kt)("h4",{id:"synonyms-18"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-base"},"Common Knowledge Base")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#layer-1"},"Layer 1")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-ckb"},"Nervos CKB"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"nervos-dao"},"Nervos DAO"),(0,i.kt)("p",null,'Nervos DAO enable users to lock CKBytes to get compensation from Nervos CKB secondary issuance. This process is similar to staking on other platforms. Nervos DAO provides a "virtual hardcap" for CKByte holders to insulate them from inflation.'),(0,i.kt)("h4",{id:"see-also-50"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#dao"},"DAO")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#secondary-issuance"},"Secondary Issuance")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://medium.com/nervosnetwork/nervos-dao-explained-95e33898b1c"},"Nervos DAO Explained on the Nervos Blog")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0015-ckb-cryptoeconomics/0015-ckb-cryptoeconomics.md"},"Nervos DAO in RFC on Nervos Network Github")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://explorer.nervos.org/charts/inflation-rate"},"Inflation Rate Chart"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"network-hash-rate"},"Network Hash Rate"),(0,i.kt)("p",null,"A measurement of the total computational processing power which is dedicated to providing security to the network."),(0,i.kt)("h4",{id:"see-also-51"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#hash-rate"},"Hash Rate")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#miner"},"Miner"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"node"},"Node"),(0,i.kt)("p",null,"A software client that participates in the network."),(0,i.kt)("h4",{id:"see-also-52"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#full-node"},"Full Node")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#light-node"},"Light Node")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mining-node"},"Mining Node"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"nonce"},"Nonce"),(0,i.kt)("p",null,"In cryptography, a value that can only be used once. Nonce can refer to two things in blockchain context: 1. a proof-of-work nonce is the random value in a block satisfying the proof of work requirement; 2. an account nonce is a transaction counter in each account, which is used to prevent replay attacks."),(0,i.kt)("h4",{id:"see-also-53"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proof-of-work"},"Proof of Work"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"non-fungible-token"},"Non-Fungible Token"),(0,i.kt)("p",null,"Non-fungible tokens or NFTs are cryptographic assets on a blockchain with unique identification codes and metadata that distinguish them from each other."),(0,i.kt)("h4",{id:"see-also-54"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#fungible-token"},"Fungible Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#user-defined-token"},"User-Defined Token"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"open-source"},"Open Source"),(0,i.kt)("p",null,"A piece of software where source code is freely available for examination or alteration by any third-party."),(0,i.kt)("h4",{id:"see-also-55"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://opensource.com/resources/what-open-source"},"What is Open Source at OpenSource.com"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"p2p"},"P2P"),(0,i.kt)("p",null,"A shortname name for peer to peer."),(0,i.kt)("h4",{id:"synonyms-19"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#peer-to-peer"},"Peer to Peer"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"paper-wallet"},"Paper Wallet"),(0,i.kt)("p",null,"A form of storing a recovery phrase or private keys offline by printing them on a piece of paper. This document would then be stored by traditional means in a secured location of the user's choosing, such as a safe."),(0,i.kt)("h4",{id:"see-also-56"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#private-key"},"Private Key")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#wallet"},"Wallet"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"payment-address"},"Payment Address"),(0,i.kt)("p",null,"A string of letters and numbers that cryptocurrency and assets can be sent to and from. "),(0,i.kt)("p",null,'Nervos CKB mainnet addresses always begin with the prefix "ckb".'),(0,i.kt)("h4",{id:"synonyms-20"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#address"},"Address"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"payment-channel"},"Payment Channel"),(0,i.kt)("p",null,"A micropayment channel or payment channel is class of techniques designed to allow users to make multiple payment transactions without committing all of the transactions to the layer 1 blockchain. In a typical payment channel, only two transactions are added to the block chain but an unlimited or nearly unlimited number of payments can be made between the participants."),(0,i.kt)("h4",{id:"see-also-57"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#layer-1"},"Layer 1"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"peer-to-peer"},"Peer to Peer"),(0,i.kt)("p",null,"A peer-to-peer (P2P) service is a decentralized platform whereby two individuals interact directly with each other, without intermediation by a third party."),(0,i.kt)("h4",{id:"synonyms-21"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#p2p"},"P2P"))),(0,i.kt)("h4",{id:"see-also-58"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#node"},"Node"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"private-key"},"Private Key"),(0,i.kt)("p",null,"A private key, also known as a secret key, is a variable in cryptography, known only to the owner(s) of the key, that is used with an algorithm to encrypt and decrypt data."),(0,i.kt)("h4",{id:"see-also-59"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#digital-asset"},"Digital Asset")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#paper-wallet"},"Paper Wallet")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#payment-address"},"Payment Address")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#wallet"},"Wallet"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"proof-of-work"},"Proof of Work"),(0,i.kt)("p",null,"PoW asks users to solve a cryptographic puzzle to prove ownershipo of a certain amount of computational resource to participate in the consensus. In general PoW is a more permissionless consensus mechanism than PoS. "),(0,i.kt)("p",null,'In contrast to wildly spread misconception, PoW is not a "waste" of energy and does not induce more carbon emission. PoW is used in the Nervos layer 1 blockchain CKB.'),(0,i.kt)("h4",{id:"see-also-60"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#consensus"},"Consensus")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mining-reward"},"Mining Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proof-of-stake"},"Proof of Stake")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"proof-of-stake"},"Proof of Stake"),(0,i.kt)("p",null,"PoS asks users to prove ownership of a certain amount of cryptocurrency (their \u201cstake\u201d in the network) in order to be able to participate in the consensus. PoS relies on weak-subjectivity due to unsolvable issues like long-range attack. In PoS system the future consensus quorum is decided by existing participants completely. PoS is used in layer 2 protocols on Nervos Network."),(0,i.kt)("h4",{id:"see-also-61"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#consensus"},"Consensus")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mining-reward"},"Mining Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proof-of-work"},"Proof of Work")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"propagation"},"Propagation"),(0,i.kt)("p",null,"A shorthand name for Block Propagation."),(0,i.kt)("h4",{id:"synonyms-22"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block-propagation"},"Block Propagation"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"public-key"},"Public Key"),(0,i.kt)("p",null,"A notion used only in public-key cryptography, a.k.a. asymmetric cryptography. A public key is a piece of information that can be known to others without compromising security. Unique for each user, a public key is associated with a private key known only to the user. The public key can be used to encrypt a message so that it can only be decrypted with the corresponding private key, or to verify that a message is authorized by the user with the corresponding private key."),(0,i.kt)("h4",{id:"see-also-62"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#private-key"},"Private Key"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"reward"},"Reward"),(0,i.kt)("p",null,"An amount of CKBytes included in each new block as a reward by the network to the miner who found the proof-of-work solution."),(0,i.kt)("h4",{id:"see-also-63"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#base-reward"},"Base Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block-reward"},"Block Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#commit-reward"},"Commit Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mining-reward"},"Mining Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proposal-reward"},"Proposal Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#secondary-reward"},"Secondary Reward"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"signature"},"Signature"),(0,i.kt)("p",null,"A shorthand name for cryptographic signature."),(0,i.kt)("h4",{id:"synonyms-23"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cryptographic-signature"},"Cryptographic Signature"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"smart-contract"},"Smart Contract"),(0,i.kt)("p",null,"A smart contract is a self-executing contract with the terms of the agreement between contract creators and contract users being directly written into lines of code. The code and the agreements contained therein exist across a distributed, decentralized blockchain network. Also known as script on Nervos CKB. "),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"state"},"State"),(0,i.kt)("p",null,"Data stored on the blockchain. In most contexts this this means current data and excludes historical data."),(0,i.kt)("h4",{id:"see-also-64"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blockchain"},"Blockchain"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"state-bloat"},"State Bloat"),(0,i.kt)("p",null,"The unlimited increase of state data in Ethereum. State bloat slows down node synchronization, raises the barrier of full node, thus hurts network decentralization."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"state-channel"},"State Channel"),(0,i.kt)("p",null,"A layer 2 solution where a channel is set up between participants, where they can transact freely and cheaply. Only a transaction to set up the channel and close the channel is sent to mainnet. This allows for very high transaction throughput, but does rely on knowing number of participants up front and locking up of funds."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"tip"},"Tip"),(0,i.kt)("p",null,"A shorthand name for tip block."),(0,i.kt)("h4",{id:"synonyms-24"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#tip-block"},"Tip Block"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"tip-block"},"Tip Block"),(0,i.kt)("p",null,"The most recent block to be confirmed in a blockchain. The tip block has the highest block height in the blockchain."),(0,i.kt)("h4",{id:"synonyms-25"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#tip"},"Tip"))),(0,i.kt)("h4",{id:"see-also-65"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block-height"},"Block Height")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blockchain"},"Blockchain"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"transaction"},"Transaction"),(0,i.kt)("p",null,"Transaction is the basic object created and signed by users to interact with distributed ledger. Transactions update ledger state at users requests. A CKB transaction destroys some outputs created in previous transactions and creates some new outputs. We call the transaction output a cell in CKB."),(0,i.kt)("h4",{id:"see-also-66"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blockchain"},"Blockchain")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-blockchain"},"Nervos Blockchain"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"transaction-fee"},"Transaction Fee"),(0,i.kt)("p",null,"A fee which is paid in the native token to miners in exchange for processing a transaction."),(0,i.kt)("h4",{id:"synonyms-26"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#miner-fee"},"Miner Fee"))),(0,i.kt)("h4",{id:"see-also-67"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#miner"},"Miner")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#native-token"},"Native Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"token"},"Token"),(0,i.kt)("p",null,"A \u201ctoken\u201d often refers to non-native token on smart contract platform, such as UDT on Nervos Network or ERC20 on Ethereum."),(0,i.kt)("h4",{id:"see-also-68"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blockchain"},"Blockchain")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#digital-asset"},"Digital Asset")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"turing-complete"},"Turing Complete"),(0,i.kt)("p",null,"Turing Complete refers to a machine that, given enough time and memory along with the necessary instructions, can solve any computational problem, no matter how complex. The term is normally used to describe modern programming languages as most of them are Turing Complete (C++, Python, JavaScript, etc.)."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"udt"},"UDT"),(0,i.kt)("p",null,"Short for User-Defined Token, a customised token created with properties defined by the user. In normal usage, this most commonly refers to fungible tokens."),(0,i.kt)("h4",{id:"synonyms-27"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#user-defined-token"},"User-Defined Token"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"unconfirmed"},"Unconfirmed"),(0,i.kt)("p",null,"The state of a transaction that has not yet been confirmed. An unconfirmed transaction is not finalized and cannot be guaranteed."),(0,i.kt)("h4",{id:"synonyms-28"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#unconfirmed-transaction"},"Unconfirmed Transaction"))),(0,i.kt)("h4",{id:"see-also-69"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#confirmation"},"Confirmation")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"unconfirmed-transaction"},"Unconfirmed Transaction"),(0,i.kt)("p",null,"A transaction that has not yet been confirmed. An unconfirmed transaction is not finalized and cannot be guaranteed."),(0,i.kt)("h4",{id:"synonyms-29"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#unconfirmed"},"Unconfirmed"))),(0,i.kt)("h4",{id:"see-also-70"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#confirmation"},"Confirmation")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"user-defined-token"},"User-Defined Token"),(0,i.kt)("p",null,"A custom token created with properties defined by the user. In normal usage, this most commonly refers to fungible tokens."),(0,i.kt)("p",null,"A User-Defined Token is usually referred to by its abbreviation, UDT."),(0,i.kt)("h4",{id:"synonyms-30"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#fungible-token"},"Fungible Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#udt"},"UDT"))),(0,i.kt)("h4",{id:"see-also-71"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://eips.ethereum.org/EIPS/eip-20"},"ERC20 on Ethereum.org")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://eips.ethereum.org/EIPS/eip-777"},"ERC777 on Ethereum.org")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://talk.nervos.org/t/rfc-simple-udt-draft-spec/4333"},"Simple UDT Draft Spec on Nervos Talk"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"wallet"},"Wallet"),(0,i.kt)("p",null,"User-facing software used to interact with on-chain entities such as assets, smart contracts and dapps. A wallet can include key management itself or delegate key management to external hardware for improved security."),(0,i.kt)("h4",{id:"see-also-72"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#paper-wallet"},"Paper Wallet")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#private-key"},"Private Key")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#payment-address"},"Payment Address")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#digital-asset"},"Digital Asset"))),(0,i.kt)("hr",null),(0,i.kt)("h2",{id:"economics-glossary"},"Economics Glossary"),(0,i.kt)("h3",{id:"base-issuance"},"Base Issuance"),(0,i.kt)("p",null,"Base issuance is the basic CKByte issuance with a fixed and decreasing schedule. Base issuance is awarded to miners as incentives to protect the network and also as an indirect token distribution method."),(0,i.kt)("p",null,"Base issuance is limited to a finite total supply 33.6G (33.6 billion) CKBytes. "),(0,i.kt)("h4",{id:"see-also-73"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#base-reward"},"Base Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#secondary-issuance"},"Secondary Issuance")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#miner"},"Miner")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0015-ckb-cryptoeconomics/0015-ckb-cryptoeconomics.md"},"Crypto-Economics RFC on Nervos Network GitHub"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"base-reward"},"Base Reward"),(0,i.kt)("p",null,"Base reward is the block reward (in CKBytes) to miners generated from the base issuance. Base reward halves approximately every 4 years until eventually reaching 0, like Bitcoin."),(0,i.kt)("h4",{id:"see-also-74"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#base-issuance"},"Base Issuance")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#miner"},"Miner")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"commit-reward-1"},"Commit Reward"),(0,i.kt)("p",null,"A reward paid to miners in CKBytes for committing a previously proposed transaction. After the transaction has been committed it is confirmed."),(0,i.kt)("h4",{id:"see-also-75"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#confirmation"},"Confirmation")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#miner"},"Miner")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"economic-abstraction"},"Economic Abstraction"),(0,i.kt)("p",null,'With proper tool support, users can use tokens other than CKByte (for example, stable coins) to pay transactions fees, a concept known as "Economic Abstraction".'),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"fiat-currency"},"Fiat Currency"),(0,i.kt)("p",null,"Fiat currencies are a medium of exchange established as money, often by government regulation. Fiat money does not have intrinsic value and does not have use value. It has value only because a government maintains its value, or because parties engaging in exchange agree on its value."),(0,i.kt)("h4",{id:"see-also-76"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cryptocurrency"},"Cryptocurrency")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#digital-currency"},"Digital Currency"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"heavy-asset-problem"},"Heavy Asset Problem"),(0,i.kt)("p",null,"A common problem found in multi-asset blockchain platforms where the value of the assets stored on the chain gains significant value but the native token of the chain does not. This raises the incentive to attack the the network, but does not increase the security because the value of the native token is what is used to secure the network."),(0,i.kt)("h4",{id:"see-also-77"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#asset"},"Asset")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#starving-layer-1-problem"},"Starving Layer 1 Problem")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#tragedy-of-the-security-commons"},"Tragedy of the Security Commons"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"liquidity"},"Liquidity"),(0,i.kt)("p",null,"The ability for an asset to be bought or sold easily without causing a significant change in the current market price."),(0,i.kt)("h4",{id:"see-also-78"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#asset"},"Asset"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"proposal-reward"},"Proposal Reward"),(0,i.kt)("p",null,"A reward paid to miners in CKBytes for proposing an unconfirmed transaction."),(0,i.kt)("h4",{id:"see-also-79"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#confirmation"},"Confirmation")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#miner"},"Miner")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"secondary-issuance"},"Secondary Issuance"),(0,i.kt)("p",null,"The creation of new CKBytes that is paid to miners through secondary rewards. Secondary issuance follows a fixed inflation schedule of 1.344 billion CKBytes per year. Nervos DAO stakers are not affected by secondary issuance."),(0,i.kt)("h4",{id:"see-also-80"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#base-issuance"},"Base Issuance")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-dao"},"Nervos DAO")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#secondary-reward"},"Secondary Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#state"},"State")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0015-ckb-cryptoeconomics/0015-ckb-cryptoeconomics.md"},"Crypto-Economics RFC on Nervos Network GitHub"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"secondary-reward"},"Secondary Reward"),(0,i.kt)("p",null,"A subsidy paid to miners in CKBytes for providing the compute and storage requirements required for processing transactions and persisting data on Nervos."),(0,i.kt)("p",null,"Secondary rewards are created from secondary issuance, and continuously pay miners for the verification of transactions and preservation of blockchain state."),(0,i.kt)("h4",{id:"see-also-81"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#miner"},"Miner")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#secondary-issuance"},"Secondary Issuance")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"selfish-mining-attack"},"Selfish Mining Attack"),(0,i.kt)("p",null,"Selfish mining is a concept that was addressed by Cornell University researchers in detail in a 2013 report. In this attack, malicious miners gain unfair block rewards by deliberately orphaning blocks mined by others."),(0,i.kt)("h4",{id:"see-also-82"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf"},"Selfish Mining Related Paper"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"starving-layer-1-problem"},"Starving Layer 1 Problem"),(0,i.kt)("p",null,"A scenario that can arise in multi-layer blockchain platforms where the vast majority of the transaction traffic moves from layer 1 to layer 2, taking the vast majority of transaction fees with it. If layer 1 relies exclusively on transaction fees to support the security of the platform, it may end up not having enough incentives available to properly secure it."),(0,i.kt)("h4",{id:"see-also-83"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#heavy-asset-problem"},"Heavy Asset Problem")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#layer-1"},"Layer 1")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#layer-2"},"Layer 2")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction-fee"},"Transaction Fee"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"state-rent"},"State Rent"),(0,i.kt)("p",null,"A recurring fee that is paid to persist and secure state data. "),(0,i.kt)("p",null,"On Nervos, secondary issuance is used to boost the payment of state rent by users who occupy space on the Nervos blockchain."),(0,i.kt)("h4",{id:"see-also-84"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#secondary-issuance"},"Secondary Issuance")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-blockchain"},"Nervos Blockchain")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0015-ckb-cryptoeconomics/0015-ckb-cryptoeconomics.md"},"Crypto-Economics RFC on Nervos Network GitHub"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"store-of-assets"},"Store of Assets"),(0,i.kt)("p",null,'Similar to the concept of "Store of Value" in the context of Bitcoin, we call the utility "Store of Assets" when a blockchain keeps any crypto-assets securely and censorship-resistantly. Nervos CKB is such a Store of Assets or SoA.'),(0,i.kt)("h4",{id:"see-also-85"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#store-of-value"},"Store of Value"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"store-of-value"},"Store of Value"),(0,i.kt)("p",null,"Assets which can maintain their worth over time without depreciating"),(0,i.kt)("p",null,"A good store of value either match or outpace the inflation rate of fiat currency, and has a reasonable amount of liquidity, allowing the asset to be easily sold."),(0,i.kt)("h4",{id:"see-also-86"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#store-of-assets"},"Store of Assets")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#liquidity"},"Liquidity"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"tail-emission"},"Tail Emission"),(0,i.kt)("p",null,"A type of reward that is paid to miners through a fixed amount of inflation."),(0,i.kt)("h4",{id:"see-also-87"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#secondary-reward"},"Secondary Reward"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"targeted-inflation"},"Targeted Inflation"),(0,i.kt)("p",null,"A form of inflation that only affects a specific subset of users."),(0,i.kt)("p",null,"Nervos uses Secondary Issuance to create targeted inflation on users who occupy space on the Nervos blockchain to pay State Rent. Long-term holders of CKBytes have the option of locking them in the Nervos DAO, which acts and an inflation shelter."),(0,i.kt)("h4",{id:"see-also-88"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#secondary-issuance"},"Secondary Issuance")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-blockchain"},"Nervos Blockchain")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-dao"},"Nervos DAO")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0015-ckb-cryptoeconomics/0015-ckb-cryptoeconomics.md"},"Crypto-Economics RFC on Nervos Network GitHub"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"tragedy-of-the-commons"},"Tragedy of the Commons"),(0,i.kt)("p",null,"A situation in a system where the participants act in accordance with their own self interest and deplete or destroy a shared resource through their collective action."),(0,i.kt)("h4",{id:"see-also-89"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#tragedy-of-the-security-commons"},"Tragedy of the Security Commons")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#tragedy-of-the-storage-commons"},"Tragedy of the Storage Commons"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"tragedy-of-the-security-commons"},"Tragedy of the Security Commons"),(0,i.kt)("p",null,'A situation that can emerge on multi-asset blockchain platforms where asset tokens rely on the storage and security of the blockchain platform, but do not contribute back to the platform. As the number of assets that "ride for free" increases, so does the burden placed on the underlying blockchain platform. If the assets do not contribute to the underlying platform, the available security may not properly support the network.'),(0,i.kt)("h4",{id:"see-also-90"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#heavy-asset-problem"},"Heavy Asset Problem")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#tragedy-of-the-commons"},"Tragedy of the Commons")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#tragedy-of-the-storage-commons"},"Tragedy of the Storage Commons"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"tragedy-of-the-storage-commons"},"Tragedy of the Storage Commons"),(0,i.kt)("p",null,"A situation that can emerge on incentivized blockchain platforms where mining rewards are paid for inclusion of data to the blockchain, but no rewards exist for the long-term persistence of the blockchain data. As the size of the chain grows, so do the costs associated with persisting the data. If there is no direct incentive for persisting data, fewer and fewer nodes will do so. Eventually, too few nodes will be available to properly support the network."),(0,i.kt)("h4",{id:"see-also-91"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#tragedy-of-the-commons"},"Tragedy of the Commons")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#tragedy-of-the-security-commons"},"Tragedy of the Security Commons"))),(0,i.kt)("hr",null),(0,i.kt)("h2",{id:"technical-glossary"},"Technical Glossary"),(0,i.kt)("h3",{id:"active-cell"},"Active Cell"),(0,i.kt)("p",null,"Or live cell, a cell exists in the current CKB state. Only active cells can be used as inputs to new transactions."),(0,i.kt)("h4",{id:"synonyms-31"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#live-cell"},"Live Cell"))),(0,i.kt)("h4",{id:"see-also-92"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#input"},"Input")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"aggron"},"Aggron"),(0,i.kt)("p",null,"The first Nervos CKB testnet corresponding to mainnet Lina."),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"CKB version"),": >= v0.101.0 (latest stable is recommended)"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"Genesis hash"),": 0x10639e0895502b5688a6be8cf69460d76541bfa4821629d86d62ba0aae3f9606"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"Init command"),": ",(0,i.kt)("inlineCode",{parentName:"li"},"ckb init --chain testnet")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"Launched at"),": 2020-05-22 04:00:00 UTC"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"ckb2021 activated at"),": 2021-10-24 03:00:00 UTC")),(0,i.kt)("h4",{id:"synonyms-32"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#testnet"},"Testnet"))),(0,i.kt)("h4",{id:"not-to-be-confused-with-3"},"Not To Be Confused With"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lina"},"Lina")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mainnet"},"Mainnet"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"animagus"},"Animagus"),(0,i.kt)("p",null,"A framework layer that runs on top of Nervos CKB which provides an easy way to query for account balances without having to go through the cell collection process."),(0,i.kt)("h4",{id:"see-also-93"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell-collection"},"Cell Collection")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-ckb"},"Nervos CKB")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://medium.com/nervosnetwork/https-medium-com-nervosnetwork-animagus-part-1-introduction-66fa8ce27ccd-cfb361a7d883"},"Animagus Introduction on the Nervos Blog"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"args"},"Args"),(0,i.kt)("p",null,"Args is short for arguments. Arguments are data provided to the lock script or type script of a cell, similar to args provided to a function or method call."),(0,i.kt)("p",null,"Arguments are stored as part of the Cell when it is created."),(0,i.kt)("h4",{id:"see-also-94"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script"},"Type Script"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"axon"},"Axon"),(0,i.kt)("p",null,"Axon is a chain-based layer 2 protocol and framework with a practical security and economic model. Axon chains allow anyone to stake tokens on CKB to become a validator and participate in consensus."),(0,i.kt)("h4",{id:"see-also-95"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#layer-2"},"Layer 2")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-ckb"},"Nervos CKB"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"blake2b"},"Blake2b"),(0,i.kt)("p",null,"A cryptographic hash function. BLAKE2b (or BLAKE2) is optimized for 64-bit platforms including NEON-enabled ARMs and produces digests of any size between 1 and 64 bytes. BLAKE2b is optimized for 8- to 32-bit platforms, and produces digests of any size between 1 and 32 bytes. CKB uses BLAKE2b as the default hash algorithm."),(0,i.kt)("h4",{id:"see-also-96"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://blake2.net/blake2.pdf"},"Blake2b paper")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbhash"},"Ckbhash")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/BLAKE_(hash_function)"},"Blake Hash Function on Wikipedia")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Hash_function"},"Hash Function on Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"block-subsidy"},"Block Subsidy"),(0,i.kt)("p",null,"A payment that is made in the native currency of the blockchain that is paid to to miners for providing the computational resources create a block and secure the blockchain."),(0,i.kt)("p",null,"The subsidy consists is the portion of the total block reward that is issued out of inflation for creating the block, but does not include any additional transaction fees that may be paid on top."),(0,i.kt)("h4",{id:"synonyms-33"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block-reward"},"Block Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction-fee"},"Transaction Fee"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"boxer"},"Boxer"),(0,i.kt)("p",null,"A lightweight Rust library for verifying the Nervos layer 1 blockchain, the Common Knowledge Base."),(0,i.kt)("h4",{id:"see-also-97"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-base"},"Common Knowledge Base")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/xxuejie/ckb-boxer"},"Boxer on GitHub"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"block_version"},(0,i.kt)("inlineCode",{parentName:"h3"},"block_version")),(0,i.kt)("p",null,"Version of a block. This field is reserved for the system, set to 0 by default."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"pub const BLOCK_VERSION: Version = 0;\n")),(0,i.kt)("h4",{id:"see-also-98"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cell-collection"},"Cell Collection"),(0,i.kt)("p",null,"The process of gathering cells that meet certain criteria."),(0,i.kt)("p",null,"For example: To find the balance of a particular account, all active cells for the address would need to be collected."),(0,i.kt)("h4",{id:"see-also-99"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cellbase"},"Cellbase"),(0,i.kt)("p",null,"The transaction in each block that is responsible for the minting of new CKBytes."),(0,i.kt)("p",null,"This is the equivalent of a coinbase transaction in Bitcoin."),(0,i.kt)("h4",{id:"see-also-100"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://developer.bitcoin.org/glossary.html"},"Coinbase on Bitcoin.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cellbase_maturity"},(0,i.kt)("inlineCode",{parentName:"h3"},"cellbase_maturity")),(0,i.kt)("p",null,'Any referenced cellbase output must meet this requirement in a transaction; otherwise, the transaction is rejected. Cellbase outputs are "locked" and have to wait for 4 epochs (approximately 16 hours) to be confirmed before they become ready to be spent. This restriction is to avoid the risk of later transactions with cellbase root being rollbacked when a soft fork occurs.'),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"pub(crate) const CELLBASE_MATURITY: EpochNumberWithFraction =\nEpochNumberWithFraction::new_unchecked(4, 0, 1);\n")),(0,i.kt)("h4",{id:"see-also-101"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cellbase"},"Cellbase"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"cell_deps"},(0,i.kt)("inlineCode",{parentName:"h3"},"cell_deps")),(0,i.kt)("p",null,"Pointers to live cells on the chain that allow scripts in the transaction to access (read-only) referenced live cells."),(0,i.kt)("p",null,"Find more in the essay ",(0,i.kt)("a",{parentName:"p",href:"https://docs.nervos.org/docs/essays/dependencies/#how-dependencies-work"},"Script dependencies"),"."),(0,i.kt)("h4",{id:"see-also-102"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#dependencies"},"Dependencies"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"ckbhash"},"Ckbhash"),(0,i.kt)("p",null,"CKB uses blake2b as the default hash algorithm with the following configurations:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"output digest size in bytes: ",(0,i.kt)("inlineCode",{parentName:"li"},"32")),(0,i.kt)("li",{parentName:"ul"},"personalization: ",(0,i.kt)("inlineCode",{parentName:"li"},"ckb-default-hash"))),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"ckbhash")," is used to denote the blake2b hash with the configurations above, there are example and test vectors in python 3:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-python"},"import hashlib\nimport unittest\n\ndef ckbhash():\n return hashlib.blake2b(digest_size=32, person=b'ckb-default-hash')\n\nclass TestCKBBlake2b(unittest.TestCase):\n\n def test_empty_message(self):\n hasher = ckbhash()\n hasher.update(b'')\n self.assertEqual('44f4c69744d5f8c55d642062949dcae49bc4e7ef43d388c5a12f42b5633d163e', hasher.hexdigest())\n\nif __name__ == '__main__':\n unittest.main()\n")),(0,i.kt)("h4",{id:"see-also-103"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blake2b"},"Blake2b"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"ckb-merkle-tree"},"CKB Merkle Tree"),(0,i.kt)("p",null,"CKB Merkle Tree is a CBMT( ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0006-merkle-tree/0006-merkle-tree.md#complete-binary-merkle-tree"},"Complete Binary Merkle Tree")," ) using following merge function:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"ckbhash(left || right)\n")),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},(0,i.kt)("inlineCode",{parentName:"p"},"ckbhash")," is the hash function, ",(0,i.kt)("inlineCode",{parentName:"p"},"||")," denotes binary concatenation.")),(0,i.kt)("h4",{id:"see-also-104"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0006-merkle-tree/0006-merkle-tree.md"},"Merkle Tree for Static Data")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbhash"},"Ckbhash")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Merkle_tree"},"Merkle Tree on Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"code-hash-1"},"Code Hash"),(0,i.kt)("p",null,"A field in a Cell that contains a hash value which could refer to a specific piece of data, or a specific cell referenced by Type ID."),(0,i.kt)("h4",{id:"see-also-105"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#data"},"Data")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-id"},"Type ID"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"commit-1"},"Commit"),(0,i.kt)("p",null,"The process of taking a proposed transaction and adding it to the blockchain. After the transaction has been committed it is confirmed."),(0,i.kt)("p",null,"Miners are incentivized to commit transactions by being paid a commit reward."),(0,i.kt)("h4",{id:"see-also-106"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#commit-reward"},"Commit Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#confirmation"},"Confirmation")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#propose"},"Propose")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"commitment-zone"},"Commitment Zone"),(0,i.kt)("p",null,"Section of the block that contains transaction commitments. The commitment zone can only contain valid transactions which have appeared in the proposal zone of one of the previous 2 to 10 blocks."),(0,i.kt)("h4",{id:"see-also-107"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proposal-zone"},"Proposal Zone")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"consume-1"},"Consume"),(0,i.kt)("p",null,"The process of using a Live Cell as an input to a transaction."),(0,i.kt)("p",null,"The process of consumption marks the Live Cell as a Dead Cell. This is the equivalent of marking a UTXO as spent in Bitcoin."),(0,i.kt)("h4",{id:"see-also-108"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell-model"},"Cell Model")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#dead-cell"},"Dead Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#live-cell"},"Live Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://developer.bitcoin.org/glossary.html"},"UTXO on Bitcoin.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"crypto-primitives"},"Crypto Primitives"),(0,i.kt)("p",null,"Well-established, low-level cryptographic algorithm commonly used to build out a cryptographic protocol."),(0,i.kt)("h4",{id:"see-also-109"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Cryptographic_primitive"},"Cryptographic Primitive on Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"dao_type_hash"},(0,i.kt)("inlineCode",{parentName:"h3"},"dao_type_hash")),(0,i.kt)("p",null,"NervosDAO\u2019s ",(0,i.kt)("inlineCode",{parentName:"p"},"type_hash"),". "),(0,i.kt)("p",null,"Find more in ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0024-ckb-genesis-script-list/0024-ckb-genesis-script-list.md#ckb-genesis-script-list"},"CKB Genesis Script List"),"."),(0,i.kt)("h4",{id:"see-also-110"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#%60type_hash%60"},(0,i.kt)("inlineCode",{parentName:"a"},"type_hash")))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"data-1"},"Data"),(0,i.kt)("p",null,"In Nervos specific contexts, data may refer to the data structure within a Cell. This structure is used to hold any form of information that needs to be stored on the Nervos blockchain."),(0,i.kt)("p",null,"In more general contexts, data may refer to any form of information."),(0,i.kt)("h4",{id:"see-also-111"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell-model"},"Cell Model"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"dead-cell"},"Dead Cell"),(0,i.kt)("p",null,"A cell that has been used as an input to a previous transaction and is consumed. "),(0,i.kt)("p",null,"A dead cell cannot be used as an input to a new transaction, nor can it be used as a dependency. It is effectively destroyed and removed from the active state of the network."),(0,i.kt)("p",null,'A dead cell is the equivalent of a "spent UTXO" in Bitcoin.'),(0,i.kt)("h4",{id:"synonyms-34"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#historical-cell"},"Historical Cell"))),(0,i.kt)("h4",{id:"see-also-112"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell-model"},"Cell Model")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#consume"},"Consume")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://developer.bitcoin.org/glossary.html"},"UTXO on Bitcoin.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"dep-group"},"Dep Group"),(0,i.kt)("p",null,"A method for referencing multiple dependencies which are commonly used together using a single dependency field."),(0,i.kt)("h4",{id:"see-also-113"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#dep-type"},"Dep Type")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#dependencies"},"Dependencies")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0022-transaction-structure/0022-transaction-structure.md"},"CKB Transaction Structure on GitHub"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"dep-type"},"Dep Type"),(0,i.kt)("p",null,"A field that specifies the type of the dependency."),(0,i.kt)("h4",{id:"see-also-114"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#dep-group"},"Dep Group")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#dependencies"},"Dependencies")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0022-transaction-structure/0022-transaction-structure.md"},"CKB Transaction Structure on GitHub"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"deps"},"Deps"),(0,i.kt)("p",null,"A shorthand name for dependencies."),(0,i.kt)("h4",{id:"synonyms-35"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#dependencies"},"Dependencies"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"dependencies"},"Dependencies"),(0,i.kt)("p",null,"Dependencies are commonly referred to as deps. Dependencies are cells that are referenced in a transaction. Cells that are referenced as dependencies are read-only and made available to any scripts executing within the transaction. Dependencies, or deps, are not consumed. "),(0,i.kt)("h4",{id:"synonyms-36"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#deps"},"Deps"))),(0,i.kt)("h4",{id:"see-also-115"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#consume"},"Consume")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#script"},"Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"duktape"},"Duktape"),(0,i.kt)("p",null,"Duktape is an embeddable Javascript engine, with a focus on portability and compact footprint."),(0,i.kt)("p",null,"Duktape is used to run JavaScript based smart contracts on Nervos."),(0,i.kt)("h4",{id:"see-also-116"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://duktape.org/"},"Duktape Official Website"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"difficulty"},"Difficulty"),(0,i.kt)("p",null,"A measurement of how difficult it is to solve the ",(0,i.kt)("a",{parentName:"p",href:"#proof-of-work"},"Proof of Work")," cryptographic puzzle required to create a block."),(0,i.kt)("p",null,"Networks automatically adjust the difficulty to control the speed at which blocks are generated as mining participants enter and exit the network."),(0,i.kt)("h4",{id:"see-also-117"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proof-of-work"},"Proof of Work"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"diviner"},"Diviner"),(0,i.kt)("p",null,"A deterministic testing framework for Rust."),(0,i.kt)("h4",{id:"see-also-118"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/xxuejie/diviner"},"Diviner on GitHub"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"eaglesong"},"Eaglesong"),(0,i.kt)("p",null,"Eaglesong is a new hash function developed specifically for Nervos CKB proof-of-work, which is also suitable in other use cases in which a secure hash function is needed. "),(0,i.kt)("h4",{id:"see-also-119"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0010-eaglesong/0010-eaglesong.md"},"Eaglesong RFC on the Nervos Github")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://medium.com/nervosnetwork/the-proof-of-work-function-of-nervos-ckb-3cc8364464d9"},"Introducing Eaglesong, Nervos\u2019s New Hash Function for CKB Proof-of-Work"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"epoch_duration_target"},(0,i.kt)("inlineCode",{parentName:"h3"},"epoch_duration_target")),(0,i.kt)("p",null,"The estimated epoch duration specified by NC-Max. Set as 4 hours in CKB. "),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"pub(crate) const DEFAULT_EPOCH_DURATION_TARGET: u64 = 4 * 60 * 60; // 4 hours, unit: second\n")),(0,i.kt)("h4",{id:"see-also-120"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#epoch"},"Epoch")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nc-max"},"NC-Max"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"erc20"},"ERC20"),(0,i.kt)("p",null,"An Ethereum token standard for basic fungible tokens."),(0,i.kt)("p",null,"An SUDT on Nervos is the equivalent of Ethereum tokens standards ERC20 or ERC777."),(0,i.kt)("h4",{id:"see-also-121"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#erc777"},"ERC777")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#fungible-token"},"Fungible Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#user-defined-token"},"User-Defined Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://eips.ethereum.org/EIPS/eip-20"},"ERC20 on Ethereum.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"erc721"},"ERC721"),(0,i.kt)("p",null,"An Ethereum token standard for non-fungible tokens."),(0,i.kt)("h4",{id:"see-also-122"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#non-fungible-token"},"Non-Fungible Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://eips.ethereum.org/EIPS/eip-721"},"ERC721 on Ethereum.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"erc777"},"ERC777"),(0,i.kt)("p",null,"An updated Ethereum token standard for basic fungible tokens that is backwards compatible with ERC20."),(0,i.kt)("p",null,"An SUDT on Nervos is the equivalent of Ethereum tokens standards ERC20 or ERC777."),(0,i.kt)("h4",{id:"see-also-123"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#erc20"},"ERC20")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#fungible-token"},"Fungible Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#user-defined-token"},"User-Defined Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://eips.ethereum.org/EIPS/eip-777"},"ERC777 on Ethereum.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"erc1155"},"ERC1155"),(0,i.kt)("p",null,"An Ethereum token standard that supports the creation any number of fungible or non-fungible tokens on a single contract."),(0,i.kt)("h4",{id:"see-also-124"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#fungible-token"},"Fungible Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#non-fungible-token"},"Non-Fungible Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#user-defined-token"},"User-Defined Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://eips.ethereum.org/EIPS/eip-1155"},"ERC1155 on Ethereum.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"full-address"},"Full Address"),(0,i.kt)("p",null,"An address format used on Nervos that includes the full code hash of the lock script associated."),(0,i.kt)("h4",{id:"see-also-125"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#address"},"Address")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#short-address"},"Short Address"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"generator"},"Generator"),(0,i.kt)("p",null,"A program used to create transactions that can be broadcast to the Nervos CKB network. "),(0,i.kt)("p",null,"Generators run locally on the client side (off-chain). They utilize user input and existing cells as program inputs, to create new cells with new states as output."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"genesis-block"},"Genesis Block"),(0,i.kt)("p",null,"The first block in the blockchain, used to initialize the global state. The genesis block is unique because it does not contain a reference to the previous block because it is the first."),(0,i.kt)("h4",{id:"see-also-126"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#blockchain"},"Blockchain"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"genesis_hash"},(0,i.kt)("inlineCode",{parentName:"h3"},"genesis_hash")),(0,i.kt)("p",null,"Hash of CKB genesis block. CKB Genesis Block was created in a decentralized manner that encourages everyone to generate a unique genesis block verifiably through the ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/genesis-block-generator/blob/master/spec.md"},"Genesis Block Generator"),". Nodes thus created and activated can be connected to any other node across the network to form a decentralized Common Knowledge Base."),(0,i.kt)("p",null,"The genesis block contains two main components:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/ckb-system-scripts/blob/v0.5.4/c/dao.c"},"System script")),(0,i.kt)("li",{parentName:"ul"},"Token pre-allocation based on the Nervos Foundation\u2018s ",(0,i.kt)("a",{parentName:"li",href:"https://medium.com/nervosnetwork/nervos-ckb-official-public-sale-announcement-431438f4cc39#:~:text=Key%20details%20of%20the%20Nervos%20Public%20Sale&text=The%20initial%20total%20supply%20of,be%201%20CKB%20%3D%200.01%20USD."},"announcement"),".")),(0,i.kt)("h4",{id:"see-also-127"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#genesis-block"},"Genesis block"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"godwoken"},"Godwoken"),(0,i.kt)("p",null,"Godwoken is a layer 2 rollup framework for Nervos CKB. It provides scaling capability, as well as an abstract account model to CKB."),(0,i.kt)("h4",{id:"see-also-128"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/godwoken"},"Godwoken on GitHub")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://docs.godwoken.io/"},"Godwoken Documentation Site"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"governance-script"},"Governance Script"),(0,i.kt)("p",null,"A type script which defines the monetary policy of a User Defined Token (UDT)."),(0,i.kt)("h4",{id:"see-also-129"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#governance-script-hash"},"Governance Script Hash")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#udt"},"UDT")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#user-defined-token"},"User Defined Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script"},"Type Script"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"governance-script-hash"},"Governance Script Hash"),(0,i.kt)("p",null,"A Blake2b hash of a type script which is used as an identifier for the script when referenced by a cell."),(0,i.kt)("h4",{id:"synonyms-37"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script-hash"},"Type Script Hash"))),(0,i.kt)("h4",{id:"see-also-130"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#governance-script"},"Governance Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#udt"},"UDT")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#user-defined-token"},"User Defined Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script"},"Type Script"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"historical-cell"},"Historical Cell"),(0,i.kt)("p",null,"An alternative term for ",(0,i.kt)("a",{parentName:"p",href:"#dead-cell"},"Dead Cell"),"."),(0,i.kt)("h4",{id:"synonyms-38"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#dead-cell"},"Dead Cell"))),(0,i.kt)("h4",{id:"see-also-131"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell-model"},"Cell Model"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"inbound-connection"},"Inbound Connection"),(0,i.kt)("p",null,"Inbound connection means it is initiated by the remote peer; and the connection itself is outgoing connection when we switch the subject to the remote peer."),(0,i.kt)("h4",{id:"see-also-132"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#outbound-connection"},"Outbound Connection"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"indexer"},"Indexer"),(0,i.kt)("p",null,"An application or library to trace live cells that comply with criteria specified by the developer or user."),(0,i.kt)("h4",{id:"see-also-133"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#live-cell"},"Live Cell"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"initial_primary_epoch_reward"},(0,i.kt)("inlineCode",{parentName:"h3"},"initial_primary_epoch_reward")),(0,i.kt)("p",null,"Incentives paid to miners in CKBytes by epoch in CKB base issuance. Under CKB's consensus, block interval is uncertain, while epoch can be fixed at approximately 4 hours, so reward issuance is determined by epoch. Each epoch issues 1_917_808_21917808 Shannons of CKBytes, whose total amount is fixed but halves every 4 years. "),(0,i.kt)("p",null,"The initial base issuance is 4.2 billion CKBytes per year. Similar to Bitcoin, the base issuance halves approximately every 4 years until it stops."),(0,i.kt)("p",null,"To calculate, ",(0,i.kt)("a",{parentName:"p",href:"https://docs.nervos.org/docs/basics/glossary/#block-reward"},"block reward")," = ",(0,i.kt)("inlineCode",{parentName:"p"},"initial_primary_epoch_reward")," / epoch_length (the number of blocks in the epoch)."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"pub(crate) const INITIAL_PRIMARY_EPOCH_REWARD: Capacity = Capacity::shannons(1_917_808_21917808);\n")),(0,i.kt)("h4",{id:"see-also-134"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block-reward"},"Block Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#epoch"},"Epoch")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#%60secondary_epoch_reward%60"},(0,i.kt)("inlineCode",{parentName:"a"},"secondary_epoch_reward"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#%60primary_epoch_reward_havling_interval%60"},(0,i.kt)("inlineCode",{parentName:"a"},"primary_epoch_reward_havling_interval")))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"input"},"Input"),(0,i.kt)("p",null,"A live cell that is used in a transaction. If the transaction is accepted by the network, the live cell gets consumed as input and labeled as a dead cell."),(0,i.kt)("h4",{id:"see-also-135"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#consume"},"Consume")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#dead-cell"},"Dead Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#live-cell"},"Live Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"keyper"},"Keyper"),(0,i.kt)("p",null,"A specification of how to manage wallet Lock Scripts which apply to a specific user."),(0,i.kt)("h4",{id:"see-also-136"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/ququzone/keyper"},"Keyper on GitHub"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"late-spawning"},"Late Spawning"),(0,i.kt)("p",null,"When a node joins a blockchain network for the first time after the network has already been in operation for a period of time."),(0,i.kt)("p",null,"A network is said to support late spawning if that participant can download and verify the entire blockchain without having to trust any of the participants in the network to feed them unaltered data."),(0,i.kt)("h4",{id:"see-also-137"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#genesis-block"},"Genesis Block"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"layer-1"},"Layer 1"),(0,i.kt)("p",null,"Layer 1 of a decentralized ecosystem is the underlying blockchain architecture."),(0,i.kt)("p",null,"A proof of work blockchain known as the Common Knowledge Base (CKB) that serves as the base layer for the Nervos Network. "),(0,i.kt)("h4",{id:"see-also-138"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckb"},"CKB")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-base"},"Common Knowledge Base")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#layer-2"},"Layer 2"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"layer-2"},"Layer 2"),(0,i.kt)("p",null,"Layer 2 refers to a secondary framework or protocol that is built on top of an existing blockchain system. "),(0,i.kt)("p",null,"The main goal of these protocols is to solve the transaction speed and scaling difficulties that are being faced by the major cryptocurrency networks."),(0,i.kt)("h4",{id:"see-also-139"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#layer-1"},"Layer 1"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"lina"},"Lina"),(0,i.kt)("p",null,"The name of public mainnet of the Nervos CKB."),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"CKB version"),": >= v0.25.2 (latest stable is recommended)"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"Genesis hash"),": 0x92b197aa1fba0f63633922c61c92375c9c074a93e85963554f5499fe1450d0e5"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"Init command"),": ",(0,i.kt)("inlineCode",{parentName:"li"},"ckb init --chain mainnet")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"Launched at"),": 2019-11-15 21:11:00 UTC")),(0,i.kt)("h4",{id:"synonyms-39"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mainnet"},"Mainnet"))),(0,i.kt)("h4",{id:"not-to-be-confused-with-4"},"Not To Be Confused With"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#aggron"},"Aggron")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#testnet"},"Testnet"))),(0,i.kt)("h4",{id:"see-also-140"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-ckb"},"Nervos CKB"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"live-cell"},"Live Cell"),(0,i.kt)("p",null,"A cell that has not been consumed and is available for use."),(0,i.kt)("p",null,"This is similar to an unspent transaction output (UTXO) in Bitcoin."),(0,i.kt)("h4",{id:"synonyms-40"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#active-cell"},"Active Cell"))),(0,i.kt)("h4",{id:"see-also-141"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell-model"},"Cell Model")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://developer.bitcoin.org/glossary.html"},"UTXO on Bitcoin.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"lock"},"Lock"),(0,i.kt)("p",null,"A script that represents the ownership of a cell. A user successfully unlocks a cell and is able to consume it if the cell's lock script exits normally. "),(0,i.kt)("h4",{id:"see-also-142"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script"))),(0,i.kt)("h3",{id:"lock-script"},"Lock Script"),(0,i.kt)("p",null,"A script that enforces access and ownership of a cell. This script controls who has permission to use the cell as an input. Lock scripts accept user generated proofs or witnesses and including transaction as inputs."),(0,i.kt)("h4",{id:"see-also-143"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script"},"Type Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#script"},"Script"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"lock-script-hash"},"Lock Script Hash"),(0,i.kt)("p",null,"A ",(0,i.kt)("a",{parentName:"p",href:"#blake2b"},"Blake2b")," hash of a lock script which is used as an identifier for the script when referenced by a cell."),(0,i.kt)("h4",{id:"see-also-144"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"mainnet"},"Mainnet"),(0,i.kt)("p",null,'Short for "main network", the running Nervos CKB public blockchain. The name of the Nervos CKB Mainnet is ',(0,i.kt)("a",{parentName:"p",href:"#lina"},"Lina"),"."),(0,i.kt)("h4",{id:"synonyms-41"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckb"},"CKB")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-base"},"Common Knowledge Base")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lina"},"Lina")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-ckb"},"Nervos CKB"))),(0,i.kt)("h4",{id:"not-to-be-confused-with-5"},"Not To Be Confused With"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#aggron"},"Aggron")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#testnet"},"Testnet"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"max_block_bytes"},(0,i.kt)("inlineCode",{parentName:"h3"},"max_block_bytes")),(0,i.kt)("p",null,"The maximum transaction size limit allowed in a block in bytes. Estimated based on the size consumed by 1000 2-in-2-out secp256k1 transactions."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"pub const MAX_BLOCK_BYTES: u64 = TWO_IN_TWO_OUT_BYTES * TWO_IN_TWO_OUT_COUNT;\n")),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"max_block_cycles"},(0,i.kt)("inlineCode",{parentName:"h3"},"max_block_cycles")),(0,i.kt)("p",null,"The maximum transaction cycle limit allowed in a block. Estimated based on the cycles consumed by 1000 2-in-2-out secp256k1 transactions."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"/// cycles of a typical two-in-two-out tx.\npub const TWO_IN_TWO_OUT_CYCLES: Cycle = 3_500_000;\n\n/// count of two-in-two-out txs a block should capable to package.\nconst TWO_IN_TWO_OUT_COUNT: u64 = 1_000;\npub(crate) const MAX_BLOCK_CYCLES: u64 = TWO_IN_TWO_OUT_CYCLES * TWO_IN_TWO_OUT_COUNT;\n")),(0,i.kt)("h4",{id:"see-also-145"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cycles"},"Cycles"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"max_block_proposals_limit"},(0,i.kt)("inlineCode",{parentName:"h3"},"max_block_proposals_limit")),(0,i.kt)("p",null,"The maximum amount of proposals contained in one block. The default value starts from 1.5."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"TWO_IN_TWO_OUT_COUNT\npub const MAX_BLOCK_PROPOSALS_LIMIT: u64 = 1_500;\n")),(0,i.kt)("h4",{id:"see-also-146"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proposal-zone"},"Proposal Zone"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"max_uncles_num"},(0,i.kt)("inlineCode",{parentName:"h3"},"max_uncles_num")),(0,i.kt)("p",null,"The maximum number (Uint64) of uncle blocks allowed for one block. Set as 2 by default."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"const MAX_UNCLE_NUM: usize = 2;\n")),(0,i.kt)("h4",{id:"see-also-147"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#uncle"},"Uncle"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"median_time_block_count"},(0,i.kt)("inlineCode",{parentName:"h3"},"median_time_block_count")),(0,i.kt)("p",null,"A timestamp is valid only when it is greater than the median timestamp of the previous 37 blocks."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"const MEDIAN_TIME_BLOCK_COUNT: usize = 37;\n")),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"minting"},"Minting"),(0,i.kt)("p",null,"The process of creating of new tokens."),(0,i.kt)("h4",{id:"see-also-148"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"molecule"},"Molecule"),(0,i.kt)("p",null,"A serialization framework for encoding data widely used on the Nervos Network."),(0,i.kt)("h4",{id:"see-also-149"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0008-serialization/0008-serialization.md"},"Molecule Specification")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/molecule"},"Molecule on Github")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/ckb/tree/develop/util/types/schemas"},"Molecule Schema used in CKB"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"muta"},"Muta"),(0,i.kt)("p",null,"A highly customizable, high-performance blockchain framework designed to support proof of stake, BFT consensus and smart contracts."),(0,i.kt)("h4",{id:"see-also-150"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/muta"},"Muta on GitHub")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proof-of-stake"},"Proof of Stake"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"nervos-ckb"},"Nervos CKB"),(0,i.kt)("p",null,"The layer 1 blockchain of the Nervos Network, the Common Knowledge Base."),(0,i.kt)("p",null,"Nervos CKB is often referred to as the Nervos Blockchain."),(0,i.kt)("h4",{id:"synonyms-42"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckb"},"CKB")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-base"},"Common Knowledge Base")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nervos-blockchain"},"Nervos Blockchain"))),(0,i.kt)("h4",{id:"see-also-151"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#layer-1"},"Layer 1"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"off-chain-computation"},"Off-Chain Computation"),(0,i.kt)("p",null,"A programming model where all computation is done off-chain to reduce the burden on the nodes in the network and provide higher levels of scalability. Nervos uses off-chain computation and on-chain verification."),(0,i.kt)("h4",{id:"see-also-152"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#on-chain-computation"},"On-Chain Computation")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#on-chain-verification"},"On-Chain Verification"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"off-chain-scaling"},"Off-Chain Scaling"),(0,i.kt)("p",null,"Off-chain scaling is the approach that only using the blockchain as a secure asset and settlement platform in conjunction with transferring almost all transactions off the blockchain."),(0,i.kt)("h4",{id:"see-also-153"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#on-chain-scaling"},"On-Chain Scaling"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"off-chain-state"},"Off-Chain State"),(0,i.kt)("p",null,"The data of an application that is not stored on the blockchain, or is not accessible by on-chain smart contracts."),(0,i.kt)("h4",{id:"see-also-154"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#on-chain-state"},"On-Chain State"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"on-chain-computation"},"On-Chain Computation"),(0,i.kt)("p",null,"A programming model where all computation by smart contracts is done on-chain by every node on the network simultaneously."),(0,i.kt)("p",null,"Ethereum uses on-chain computation."),(0,i.kt)("h4",{id:"see-also-155"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#off-chain-computation"},"Off-Chain Computation"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"on-chain-scaling"},"On-Chain Scaling"),(0,i.kt)("p",null,"On-chain scaling solution refer to extending the throughput of the consensus process, or increasing network throughput as node number increases."),(0,i.kt)("h4",{id:"see-also-156"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#off-chain-scaling"},"Off-chain Scaling"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"on-chain-state"},"On-Chain State"),(0,i.kt)("p",null,"The data of an application that is stored on the blockchain and is accessible by on-chain smart contracts."),(0,i.kt)("p",null,"Nervos provides on-chain state for all smart contracts."),(0,i.kt)("h4",{id:"see-also-157"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#off-chain-state"},"Off-Chain State"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"on-chain-verification"},"On-Chain Verification"),(0,i.kt)("p",null,"A programming model where all computation is done off-chain to reduce the burden on the nodes in the network, but verification of the resulting data is done on-chain to enforce the smart contract rules created by the developer."),(0,i.kt)("p",null,"Nervos uses off-chain computation and on-chain verification."),(0,i.kt)("h4",{id:"see-also-158"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#on-chain-computation"},"On-Chain Computation"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"open-transaction"},"Open Transaction"),(0,i.kt)("p",null,"A signed piece of a transaction that is incomplete and invalid on its own. When combined with other signed transaction pieces can form a complete transaction which can be processed."),(0,i.kt)("p",null,"One use of open transactions is to create the functionality required for a trustless decentalized exchange."),(0,i.kt)("h4",{id:"see-also-159"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cryptographic-signature"},"Cryptographic Signature")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"optimistic-rollup"},"Optimistic Rollup"),(0,i.kt)("p",null,"A rollup of transactions that use fraud proofs to offer increased layer 2 transaction throughput while using the security and data availability provided by layer 1."),(0,i.kt)("h4",{id:"see-also-160"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#layer-1"},"Layer 1")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#layer-2"},"Layer 2"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"orphan"},"Orphan"),(0,i.kt)("p",null,"A shorthand name for Orphan Block."),(0,i.kt)("h4",{id:"synonyms-43"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan-block"},"Orphan Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#uncle"},"Uncle"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"orphan-block"},"Orphan Block"),(0,i.kt)("p",null,"An orphan block is a valid block that is not included in the main fork due to, for example, a lag within the network itself. There can be two miners who solve a block simultaneously in NC-Max. They are non-main-chain blocks, also known as stale blocks."),(0,i.kt)("p",null,"In Nervos, orphan blocks are better described as Uncles."),(0,i.kt)("h4",{id:"synonyms-44"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan"},"Orphan")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#uncle"},"Uncle"))),(0,i.kt)("h4",{id:"see-also-161"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block"},"Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nc-max"},"NC-Max")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan-rate"},"Orphan Rate"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"orphan-rate"},"Orphan Rate"),(0,i.kt)("p",null,"A measure of the speed at which Orphan blocks occur within the blockchain network."),(0,i.kt)("h4",{id:"see-also-162"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan-block"},"Orphan Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#%60orphan_rate_target%60"},(0,i.kt)("inlineCode",{parentName:"a"},"orphan_rate_target")))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"orphan_rate_target"},(0,i.kt)("inlineCode",{parentName:"h3"},"orphan_rate_target")),(0,i.kt)("p",null,"The estimated orphan block rate specified in NC-max. Set as 2.5% in CKB."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"// o_ideal = 1/40 = 2.5%\npub(crate) const DEFAULT_ORPHAN_RATE_TARGET: (u32, u32) = (1, 40);\n")),(0,i.kt)("h4",{id:"see-also-163"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan-rate"},"Orphan Rate")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan-block"},"Orphan Block"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"orphan-transactions"},"Orphan Transactions"),(0,i.kt)("p",null,"Orphan transactions are those whose parental transactions are missing at the time that they are processed. These transactions are not propagated to other nodes until all of their missing parents are received, and they thus end up languishing in a local buffer until evicted or their parents are found."),(0,i.kt)("h4",{id:"see-also-164"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan-block"},"Orphan Block"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"outbound-connection"},"Outbound Connection"),(0,i.kt)("p",null,'Also knowns as "outgoing connection".'),(0,i.kt)("p",null,"A TCP connection is outgoing for the node if it was initiated (sent the TCP SYN packet) by the node in the context."),(0,i.kt)("h4",{id:"see-also-165"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#inbound-connection"},"Inbound Connection"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"outpoint"},"Outpoint"),(0,i.kt)("p",null,"A particular output Cell in a transaction."),(0,i.kt)("h4",{id:"see-also-166"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#output"},"Output")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"output"},"Output"),(0,i.kt)("p",null,"A live cell that is created in a transaction."),(0,i.kt)("h4",{id:"see-also-167"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#live-cell"},"Live Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"overlord"},"Overlord"),(0,i.kt)("p",null,"A byzantine fault tollerant consensus algorithm designed by Nervos for Huobi which can support thousands of transactions per second."),(0,i.kt)("h4",{id:"see-also-168"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://medium.com/nervosnetwork/overlord-a-new-consensus-algorithm-3cc51690d269"},"Overlord on Medium"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"p2wsh"},"P2WSH"),(0,i.kt)("p",null,"A Pay-to-Witness-Script-Hash (P2WSH) is a type of Bitcoin transaction similar to a ",(0,i.kt)("a",{parentName:"p",href:"https://en.bitcoin.it/wiki/Pay_to_script_hash"},"P2SH")," transaction in most ways, except that it uses ",(0,i.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/SegWit"},"SegWit"),"."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"permanent_difficulty_in_dummy"},(0,i.kt)("inlineCode",{parentName:"h3"},"permanent_difficulty_in_dummy")),(0,i.kt)("p",null,"Keeps the difficulty permanent if PoW is dummy when dev-chain disables NC-MAX difficulty adjustment. As ",(0,i.kt)("inlineCode",{parentName:"p"},"boolean"),", it can be enabled through configuration."),(0,i.kt)("h4",{id:"see-also-169"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#difficulty"},"Difficulty"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"polyjuice"},"Polyjuice"),(0,i.kt)("p",null,"Polyjuice provides an Ethereum compatible runtime on Godwoken."),(0,i.kt)("h4",{id:"see-also-170"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#godwoken"},"Godwoken")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/polyjuice"},"Polyjuice on GitHub"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"primary_epoch_reward_halving_interval"},(0,i.kt)("inlineCode",{parentName:"h3"},"primary_epoch_reward_halving_interval")),(0,i.kt)("p",null,"The halving cycle of epoch reward in CKB base issuance, typically every four years. The mining reward halves when the halving interval occurs."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"pub(crate) const DEFAULT_PRIMARY_EPOCH_REWARD_HALVING_INTERVAL: EpochNumber =\n4 * 365 * 24 * 60 * 60 / DEFAULT_EPOCH_DURATION_TARGET; // every 4 years\n")),(0,i.kt)("h4",{id:"see-also-171"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#%60initial_primary_epoch_reward%60"},(0,i.kt)("inlineCode",{parentName:"a"},"initial_primary_epoch_reward")))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"proposal-zone"},"Proposal Zone"),(0,i.kt)("p",null,"Section of the block that contains transaction proposals."),(0,i.kt)("h4",{id:"see-also-172"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#commitment-zone"},"Commitment Zone")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#propose"},"Propose"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"propose"},"Propose"),(0,i.kt)("p",null,"The process of taking an unconfirmed transaction out of the mempool and proposing it for commitment. A transaction is not confirmed until after it has been committed."),(0,i.kt)("p",null,"Miners are incentivized to propose transactions by being paid a proposal reward."),(0,i.kt)("h4",{id:"see-also-173"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#commit"},"Commit")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#confirmation"},"Confirmation")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mempool"},"Mempool")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proposal-reward"},"Proposal Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proposal-zone"},"Proposal Zone")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"proposer_reward_ratio"},(0,i.kt)("inlineCode",{parentName:"h3"},"proposer_reward_ratio")),(0,i.kt)("p",null,"The reward ratio from transaction fees for miners who submit proposals specified by NC-Max. It is set as 40% in CKB, meaning the miner who first submits the transaction proposal will be rewarded with 40% of the transaction fee."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"const PROPOSER_REWARD_RATIO: Ratio = Ratio::new(4, 10);\n")),(0,i.kt)("h4",{id:"see-also-174"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#proposal-reward"},"Proposal Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nc-max"},"NC-Max"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"risc-v"},"RISC-V"),(0,i.kt)("p",null,"An open standard instruction set architecture (ISA) for general computing."),(0,i.kt)("p",null,"RISC-V is the instruction set used by the CKB-VM."),(0,i.kt)("h4",{id:"see-also-175"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckb-vm"},"CKB-VM")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/RISC-V"},"RISC-V on Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"schnorr-signature"},"Schnorr Signature"),(0,i.kt)("p",null,"A cryptographic signature scheme for signing and verification."),(0,i.kt)("h4",{id:"see-also-176"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Schnorr_signature"},"Schnorr Signature on Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"script"},"Script"),(0,i.kt)("p",null,"A program that executes on the CKB-VM. A Script can be one of two types:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Lock Script - Used to control ownership and access to a Cell."),(0,i.kt)("li",{parentName:"ul"},"Type Script - Used to control how a Cell is used in a transaction.")),(0,i.kt)("p",null,"A script is a binary executable in the ELF format for the RISC-V architecture, a program that runs on the CKB-VM."),(0,i.kt)("h4",{id:"see-also-177"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#risc-v"},"CKB-VM")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#risc-v"},"RISC-V")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script"},"Type Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Executable_and_Linkable_Format"},"ELF on Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"secondary_epoch_reward"},(0,i.kt)("inlineCode",{parentName:"h3"},"secondary_epoch_reward")),(0,i.kt)("p",null,"The secondary reward per epoch. Issued according to CKB\u2019s tokenomics detailed in ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0015-ckb-cryptoeconomics/0015-ckb-cryptoeconomics.md"},"RFC0015"),". "),(0,i.kt)("p",null,"Secondary issuance is designed to collect state rent, and has an issuance amount that is constant over time. After base issuance stops, there will only be secondary issuance."),(0,i.kt)("p",null,"Secondary issuance has two parts. One is a fixed amount of base incentive (approximately 134.4 million CKBytes per year), while the other varies according to the number of CKBytes currently occupied."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"pub(crate) const DEFAULT_SECONDARY_EPOCH_REWARD: Capacity = Capacity::shannons(613_698_63013698);\n")),(0,i.kt)("h4",{id:"see-also-178"},"See also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#%60initial_primary_epoch_reward%60"},(0,i.kt)("inlineCode",{parentName:"a"},"initial_primary_epoch_reward"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#secondary-reward"},"Secondary Reward")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#secondary-issuance"},"Secondary Issuance"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"secp256k1_blake160_sighash_all_type_hash"},(0,i.kt)("inlineCode",{parentName:"h3"},"secp256k1_blake160_sighash_all_type_hash")),(0,i.kt)("p",null,"Type hash of ",(0,i.kt)("inlineCode",{parentName:"p"},"secp256k1_blake160_sighash_all")," in ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0024-ckb-genesis-script-list/0024-ckb-genesis-script-list.md#ckb-genesis-script-list"},"CKB genesis scripts"),"."),(0,i.kt)("p",null,"Find more details ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0024-ckb-genesis-script-list/0024-ckb-genesis-script-list.md#secp256k1blake160"},"here"),"."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"secp256k1_blake160_multisig_all_type_hash"},(0,i.kt)("inlineCode",{parentName:"h3"},"secp256k1_blake160_multisig_all_type_hash")),(0,i.kt)("p",null,"Type hash of ",(0,i.kt)("inlineCode",{parentName:"p"},"secp256k1_blake160_multisig_all")," in ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0024-ckb-genesis-script-list/0024-ckb-genesis-script-list.md#ckb-genesis-script-list"},"CKB genesis scripts"),"."),(0,i.kt)("p",null,"Find more details ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0024-ckb-genesis-script-list/0024-ckb-genesis-script-list.md#secp256k1multisig"},"here"),"."),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"seed-cell"},"Seed Cell"),(0,i.kt)("p",null,"A design pattern on Nervos from creating unique identifiers used to create unforgeable assets."),(0,i.kt)("h4",{id:"see-also-179"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"shannon"},"Shannon"),(0,i.kt)("p",null,"A fractional denomination of CKBytes. One CKByte is equal to 100,000,000 Shannons."),(0,i.kt)("p",null,"A Shannon is the equivalent of a Bitcoin Satoshi."),(0,i.kt)("h4",{id:"see-also-180"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbyte"},"CKByte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#common-knowledge-byte"},"Common Knowledge Byte")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://developer.bitcoin.org/glossary.html"},"Satoshi (denomination) on Bitcoin.org"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"short-address"},"Short Address"),(0,i.kt)("p",null,"An address format on Nervos that does not include a code hash of the associated lock script, instead using one of the many common lock scripts."),(0,i.kt)("p",null,'The short address format is the most common address format used, and is often referred to as simply "address".'),(0,i.kt)("h4",{id:"synonyms-45"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#address"},"Address"))),(0,i.kt)("h4",{id:"see-also-181"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#code-hash"},"Code Hash")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#full-address"},"Full Address"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"simple-udt"},"Simple UDT"),(0,i.kt)("p",null,"A standard that defines a the most basic implementation of a UDT fungible token on Nervos. "),(0,i.kt)("p",null,"An SUDT on Nervos is the equivalent of Ethereum tokens standards ERC20 or ERC777."),(0,i.kt)("h4",{id:"synonyms-46"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#sudt"},"SUDT"))),(0,i.kt)("h4",{id:"see-also-182"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#token"},"Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#udt"},"UDT")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#user-defined-token"},"User-Defined Token")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://eips.ethereum.org/EIPS/eip-20"},"ERC20 on Ethereum.org")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0025-simple-udt/0025-simple-udt.md"},"Simple UDT RFC on Nervos Nerwork Github"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"since"},"Since"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"since")," is the u64 (unsigned 64-bit integer) field in transaction input for preventing inclusion before a certain block timestamp or a block number."),(0,i.kt)("h4",{id:"see-also-183"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"spv"},"SPV"),(0,i.kt)("p",null,"An abbreviation for Simplified Payment Verification. A protocol for using a blockchain cryptocurrency without having to operate a full node."),(0,i.kt)("p",null,"SPV clients require far less data to be stored, but also must requires the trust of the network clients it is connected to directly."),(0,i.kt)("h4",{id:"see-also-184"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#spv-wallet"},"SPV Wallet")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.bitcoinwiki.org/wiki/Simplified_Payment_Verification"},"Simplified Payment Verification on BitcoinWiki"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"spv-wallet"},"SPV Wallet"),(0,i.kt)("p",null,"A light-weight cryptocurrency wallet that uses the SPV protocol."),(0,i.kt)("h4",{id:"see-also-185"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#spv"},"SPV"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"sudt"},"SUDT"),(0,i.kt)("p",null,"An abbreviation for Simple UDT."),(0,i.kt)("h4",{id:"synonyms-47"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#simple-udt"},"Simple UDT"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"testnet"},"Testnet"),(0,i.kt)("p",null,"Short for \u201ctest network,\u201d a network used to simulate the behavior of the ",(0,i.kt)("a",{parentName:"p",href:"#mainnet"},"Mainnet"),". The name of the Nervos CKB Testnet is ",(0,i.kt)("a",{parentName:"p",href:"#aggron"},"Aggron"),"."),(0,i.kt)("h4",{id:"synonyms-48"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#aggron"},"Aggron"))),(0,i.kt)("h4",{id:"not-to-be-confused-with-6"},"Not To Be Confused With"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lina"},"Lina")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#mainnet"},"Mainnet"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"transaction-confirmation-number"},"Transaction Confirmation Number"),(0,i.kt)("p",null,"The number of confirmations required for a transaction to be added to a block. "),(0,i.kt)("p",null,"As permissionless blockchain designs offer only probabilistic finality, a transaction can never be fully confirmed, facing an adversary with infinite computational power. Therefore, users and apps can choose a number they deem secure. We briefly discuss one factor here that influences the level of security: the recent orphan rate. It takes 6 confirmations to fully settle a transaction when the orphan rate is 0, and 24 confirmations when the rate reaches 2.5% to achieve the same level of security (See the rationale and calculation ",(0,i.kt)("a",{parentName:"p",href:"https://docs.nervos.org/docs/essays/tx-confirmation/"},"here"),")."),(0,i.kt)("p",null,"In blockchain settlement assurance, transaction confirmation is one of the variables that cannot be easily quantified (See Nic Carter\u2019s ",(0,i.kt)("a",{parentName:"p",href:"https://medium.com/@nic__carter/its-the-settlement-assurances-stupid-5dcd1c3f4e41"},"article"),"). The exact number is open to adjustment depending on the security level that users desire. Nervos CKB sets a minimum of 15 confirmations, which should be considered conservative."),(0,i.kt)("h4",{id:"see-also-186"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#confirmation"},"Confirmation")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#nc-max"},"NC-Max")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan-block"},"Orphan Block")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan-rate"},"Orphan Rate"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"transaction-hash"},"Transaction Hash"),(0,i.kt)("p",null,"Transaction hash, or Txhash, is the unique identifier of a transaction in a blockchain that acts as a record or proof that the transaction has taken place. To get a transaction hash in CKB, the transaction is serialized via Molecule, then the serialized raw is feed to ckbhash function. Its schema is:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"table Transaction {\n raw: RawTransaction,\n witnesses: BytesVec,\n}\n")),(0,i.kt)("p",null,"Transaction hash is generated by the serialized ",(0,i.kt)("inlineCode",{parentName:"p"},"raw")," structure through ",(0,i.kt)("a",{parentName:"p",href:"#ckbhash"},"ckbhash"),"."),(0,i.kt)("h4",{id:"see-also-187"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction-witness-hash"},"Transaction Witness Hash")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#molecule"},"Molecule")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbhash"},"Ckbhash")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0027-block-structure/0027-block-structure.md#transaction-hash"},"Transaction Hash in RFC on Nervos Network Github"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"transaction-witness-hash"},"Transaction Witness Hash"),(0,i.kt)("p",null,"Transaction witness hash is generated by the serialized transaction through ckbhash. Transaction is serialized via ",(0,i.kt)("a",{parentName:"p",href:"#molecule"},"molecule")," in CKB. Its schema is:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"table Transaction {\n raw: RawTransaction,\n witnesses: BytesVec,\n}\n")),(0,i.kt)("h4",{id:"see-also-188"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction-hash"},"Transaction Hash")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#molecule"},"Molecule")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbhash"},"Ckbhash"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"transaction-root"},"Transaction Root"),(0,i.kt)("p",null,"The field ",(0,i.kt)("inlineCode",{parentName:"p"},"transactions_root")," in header is"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"ckbhash(T || W)\n")),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},(0,i.kt)("inlineCode",{parentName:"p"},"ckbhash")," is the hash function, ",(0,i.kt)("inlineCode",{parentName:"p"},"||")," denotes binary concatenation.")),(0,i.kt)("p",null,"T is the root of a ",(0,i.kt)("a",{parentName:"p",href:"#ckb-merkle-tree"},"CKB Merkle Tree"),", which items are the ",(0,i.kt)("a",{parentName:"p",href:"#transaction-hash"},"transaction hashes")," of all the transactions in the block."),(0,i.kt)("p",null,"W is also the root of a ",(0,i.kt)("a",{parentName:"p",href:"#ckb-merkle-tree"},"CKB Merkle Tree"),", but the items are the ",(0,i.kt)("a",{parentName:"p",href:"#transaction-witness-hash"},"Transaction Witness Hash")," of all the transactions in the block."),(0,i.kt)("h4",{id:"see-also-189"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckbhash"},"Ckbhash")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckb-merkle-tree"},"CKB Merkle Tree")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction-witness-hash"},"Transaction Witness Hash"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"tx_proposal_window"},(0,i.kt)("inlineCode",{parentName:"h3"},"tx_proposal_window")),(0,i.kt)("p",null,"Interval for submitting proposals in the second stage specified by NC-Max. Set between 2 and 10 blocks in CKB."),(0,i.kt)("img",{src:(0,o.Z)("img/tx-proposal-window.png")}),(0,i.kt)("p",null,"As shown above, when a transaction is first proposed in Block 13, it can be committed in the window between Block 15 and Block 23."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"pub(crate) const TX_PROPOSAL_WINDOW: ProposalWindow = ProposalWindow(2, 10);\n")),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"tx_version"},(0,i.kt)("inlineCode",{parentName:"h3"},"tx_version")),(0,i.kt)("p",null,"The version of a transaction. This field is set to 0 and is reserved for the system."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"pub const TX_VERSION: Version = 0;\n")),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"type_id"},(0,i.kt)("inlineCode",{parentName:"h3"},"type_id")),(0,i.kt)("p",null,"One of the CKB ",(0,i.kt)("inlineCode",{parentName:"p"},"system_scripts"),". A unique feature of Type ID is that it\u2018s a CKB built-in script directly implemented in Rust. It doesn't run in CKB-VM but can be used in the same way as other ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0024-ckb-genesis-script-list/0024-ckb-genesis-script-list.md#type-id"},"CKB genesis scripts"),"."),(0,i.kt)("p",null,"For a deeper understanding of Type ID, check out this blog post: ",(0,i.kt)("a",{parentName:"p",href:"https://xuejie.space/2020_02_03_introduction_to_ckb_script_programming_type_id/"},"Introduction to CKB Script Programming 6: Type ID")," (also translated into ",(0,i.kt)("a",{parentName:"p",href:"https://talk.nervos.org/t/ckb-type-id/4258"},"Chinese"),")."),(0,i.kt)("h4",{id:"see-also-190"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#script"},"Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script"},"Type Script"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"type_id_code_hash"},(0,i.kt)("inlineCode",{parentName:"h3"},"type_id_code_hash")),(0,i.kt)("p",null,"The ",(0,i.kt)("inlineCode",{parentName:"p"},"code_hash")," of ",(0,i.kt)("inlineCode",{parentName:"p"},"type_id"),". In view of the specificity of ",(0,i.kt)("inlineCode",{parentName:"p"},"type_id"),", ",(0,i.kt)("inlineCode",{parentName:"p"},"type_id_code_hash")," is hard-coded, not the hash of the actual code."),(0,i.kt)("h4",{id:"see-also-191"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#%60type_id%60"},(0,i.kt)("inlineCode",{parentName:"a"},"type_id")))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"type-script"},"Type Script"),(0,i.kt)("p",null,"A script that enforces the rules that must be followed in a transaction for a cell to be consumed as an input or for a cell to be created as an output."),(0,i.kt)("h4",{id:"see-also-192"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#script"},"Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script-hash"},"Type Script Hash"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"type-script-hash"},"Type Script Hash"),(0,i.kt)("p",null,"Or ",(0,i.kt)("inlineCode",{parentName:"p"},"type_hash"),", a Blake2b hash of a Type Script which is used as an identifier for the Script when referenced by a Cell."),(0,i.kt)("p",null,"The two entities in the data structure of CKB\u2019s cell are ",(0,i.kt)("inlineCode",{parentName:"p"},"lock")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"type"),". Type scripts can capture any validation logic needed in the cell transformation."),(0,i.kt)("p",null,"Type scripts can implement economic constructs as well. NervosDAO is completely implemented as a type script with minimal support from the consensus layer."),(0,i.kt)("h4",{id:"see-also-193"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#cell"},"Cell")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#script"},"Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script"},"Type Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/ckb-system-scripts/blob/66d7da8ec72dffaa7e9c55904833951eca2422a9/c/dao.c"},"NervosDAO"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"uncle"},"Uncle"),(0,i.kt)("p",null,"Or Uncle Block. Uncle blocks are created when two blocks are mined and submitted to the ledger at roughly the same time. Only one can enter the ledger as an included block, and the other does not."),(0,i.kt)("p",null,"Uncles are paid a reduced block reward when they are found and reported."),(0,i.kt)("p",null,"On Nervos, Uncles are tracked by consensus to adjust the block interval of the network."),(0,i.kt)("p",null,"An uncle block has to meet the following conditions:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"An uncle should not be on the main chain; in other words, it should not be an uncle if it includes any block from the main chain."),(0,i.kt)("li",{parentName:"ul"},"Uncle\u2019s block number must be smaller than the block\u2018s number that later includes it."),(0,i.kt)("li",{parentName:"ul"},"Uncle\u2018s parent must be on the main chain, or uncle\u2019s parent must also be an uncle. In other words, uncle must be linkable to the main chain in any way. It can never be a random block that is not on the main chain.")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"- if !snapshot.is_main_chain(&uncle.hash()) // It should not be on the main chain.\n- && !snapshot.is_uncle(&uncle.hash()) // It should not be an uncle twice. \n- && uncle.number() < candidate_number // The block number of the uncle should be smaller than that of any block on the main chain. \n- && (uncles.iter().any(|u| u.hash() == parent_hash) \n|| snapshot.is_main_chain(&parent_hash) // Uncle block should not be parentless. The parent of un uncle must be a block on the main chain or another uncle. \n|| snapshot.is_uncle(&parent_hash))\n")),(0,i.kt)("img",{src:(0,o.Z)("img/uncle_rule.png")}),(0,i.kt)("p",null,"As illustrated above, A is the main chain. B3 can be the uncle of A4 (to be included in A4), since B3 is linked to A2. However, B4 cannot be included in A4, since the uncle\u2019s block number must be smaller than A4, the current block on the main chain."),(0,i.kt)("p",null,"Similarly, B4 can be the uncle of A5 (be included by A5). Although B4\u2018s parent, B3, is not on the main chain, B3 is the uncle of A4. For this reason, B4 is a legal uncle, and B3 cannot be included by A5."),(0,i.kt)("p",null,"C2 and C3 cannot be linked to the main chain as their parent is unknown, therefore, they cannot be uncles."),(0,i.kt)("h4",{id:"see-also-194"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#%60max_uncles_num%60"},(0,i.kt)("inlineCode",{parentName:"a"},"max_uncles_num")))),(0,i.kt)("h4",{id:"synonyms-49"},"Synonyms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan-block"},"Orphan Block"))),(0,i.kt)("h4",{id:"see-also-195"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#block-interval"},"Block Interval")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan-rate"},"Orphan Rate")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#uncle"},"Uncle"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"uncle-rate"},"Uncle Rate"),(0,i.kt)("h4",{id:"see-also-196"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#orphan-rate"},"Orphan Rate")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#uncle"},"Uncle"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"validator"},"Validator"),(0,i.kt)("p",null,"A script that is used to ensure that the transactions created by the generators are valid. Validators are scripts that run in CKB-VM as either lock scripts or type scripts."),(0,i.kt)("h4",{id:"see-also-197"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ckb-vm"},"CKB-VM")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#lock-script"},"Lock Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#type-script"},"Type Script")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"witness"},"Witness"),(0,i.kt)("p",null,"A set of cryptographic proof containing the data required to prove authorization of the resources used in the transaction."),(0,i.kt)("h4",{id:"see-also-198"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"zk-snark"},"Zk-SNARK"),(0,i.kt)("p",null,"A form of cryptographic proof, that when used in cryptocurrencies, allows for privacy features which do not reveal the amounts or participants in transactions."),(0,i.kt)("p",null,"Zk-SNARKs require a trusted setup, but are otherwise trustless."),(0,i.kt)("h4",{id:"see-also-199"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#zk-stark"},"Zk-STARK")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Non-interactive_zero-knowledge_proof"},"Non-interactive zero-knowledge proofs on Wikipedia"))),(0,i.kt)("hr",null),(0,i.kt)("h3",{id:"zk-stark"},"Zk-STARK"),(0,i.kt)("p",null,"A form of cryptographic proof, that when used in cryptocurrencies, allows for privacy features which do not reveal the amounts or participants in transactions."),(0,i.kt)("p",null,"Unlike Zk-SNARKs, Zk-STARKs do not require a trusted setup."),(0,i.kt)("h4",{id:"see-also-200"},"See Also"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#transaction"},"Transaction")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#zk-snark"},"Zk-SNARK")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Non-interactive_zero-knowledge_proof"},"Non-interactive zero-knowledge proofs on Wikipedia"))),(0,i.kt)("hr",null))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/2c43fa15.207825b9.js b/assets/js/2c43fa15.207825b9.js new file mode 100644 index 000000000..ca0fd37ff --- /dev/null +++ b/assets/js/2c43fa15.207825b9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[7277],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>k});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var o=a.createContext({}),s=function(e){var t=a.useContext(o),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},d=function(e){var t=s(e.components);return a.createElement(o.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},p=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,l=e.originalType,o=e.parentName,d=c(e,["components","mdxType","originalType","parentName"]),p=s(n),k=r,h=p["".concat(o,".").concat(k)]||p[k]||u[k]||l;return n?a.createElement(h,i(i({ref:t},d),{},{components:n})):a.createElement(h,i({ref:t},d))}));function k(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var l=n.length,i=new Array(l);i[0]=p;var c={};for(var o in t)hasOwnProperty.call(t,o)&&(c[o]=t[o]);c.originalType=e,c.mdxType="string"==typeof e?e:r,i[1]=c;for(var s=2;s{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>o,default:()=>k,frontMatter:()=>c,metadata:()=>s,toc:()=>u});var a=n(7462),r=n(3366),l=(n(7294),n(3905)),i=["components"],c={id:"devchain",title:"Run a CKB Dev Blockchain"},o=void 0,s={unversionedId:"basics/guides/devchain",id:"basics/guides/devchain",title:"Run a CKB Dev Blockchain",description:"Nervos CKB supports a special development mode that is particularly useful for building and testing applications. This mode of operation is highly configurable, and allows the developer to speed up the block interval, adjust epochs lengths, create blocks without having to do Proof-of-Work (PoW) mining.",source:"@site/docs/basics/guides/devchain.md",sourceDirName:"basics/guides",slug:"/basics/guides/devchain",permalink:"/docs/basics/guides/devchain",draft:!1,editUrl:"https://github.com/nervosnetwork/docs-new/tree/develop/website/docs/basics/guides/devchain.md",tags:[],version:"current",frontMatter:{id:"devchain",title:"Run a CKB Dev Blockchain"},sidebar:"Basics",previous:{title:"Crypto Wallet",permalink:"/docs/basics/concepts/cryptowallet"},next:{title:"Run a CKB Node",permalink:"/docs/basics/guides/mainnet"}},d={},u=[{value:"Setup a Dummy-Worker Blockchain",id:"setup-a-dummy-worker-blockchain",level:2},{value:"1. Download the Latest CKB Binary",id:"1-download-the-latest-ckb-binary",level:3},{value:"2. Initialize the Configuration",id:"2-initialize-the-configuration",level:3},{value:"3. Configure the Block Assembler",id:"3-configure-the-block-assembler",level:3},{value:"3a. Create a New Account",id:"3a-create-a-new-account",level:4},{value:"3b. Update the Configuration",id:"3b-update-the-configuration",level:4},{value:"4. Adjust the Parameters to Shorten the Block Interval (Optional)",id:"4-adjust-the-parameters-to-shorten-the-block-interval-optional",level:3},{value:"4a. Change the Number of Blocks in an Epoch",id:"4a-change-the-number-of-blocks-in-an-epoch",level:4},{value:"4b. Use Permanent Difficulty",id:"4b-use-permanent-difficulty",level:4},{value:"4c. Change the Mining Interval",id:"4c-change-the-mining-interval",level:4},{value:"5. Start the CKB Node",id:"5-start-the-ckb-node",level:3},{value:"6. Start the CKB Miner",id:"6-start-the-ckb-miner",level:3},{value:"Setup an Eaglesong-Worker Blockchain",id:"setup-an-eaglesong-worker-blockchain",level:2},{value:"1. Download the Latest CKB Binary",id:"1-download-the-latest-ckb-binary-1",level:3},{value:"2. Create a New Account",id:"2-create-a-new-account",level:4},{value:"3. Initialize the Configuration with the Miner Account",id:"3-initialize-the-configuration-with-the-miner-account",level:3},{value:"4. Change the PoW Function to Eaglesong",id:"4-change-the-pow-function-to-eaglesong",level:3},{value:"5. Start the CKB Node",id:"5-start-the-ckb-node-1",level:3},{value:"6. Start the CKB Miner",id:"6-start-the-ckb-miner-1",level:3},{value:"Transferring CKBytes Using ckb-cli",id:"transferring-ckbytes-using-ckb-cli",level:2},{value:"1. Enter the ckb-cli Interface",id:"1-enter-the-ckb-cli-interface",level:3},{value:"2. Create a New Account",id:"2-create-a-new-account-1",level:3},{value:"4. Transfer 10,000 CKBytes to the New Account",id:"4-transfer-10000-ckbytes-to-the-new-account",level:3},{value:"5. Check the New Account's Balance",id:"5-check-the-new-accounts-balance",level:3},{value:"Adding the Genesis Issued Cells",id:"adding-the-genesis-issued-cells",level:2},{value:"1. Create Private Key Files",id:"1-create-private-key-files",level:3},{value:"2. Import the Private Keys",id:"2-import-the-private-keys",level:3}],p={toc:u};function k(e){var t=e.components,n=(0,r.Z)(e,i);return(0,l.kt)("wrapper",(0,a.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,l.kt)("p",null,"Nervos CKB supports a special development mode that is particularly useful for building and testing applications. This mode of operation is highly configurable, and allows the developer to speed up the block interval, adjust epochs lengths, create blocks without having to do Proof-of-Work (PoW) mining."),(0,l.kt)("p",null,"When running a development blockchain you have the option of selecting between ",(0,l.kt)("inlineCode",{parentName:"p"},"Dummy-Worker")," and ",(0,l.kt)("inlineCode",{parentName:"p"},"Eaglesong-Worker"),". ",(0,l.kt)("inlineCode",{parentName:"p"},"Dummy-Worker")," allows the mining of blocks at a constant block interval without PoW. ",(0,l.kt)("inlineCode",{parentName:"p"},"Eaglesong-Worker")," uses real PoW to produce blocks."),(0,l.kt)("p",null,"Note: It is highly recommended that ",(0,l.kt)("inlineCode",{parentName:"p"},"Dummy-Worker")," be used for most development scenarios. ",(0,l.kt)("inlineCode",{parentName:"p"},"Eaglesong-Worker")," should only be used when validating the PoW function is necessary, because the block time can behave erratically with extremely low hashrates."),(0,l.kt)("h2",{id:"setup-a-dummy-worker-blockchain"},"Setup a Dummy-Worker Blockchain"),(0,l.kt)("h3",{id:"1-download-the-latest-ckb-binary"},"1. Download the Latest CKB Binary"),(0,l.kt)("p",null,"Download the latest ",(0,l.kt)("inlineCode",{parentName:"p"},"ckb")," binary file from the CKB releases page on ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/ckb/releases"},"GitHub"),"."),(0,l.kt)("p",null,"The following commands can be used to verify the binaries are working and to check versions:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"ckb --version\nckb-cli --version\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"ckb 0.32.1 (9ebc9ce 2020-05-29)\nckb-cli 0.32.0 (0fc435d 2020-05-22)\n"))),(0,l.kt)("h3",{id:"2-initialize-the-configuration"},"2. Initialize the Configuration"),(0,l.kt)("p",null,"Use the following command to initialize the development blockchain and generate the required configuration files:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"ckb init --chain dev\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"WARN: mining feature is disabled because of lacking the block assembler config options\nInitialized CKB directory in /PATH/ckb_v0.32.1_x86_64-apple-darwin\ncreate specs/dev.toml\ncreate ckb.toml\ncreate ckb-miner.toml\n"))),(0,l.kt)("h3",{id:"3-configure-the-block-assembler"},"3. Configure the Block Assembler"),(0,l.kt)("p",null,"The Block Assembler configuration specifies which address should be receive block rewards for mining."),(0,l.kt)("h4",{id:"3a-create-a-new-account"},"3a. Create a New Account"),(0,l.kt)("p",null,"An address to receive the block rewards must be created. We can do this using ",(0,l.kt)("inlineCode",{parentName:"p"},"ckb-cli"),"."),(0,l.kt)("p",null,"Note: Be sure to record the ",(0,l.kt)("inlineCode",{parentName:"p"},"lock_arg")," value in the response which we will use in the next step."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"ckb-cli account new\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"Your new account is locked with a password. Please give a password. Do not forget this password.\nPassword: \nRepeat password: \naddress:\n mainnet: ckb1qyqyrm8w0w8uq7puwhdp7s6xqzdjuknhf2tqzdztph\n testnet: ckt1qyqyrm8w0w8uq7puwhdp7s6xqzdjuknhf2tqlgu5dt\nlock_arg: 0x41ecee7b8fc0783c75da1f4346009b2e5a774a96\nlock_hash: 0xeb31c5232b322905b9d52350c0d0cf55987f676d86704146ce67d92ddef05ed3\n"))),(0,l.kt)("h4",{id:"3b-update-the-configuration"},"3b. Update the Configuration"),(0,l.kt)("p",null,"Modify the ",(0,l.kt)("inlineCode",{parentName:"p"},"args")," and ",(0,l.kt)("inlineCode",{parentName:"p"},"message")," parameters in the ",(0,l.kt)("inlineCode",{parentName:"p"},"ckb.toml")," file under the ",(0,l.kt)("inlineCode",{parentName:"p"},"block_assembler")," section:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'[block_assembler]\ncode_hash = "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8" # Do not change this.\nargs = "0x8d627decece439977a3a0a97815b63debaff2874" # Change this to your lock_arg value. \nhash_type = "type" # Do not change this.\nmessage = "A 0x-prefixed hex string" # Change this to "0x" to supply an empty message.\n\n')),(0,l.kt)("h3",{id:"4-adjust-the-parameters-to-shorten-the-block-interval-optional"},"4. Adjust the Parameters to Shorten the Block Interval (Optional)"),(0,l.kt)("p",null,"For most development the default configuration should be sufficient, but sometimes it is beneficial to speed up certain operations so results can be viewed quickly."),(0,l.kt)("h4",{id:"4a-change-the-number-of-blocks-in-an-epoch"},"4a. Change the Number of Blocks in an Epoch"),(0,l.kt)("p",null,"The default epoch length is ",(0,l.kt)("inlineCode",{parentName:"p"},"1000")," blocks. Reducing this to ",(0,l.kt)("inlineCode",{parentName:"p"},"10")," or ",(0,l.kt)("inlineCode",{parentName:"p"},"100")," can help with testing Nervos DAO operations."),(0,l.kt)("p",null,"Modify the ",(0,l.kt)("inlineCode",{parentName:"p"},"genesis_epoch_length")," parameter in the ",(0,l.kt)("inlineCode",{parentName:"p"},"specs/dev.toml")," file under the ",(0,l.kt)("inlineCode",{parentName:"p"},"params")," section:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'[params]\ngenesis_epoch_length = 1000 # The unit of meansurement is "block".\n')),(0,l.kt)("h4",{id:"4b-use-permanent-difficulty"},"4b. Use Permanent Difficulty"),(0,l.kt)("p",null,"When ",(0,l.kt)("inlineCode",{parentName:"p"},"permanent_difficulty_in_dummy")," is set to ",(0,l.kt)("inlineCode",{parentName:"p"},"true"),", all epochs will use the same length as the genesis epoch length, skipping the difficulty adjustment entirely. This param is typically used in conjunction with ",(0,l.kt)("inlineCode",{parentName:"p"},"genesis_epoch_length"),"."),(0,l.kt)("p",null,"Modify the ",(0,l.kt)("inlineCode",{parentName:"p"},"permanent_difficulty_in_dummy")," parameter in the ",(0,l.kt)("inlineCode",{parentName:"p"},"specs/dev.toml")," file under the ",(0,l.kt)("inlineCode",{parentName:"p"},"params")," section:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"[params]\ngenesis_epoch_length = 10\npermanent_difficulty_in_dummy = true\n")),(0,l.kt)("h4",{id:"4c-change-the-mining-interval"},"4c. Change the Mining Interval"),(0,l.kt)("p",null,"The default mining interval is ",(0,l.kt)("inlineCode",{parentName:"p"},"5000"),", which is a value in milliseconds, meaning 5 seconds. Reducing this value will create blocks faster."),(0,l.kt)("p",null,"Modify the ",(0,l.kt)("inlineCode",{parentName:"p"},"value")," parameter in the ",(0,l.kt)("inlineCode",{parentName:"p"},"ckb-miner.toml")," file under the ",(0,l.kt)("inlineCode",{parentName:"p"},"miner.workers")," section:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'[[miner.workers]]\nworker_type = "Dummy"\ndelay_type = "Constant"\nvalue = 5000 # The unit of measurement is "ms".\n')),(0,l.kt)("h3",{id:"5-start-the-ckb-node"},"5. Start the CKB Node"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"ckb run\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},'2020-06-05 18:31:14.970 +08:00 main INFO sentry sentry is disabled\n2020-06-05 18:31:15.058 +08:00 main INFO ckb-db Initialize a new database\n2020-06-05 18:31:15.136 +08:00 main INFO ckb-db Init database version 20191127135521\n2020-06-05 18:31:15.162 +08:00 main INFO ckb-memory-tracker track current process: unsupported\n2020-06-05 18:31:15.164 +08:00 main INFO main ckb version: 0.32.1 (9ebc9ce 2020-05-29)\n2020-06-05 18:31:15.164 +08:00 main INFO main chain genesis hash: 0x823b2ff5785b12da8b1363cac9a5cbe566d8b715a4311441b119c39a0367488c\n2020-06-05 18:31:15.166 +08:00 main INFO ckb-network Generate random key\n2020-06-05 18:31:15.166 +08:00 main INFO ckb-network write random secret key to "/PATH/ckb_v0.32.1_x86_64-apple-darwin/data/network/secret_key"\n2020-06-05 18:31:15.177 +08:00 NetworkRuntime INFO ckb-network p2p service event: ListenStarted { address: "/ip4/0.0.0.0/tcp/8115" }\n2020-06-05 18:31:15.179 +08:00 NetworkRuntime INFO ckb-network Listen on address: /ip4/0.0.0.0/tcp/8115/p2p/QmSHk4EucevEuX76Q44hEdYpRxr3gyDmbKtnMQ4kxGaJ6m\n2020-06-05 18:31:15.185 +08:00 main INFO ckb-db Initialize a new database\n2020-06-05 18:31:15.211 +08:00 main INFO ckb-db Init database version 20191201091330\n2020-06-05 18:31:26.586 +08:00 ChainService INFO ckb-chain block: 1, hash: 0x47995f78e95202d2c85ce11bce2ee16d131a57d871f7d93cd4c90ad2a8220bd1, epoch: 0(1/1000), total_diff: 0x200, txs: 1\n'))),(0,l.kt)("h3",{id:"6-start-the-ckb-miner"},"6. Start the CKB Miner"),(0,l.kt)("p",null,"This should be performed in a separate terminal."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"ckb miner\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"2020-06-05 18:31:21.558 +08:00 main INFO sentry sentry is disabled\nDummy-Worker \u2801 [00:00:00] \nFound! #1 0x47995f78e95202d2c85ce11bce2ee16d131a57d871f7d93cd4c90ad2a8220bd1\nFound! #2 0x19978085abfa6204471d42bfb279eac0c20e3b81745b48c4dcaea85643e301f9\nFound! #3 0x625b230f84cb92bcd9cb0bf76d1397c1d948ab25c19df3c4edc246a765f94427\nFound! #4 0x4550fb3b62d9d5ba4d3926db6704b25b90438cfb67037d253ceceb2d86ffdbf7\n\n"))),(0,l.kt)("h2",{id:"setup-an-eaglesong-worker-blockchain"},"Setup an Eaglesong-Worker Blockchain"),(0,l.kt)("h3",{id:"1-download-the-latest-ckb-binary-1"},"1. Download the Latest CKB Binary"),(0,l.kt)("p",null,"Download the latest ckb binary file from the CKB releases page on ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/ckb/releases"},"GitHub"),"."),(0,l.kt)("p",null,"The following commands can be used to verify the binaries are working and to check versions:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"ckb --version\nckb-cli --version\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"ckb 0.32.1 (9ebc9ce 2020-05-29)\nckb-cli 0.32.0 (0fc435d 2020-05-22)\n"))),(0,l.kt)("h4",{id:"2-create-a-new-account"},"2. Create a New Account"),(0,l.kt)("p",null,"An address to receive the block rewards must be created. We can do this using ",(0,l.kt)("inlineCode",{parentName:"p"},"ckb-cli"),"."),(0,l.kt)("p",null,"Note: Be sure to record the ",(0,l.kt)("inlineCode",{parentName:"p"},"lock_arg")," value in the response which we will use in the next step."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"ckb-cli account new\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"Your new account is locked with a password. Please give a password. Do not forget this password.\nPassword: \nRepeat password: \naddress:\n mainnet: ckb1qyqyrm8w0w8uq7puwhdp7s6xqzdjuknhf2tqzdztph\n testnet: ckt1qyqyrm8w0w8uq7puwhdp7s6xqzdjuknhf2tqlgu5dt\nlock_arg: 0x41ecee7b8fc0783c75da1f4346009b2e5a774a96\nlock_hash: 0xeb31c5232b322905b9d52350c0d0cf55987f676d86704146ce67d92ddef05ed3\n"))),(0,l.kt)("h3",{id:"3-initialize-the-configuration-with-the-miner-account"},"3. Initialize the Configuration with the Miner Account"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"ckb init -c dev --ba-arg 0x41ecee7b8fc0783c75da1f4346009b2e5a774a96 // Change this to your lock_arg value. \n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"Initialized CKB directory in /PATH/ckb_v0.32.1_x86_64-apple-darwin\ncreate specs/dev.toml\ncreate ckb.toml\ncreate ckb-miner.toml\n"))),(0,l.kt)("h3",{id:"4-change-the-pow-function-to-eaglesong"},"4. Change the PoW Function to Eaglesong"),(0,l.kt)("p",null,"Modify the ",(0,l.kt)("inlineCode",{parentName:"p"},"func")," parameter in the ",(0,l.kt)("inlineCode",{parentName:"p"},"specs/dev.toml")," file under the ",(0,l.kt)("inlineCode",{parentName:"p"},"pow")," section:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'func = "Eaglesong"\n')),(0,l.kt)("p",null,"Replace the ",(0,l.kt)("inlineCode",{parentName:"p"},"miner.workers")," section in the ",(0,l.kt)("inlineCode",{parentName:"p"},"ckb-miner.toml")," file with the following:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'[[miner.workers]]\nworker_type = "EaglesongSimple"\nthreads = 1\n')),(0,l.kt)("h3",{id:"5-start-the-ckb-node-1"},"5. Start the CKB Node"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"ckb run\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},'2020-06-05 11:25:31.433 +08:00 main INFO sentry sentry is disabled\n2020-06-05 11:25:31.508 +08:00 main INFO ckb-db Initialize a new database\n2020-06-05 11:25:31.590 +08:00 main INFO ckb-db Init database version 20191127135521\n2020-06-05 11:25:31.604 +08:00 main INFO ckb-memory-tracker track current process: unsupported\n2020-06-05 11:25:31.604 +08:00 main INFO main ckb version: 0.32.1 (9ebc9ce 2020-05-29)\n2020-06-05 11:25:31.604 +08:00 main INFO main chain genesis hash: 0x823b2ff5785b12da8b1363cac9a5cbe566d8b715a4311441b119c39a0367488c\n2020-06-05 11:25:31.604 +08:00 main INFO ckb-network Generate random key\n2020-06-05 11:25:31.604 +08:00 main INFO ckb-network write random secret key to "/PATH/ckb_v0.32.1_x86_64-apple-darwin/data/network/secret_key"\n2020-06-05 11:25:31.608 +08:00 NetworkRuntime INFO ckb-network p2p service event: ListenStarted { address: "/ip4/0.0.0.0/tcp/8115" }\n2020-06-05 11:25:31.610 +08:00 NetworkRuntime INFO ckb-network Listen on address: /ip4/0.0.0.0/tcp/8115/p2p/QmcCGH7VeXbpV4jj7VgSEM7NANuud6TmGHV2DXPsSVrRkR\n2020-06-05 11:25:31.612 +08:00 main INFO ckb-db Initialize a new database\n2020-06-05 11:25:31.638 +08:00 main INFO ckb-db Init database version 20191201091330\n'))),(0,l.kt)("h3",{id:"6-start-the-ckb-miner-1"},"6. Start the CKB Miner"),(0,l.kt)("p",null,"This should be performed in a separate terminal."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"ckb miner\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"2020-06-05 11:25:37.867 +08:00 main INFO sentry sentry is disabled\nEaglesongSimple-Worker-0 \u2801 [00:00:00] \n2020-06-05 11:25:37.870 +08:00 main INFO ckb-memory-tracker track current proceFound! #1 0x57e6ad0f15bacc4f30e53811d488d895e6619c17222981eca5484f0115f84acd\nFound! #2 0xe5831f39f928dca599a02e490c482a881ccdc47a2376371dec4e440e363fa5c0\nFound! #3 0x605b3e6449954c2daa996c06b2412bbf60b8231763149742119fb623f9de27b2\nFound! #4 0x64064e7257ea4589e8cb177cf119c68ab1b4559de005a20dc13ef3d42949e04b\n"))),(0,l.kt)("h2",{id:"transferring-ckbytes-using-ckb-cli"},"Transferring CKBytes Using ",(0,l.kt)("inlineCode",{parentName:"h2"},"ckb-cli")),(0,l.kt)("p",null,"Included in CKB releases is the ",(0,l.kt)("inlineCode",{parentName:"p"},"ckb-cli")," command line tool. This is can be used to directly invoke RPC calls to perform actions such as managing accounts, transferring CKBytes, and checking account balances. We will demonstrate a CKBytes transfer below. Please refer to ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/ckb-cli"},"ckb-cli")," for full instructions."),(0,l.kt)("p",null,"Note: Using ",(0,l.kt)("inlineCode",{parentName:"p"},"ckb-cli")," to transfer CKBytes is recommended for developing and testing purposes only. For management of real funds and assets please use a wallet."),(0,l.kt)("h3",{id:"1-enter-the-ckb-cli-interface"},"1. Enter the ",(0,l.kt)("inlineCode",{parentName:"h3"},"ckb-cli")," Interface"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"ckb-cli\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"[ ckb-cli version ]: 0.31.0 (a531b3b 2020-04-17)\n[ url ]: http://127.0.0.1:8114 (network: Dev)\n[ pwd ]: /Users/zengbing/Documents/projects/ckb_v0.32.0-rc1_x86_64-apple-darwin-dev\n[ color ]: true\n[ debug ]: false\n[ output format ]: yaml\n[ completion style ]: List\n[ edit style ]: Emacs\n[ index db state ]: Waiting for first query\n"))),(0,l.kt)("h3",{id:"2-create-a-new-account-1"},"2. Create a New Account"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"account new\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"Your new account is locked with a password. Please give a password. Do not forget this password.\nPassword:\nRepeat password:\naddress:\nmainnet: ckb1qyq0g9p6nxf5cdy38fm35zech5f90jl5aueqw4c8mg\ntestnet: ckt1qyq0g9p6nxf5cdy38fm35zech5f90jl5aueqnsxch5\nlock_arg: 0xf4143a99934c34913a771a0b38bd1257cbf4ef32\nlock_hash: 0xea4db70029dd393789a6be0e4137a3e95cd8d20b2b028a0fc0eab07622a894f4\n"))),(0,l.kt)("ol",{start:3},(0,l.kt)("li",{parentName:"ol"},"Check the Balance of an Existing Account")),(0,l.kt)("p",null,"In the previous sections you created a miner account that collects all mining rewards. Using the following command with the correct address will show you the current CKByte balance:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'wallet get-capacity --address "miner\'s address" \n')),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},'CKB> wallet get-capacity --address "ckt1qyqg6cnaankwgwvh0gaq49uptd3aawhl9p6qpg5cus"\nimmature: 8027902.89083717 (CKB)\ntotal: 46253677.72927512 (CKB)\n'))),(0,l.kt)("h3",{id:"4-transfer-10000-ckbytes-to-the-new-account"},"4. Transfer 10,000 CKBytes to the New Account"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'wallet transfer --from-account "miner\'s address" --to-address "new account\'s address" --capacity 10000 --tx-fee 0.00001\n')),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"CKB> wallet transfer --from-account ckt1qyqg6cnaankwgwvh0gaq49uptd3aawhl9p6qpg5cus --to-address ckt1qyq0g9p6nxf5cdy38fm35zech5f90jl5aueqnsxch5 --capacity 10000 --max-tx-fee 0.00001\nPassword: \n0x1b66aafaaba5ce34de494f60374ef78e8f536bb3af9cab4fa63c0f29374c3f89\n"))),(0,l.kt)("h3",{id:"5-check-the-new-accounts-balance"},"5. Check the New Account's Balance"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'wallet get-capacity --address "new account\'s address"\n')),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"CKB> wallet get-capacity --address ckt1qyq0g9p6nxf5cdy38fm35zech5f90jl5aueqnsxch5\ntotal: 10000.0 (CKB)\n"))),(0,l.kt)("p",null,"The transfer is successful!"),(0,l.kt)("h2",{id:"adding-the-genesis-issued-cells"},"Adding the Genesis Issued Cells"),(0,l.kt)("p",null,"When the development blockchain configuration is generated with ",(0,l.kt)("inlineCode",{parentName:"p"},"ckb init --chain dev"),", a few Cells are created with large amounts of capacity. These are specified in ",(0,l.kt)("inlineCode",{parentName:"p"},"specs/dev.toml")," and exist only for your local development blockchain, and they can be useful for testing purposes."),(0,l.kt)("table",null,(0,l.kt)("tr",null,(0,l.kt)("td",{colspan:"2"},"Genesis Issued Cell #1")),(0,l.kt)("tr",null,(0,l.kt)("td",null,"Private Key"),(0,l.kt)("td",null,"0xd00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc")),(0,l.kt)("tr",null,(0,l.kt)("td",null,"Lock Arg"),(0,l.kt)("td",null,"0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7")),(0,l.kt)("tr",null,(0,l.kt)("td",null,"Testnet Address"),(0,l.kt)("td",null,"ckt1qyqvsv5240xeh85wvnau2eky8pwrhh4jr8ts8vyj37")),(0,l.kt)("tr",null,(0,l.kt)("td",null,"Capcity"),(0,l.kt)("td",null,"20,000,000,000 CKBytes"))),(0,l.kt)("table",null,(0,l.kt)("tr",null,(0,l.kt)("td",{colspan:"2"},"Genesis Issued Cell #2")),(0,l.kt)("tr",null,(0,l.kt)("td",null,"Private Key"),(0,l.kt)("td",null,"0x63d86723e08f0f813a36ce6aa123bb2289d90680ae1e99d4de8cdb334553f24d")),(0,l.kt)("tr",null,(0,l.kt)("td",null,"Lock Arg"),(0,l.kt)("td",null,"0x470dcdc5e44064909650113a274b3b36aecb6dc7")),(0,l.kt)("tr",null,(0,l.kt)("td",null,"Testnet Address"),(0,l.kt)("td",null,"ckt1qyqywrwdchjyqeysjegpzw38fvandtktdhrs0zaxl4")),(0,l.kt)("tr",null,(0,l.kt)("td",null,"Capcity"),(0,l.kt)("td",null,"5,198,735,037 CKBytes"))),(0,l.kt)("h3",{id:"1-create-private-key-files"},"1. Create Private Key Files"),(0,l.kt)("p",null,"Private keys must be added to a text file before they can be used."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"echo 0xd00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc > pk1\necho 0x63d86723e08f0f813a36ce6aa123bb2289d90680ae1e99d4de8cdb334553f24d > pk2\n")),(0,l.kt)("h3",{id:"2-import-the-private-keys"},"2. Import the Private Keys"),(0,l.kt)("p",null,"Import the private key files using ",(0,l.kt)("inlineCode",{parentName:"p"},"ckb-cli"),":"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"CKB> account import --privkey-path pk1\nCKB> account import --privkey-path pk2\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"Password:\naddress:\n mainnet: ckb1qyqvsv5240xeh85wvnau2eky8pwrhh4jr8ts6f6daz\n testnet: ckt1qyqvsv5240xeh85wvnau2eky8pwrhh4jr8ts8vyj37\nlock_arg: 0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7\nPassword:\naddress:\n mainnet: ckb1qyqywrwdchjyqeysjegpzw38fvandtktdhrsj8renf\n testnet: ckt1qyqywrwdchjyqeysjegpzw38fvandtktdhrs0zaxl4\nlock_arg: 470dcdc5e44064909650113a274b3b36aecb6dc7\n"))))}k.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/2c43fa15.31f9975a.js b/assets/js/2c43fa15.31f9975a.js deleted file mode 100644 index 8fe1189be..000000000 --- a/assets/js/2c43fa15.31f9975a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[7277],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>k});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var o=a.createContext({}),s=function(e){var t=a.useContext(o),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},d=function(e){var t=s(e.components);return a.createElement(o.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},p=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,l=e.originalType,o=e.parentName,d=c(e,["components","mdxType","originalType","parentName"]),p=s(n),k=r,h=p["".concat(o,".").concat(k)]||p[k]||u[k]||l;return n?a.createElement(h,i(i({ref:t},d),{},{components:n})):a.createElement(h,i({ref:t},d))}));function k(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var l=n.length,i=new Array(l);i[0]=p;var c={};for(var o in t)hasOwnProperty.call(t,o)&&(c[o]=t[o]);c.originalType=e,c.mdxType="string"==typeof e?e:r,i[1]=c;for(var s=2;s{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>o,default:()=>k,frontMatter:()=>c,metadata:()=>s,toc:()=>u});var a=n(7462),r=n(3366),l=(n(7294),n(3905)),i=["components"],c={id:"devchain",title:"Run a CKB Dev Blockchain"},o=void 0,s={unversionedId:"basics/guides/devchain",id:"basics/guides/devchain",title:"Run a CKB Dev Blockchain",description:"Nervos CKB supports a special development mode that is particularly useful for building and testing applications. This mode of operation is highly configurable, and allows the developer to speed up the block interval, adjust epochs lengths, create blocks without having to do Proof-of-Work (PoW) mining.",source:"@site/docs/basics/guides/devchain.md",sourceDirName:"basics/guides",slug:"/basics/guides/devchain",permalink:"/docs/basics/guides/devchain",draft:!1,editUrl:"https://github.com/nervosnetwork/docs-new/tree/develop/website/docs/basics/guides/devchain.md",tags:[],version:"current",frontMatter:{id:"devchain",title:"Run a CKB Dev Blockchain"},sidebar:"Basics",previous:{title:"Crypto Wallet",permalink:"/docs/basics/concepts/cryptowallet"},next:{title:"Run a CKB Node",permalink:"/docs/basics/guides/mainnet"}},d={},u=[{value:"Setup a Dummy-Worker Blockchain",id:"setup-a-dummy-worker-blockchain",level:2},{value:"1. Download the Latest CKB Binary",id:"1-download-the-latest-ckb-binary",level:3},{value:"2. Initialize the Configuration",id:"2-initialize-the-configuration",level:3},{value:"3. Configure the Block Assembler",id:"3-configure-the-block-assembler",level:3},{value:"3a. Create a New Account",id:"3a-create-a-new-account",level:4},{value:"3b. Update the Configuration",id:"3b-update-the-configuration",level:4},{value:"4. Adjust the Parameters to Shorten the Block Interval (Optional)",id:"4-adjust-the-parameters-to-shorten-the-block-interval-optional",level:3},{value:"4a. Change the Number of Blocks in an Epoch",id:"4a-change-the-number-of-blocks-in-an-epoch",level:4},{value:"4b. Use Permanent Difficulty",id:"4b-use-permanent-difficulty",level:4},{value:"4c. Change the Mining Interval",id:"4c-change-the-mining-interval",level:4},{value:"5. Start the CKB Node",id:"5-start-the-ckb-node",level:3},{value:"6. Start the CKB Miner",id:"6-start-the-ckb-miner",level:3},{value:"Setup an Eaglesong-Worker Blockchain",id:"setup-an-eaglesong-worker-blockchain",level:2},{value:"1. Download the Latest CKB Binary",id:"1-download-the-latest-ckb-binary-1",level:3},{value:"2. Create a New Account",id:"2-create-a-new-account",level:4},{value:"3. Initialize the Configuration with the Miner Account",id:"3-initialize-the-configuration-with-the-miner-account",level:3},{value:"4. Change the PoW Function to Eaglesong",id:"4-change-the-pow-function-to-eaglesong",level:3},{value:"5. Start the CKB Node",id:"5-start-the-ckb-node-1",level:3},{value:"6. Start the CKB Miner",id:"6-start-the-ckb-miner-1",level:3},{value:"Transferring CKBytes Using ckb-cli",id:"transferring-ckbytes-using-ckb-cli",level:2},{value:"1. Enter the ckb-cli Interface",id:"1-enter-the-ckb-cli-interface",level:3},{value:"2. Create a New Account",id:"2-create-a-new-account-1",level:3},{value:"4. Transfer 10,000 CKBytes to the New Account",id:"4-transfer-10000-ckbytes-to-the-new-account",level:3},{value:"5. Check the New Account's Balance",id:"5-check-the-new-accounts-balance",level:3},{value:"Adding the Genesis Issued Cells",id:"adding-the-genesis-issued-cells",level:2},{value:"1. Create Private Key Files",id:"1-create-private-key-files",level:3},{value:"2. Import the Private Keys",id:"2-import-the-private-keys",level:3}],p={toc:u};function k(e){var t=e.components,n=(0,r.Z)(e,i);return(0,l.kt)("wrapper",(0,a.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,l.kt)("p",null,"Nervos CKB supports a special development mode that is particularly useful for building and testing applications. This mode of operation is highly configurable, and allows the developer to speed up the block interval, adjust epochs lengths, create blocks without having to do Proof-of-Work (PoW) mining."),(0,l.kt)("p",null,"When running a development blockchain you have the option of selecting between ",(0,l.kt)("inlineCode",{parentName:"p"},"Dummy-Worker")," and ",(0,l.kt)("inlineCode",{parentName:"p"},"Eaglesong-Worker"),". ",(0,l.kt)("inlineCode",{parentName:"p"},"Dummy-Worker")," allows the mining of blocks at a constant block interval without PoW. ",(0,l.kt)("inlineCode",{parentName:"p"},"Eaglesong-Worker")," uses real PoW to produce blocks."),(0,l.kt)("p",null,"Note: It is highly recommended that ",(0,l.kt)("inlineCode",{parentName:"p"},"Dummy-Worker")," be used for most development scenarios. ",(0,l.kt)("inlineCode",{parentName:"p"},"Eaglesong-Worker")," should only be used when validating the PoW function is necessary, because the block time can behave erratically with extremely low hashrates."),(0,l.kt)("h2",{id:"setup-a-dummy-worker-blockchain"},"Setup a Dummy-Worker Blockchain"),(0,l.kt)("h3",{id:"1-download-the-latest-ckb-binary"},"1. Download the Latest CKB Binary"),(0,l.kt)("p",null,"Download the latest ",(0,l.kt)("inlineCode",{parentName:"p"},"ckb")," binary file from the CKB releases page on ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/ckb/releases"},"GitHub"),"."),(0,l.kt)("p",null,"The following commands can be used to verify the binaries are working and to check versions:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"ckb --version\nckb-cli --version\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"ckb 0.32.1 (9ebc9ce 2020-05-29)\nckb-cli 0.32.0 (0fc435d 2020-05-22)\n"))),(0,l.kt)("h3",{id:"2-initialize-the-configuration"},"2. Initialize the Configuration"),(0,l.kt)("p",null,"Use the following command to initialize the development blockchain and generate the required configuration files:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"ckb init --chain dev\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"WARN: mining feature is disabled because of lacking the block assembler config options\nInitialized CKB directory in /PATH/ckb_v0.32.1_x86_64-apple-darwin\ncreate specs/dev.toml\ncreate ckb.toml\ncreate ckb-miner.toml\n"))),(0,l.kt)("h3",{id:"3-configure-the-block-assembler"},"3. Configure the Block Assembler"),(0,l.kt)("p",null,"The Block Assembler configuration specifies which address should be receive block rewards for mining."),(0,l.kt)("h4",{id:"3a-create-a-new-account"},"3a. Create a New Account"),(0,l.kt)("p",null,"An address to receive the block rewards must be created. We can do this using ",(0,l.kt)("inlineCode",{parentName:"p"},"ckb-cli"),"."),(0,l.kt)("p",null,"Note: Be sure to record the ",(0,l.kt)("inlineCode",{parentName:"p"},"lock_arg")," value in the response which we will use in the next step."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"ckb-cli account new\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"Your new account is locked with a password. Please give a password. Do not forget this password.\nPassword: \nRepeat password: \naddress:\n mainnet: ckb1qyqyrm8w0w8uq7puwhdp7s6xqzdjuknhf2tqzdztph\n testnet: ckt1qyqyrm8w0w8uq7puwhdp7s6xqzdjuknhf2tqlgu5dt\nlock_arg: 0x41ecee7b8fc0783c75da1f4346009b2e5a774a96\nlock_hash: 0xeb31c5232b322905b9d52350c0d0cf55987f676d86704146ce67d92ddef05ed3\n"))),(0,l.kt)("h4",{id:"3b-update-the-configuration"},"3b. Update the Configuration"),(0,l.kt)("p",null,"Modify the ",(0,l.kt)("inlineCode",{parentName:"p"},"args")," and ",(0,l.kt)("inlineCode",{parentName:"p"},"message")," parameters in the ",(0,l.kt)("inlineCode",{parentName:"p"},"ckb.toml")," file under the ",(0,l.kt)("inlineCode",{parentName:"p"},"block_assembler")," section:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'[block_assembler]\ncode_hash = "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8" # Do not change this.\nargs = "0x8d627decece439977a3a0a97815b63debaff2874" # Change this to your lock_arg value. \nhash_type = "type" # Do not change this.\nmessage = "A 0x-prefixed hex string" # Change this to "0x" to supply an empty message.\n\n')),(0,l.kt)("h3",{id:"4-adjust-the-parameters-to-shorten-the-block-interval-optional"},"4. Adjust the Parameters to Shorten the Block Interval (Optional)"),(0,l.kt)("p",null,"For most development the default configuration should be sufficient, but sometimes it is beneficial to speed up certain operations so results can be viewed quickly."),(0,l.kt)("h4",{id:"4a-change-the-number-of-blocks-in-an-epoch"},"4a. Change the Number of Blocks in an Epoch"),(0,l.kt)("p",null,"The default epoch length is ",(0,l.kt)("inlineCode",{parentName:"p"},"1000")," blocks. Reducing this to ",(0,l.kt)("inlineCode",{parentName:"p"},"10")," or ",(0,l.kt)("inlineCode",{parentName:"p"},"100")," can help with testin Nervos DAO operations."),(0,l.kt)("p",null,"Modify the ",(0,l.kt)("inlineCode",{parentName:"p"},"genesis_epoch_length")," parameter in the ",(0,l.kt)("inlineCode",{parentName:"p"},"specs/dev.toml")," file under the ",(0,l.kt)("inlineCode",{parentName:"p"},"params")," section:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'[params]\ngenesis_epoch_length = 1000 # The unit of meansurement is "block".\n')),(0,l.kt)("h4",{id:"4b-use-permanent-difficulty"},"4b. Use Permanent Difficulty"),(0,l.kt)("p",null,"When ",(0,l.kt)("inlineCode",{parentName:"p"},"permanent_difficulty_in_dummy")," is set to ",(0,l.kt)("inlineCode",{parentName:"p"},"true"),", all epochs will use the same length as the genesis epoch length, skipping the difficulty adjustment entirely. This param is typically used in conjunction with ",(0,l.kt)("inlineCode",{parentName:"p"},"genesis_epoch_length"),"."),(0,l.kt)("p",null,"Modify the ",(0,l.kt)("inlineCode",{parentName:"p"},"permanent_difficulty_in_dummy")," parameter in the ",(0,l.kt)("inlineCode",{parentName:"p"},"specs/dev.toml")," file under the ",(0,l.kt)("inlineCode",{parentName:"p"},"params")," section:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"[params]\ngenesis_epoch_length = 10\npermanent_difficulty_in_dummy = true\n")),(0,l.kt)("h4",{id:"4c-change-the-mining-interval"},"4c. Change the Mining Interval"),(0,l.kt)("p",null,"The default mining interval is ",(0,l.kt)("inlineCode",{parentName:"p"},"5000"),", which is a value in milliseconds, meaning 5 seconds. Reducing this value will create blocks faster."),(0,l.kt)("p",null,"Modify the ",(0,l.kt)("inlineCode",{parentName:"p"},"value")," parameter in the ",(0,l.kt)("inlineCode",{parentName:"p"},"ckb-miner.toml")," file under the ",(0,l.kt)("inlineCode",{parentName:"p"},"miner.workers")," section:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'[[miner.workers]]\nworker_type = "Dummy"\ndelay_type = "Constant"\nvalue = 5000 # The unit of measurement is "ms".\n')),(0,l.kt)("h3",{id:"5-start-the-ckb-node"},"5. Start the CKB Node"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"ckb run\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},'2020-06-05 18:31:14.970 +08:00 main INFO sentry sentry is disabled\n2020-06-05 18:31:15.058 +08:00 main INFO ckb-db Initialize a new database\n2020-06-05 18:31:15.136 +08:00 main INFO ckb-db Init database version 20191127135521\n2020-06-05 18:31:15.162 +08:00 main INFO ckb-memory-tracker track current process: unsupported\n2020-06-05 18:31:15.164 +08:00 main INFO main ckb version: 0.32.1 (9ebc9ce 2020-05-29)\n2020-06-05 18:31:15.164 +08:00 main INFO main chain genesis hash: 0x823b2ff5785b12da8b1363cac9a5cbe566d8b715a4311441b119c39a0367488c\n2020-06-05 18:31:15.166 +08:00 main INFO ckb-network Generate random key\n2020-06-05 18:31:15.166 +08:00 main INFO ckb-network write random secret key to "/PATH/ckb_v0.32.1_x86_64-apple-darwin/data/network/secret_key"\n2020-06-05 18:31:15.177 +08:00 NetworkRuntime INFO ckb-network p2p service event: ListenStarted { address: "/ip4/0.0.0.0/tcp/8115" }\n2020-06-05 18:31:15.179 +08:00 NetworkRuntime INFO ckb-network Listen on address: /ip4/0.0.0.0/tcp/8115/p2p/QmSHk4EucevEuX76Q44hEdYpRxr3gyDmbKtnMQ4kxGaJ6m\n2020-06-05 18:31:15.185 +08:00 main INFO ckb-db Initialize a new database\n2020-06-05 18:31:15.211 +08:00 main INFO ckb-db Init database version 20191201091330\n2020-06-05 18:31:26.586 +08:00 ChainService INFO ckb-chain block: 1, hash: 0x47995f78e95202d2c85ce11bce2ee16d131a57d871f7d93cd4c90ad2a8220bd1, epoch: 0(1/1000), total_diff: 0x200, txs: 1\n'))),(0,l.kt)("h3",{id:"6-start-the-ckb-miner"},"6. Start the CKB Miner"),(0,l.kt)("p",null,"This should be performed in a separate terminal."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"ckb miner\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"2020-06-05 18:31:21.558 +08:00 main INFO sentry sentry is disabled\nDummy-Worker \u2801 [00:00:00] \nFound! #1 0x47995f78e95202d2c85ce11bce2ee16d131a57d871f7d93cd4c90ad2a8220bd1\nFound! #2 0x19978085abfa6204471d42bfb279eac0c20e3b81745b48c4dcaea85643e301f9\nFound! #3 0x625b230f84cb92bcd9cb0bf76d1397c1d948ab25c19df3c4edc246a765f94427\nFound! #4 0x4550fb3b62d9d5ba4d3926db6704b25b90438cfb67037d253ceceb2d86ffdbf7\n\n"))),(0,l.kt)("h2",{id:"setup-an-eaglesong-worker-blockchain"},"Setup an Eaglesong-Worker Blockchain"),(0,l.kt)("h3",{id:"1-download-the-latest-ckb-binary-1"},"1. Download the Latest CKB Binary"),(0,l.kt)("p",null,"Download the latest ckb binary file from the CKB releases page on ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/ckb/releases"},"GitHub"),"."),(0,l.kt)("p",null,"The following commands can be used to verify the binaries are working and to check versions:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"ckb --version\nckb-cli --version\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"ckb 0.32.1 (9ebc9ce 2020-05-29)\nckb-cli 0.32.0 (0fc435d 2020-05-22)\n"))),(0,l.kt)("h4",{id:"2-create-a-new-account"},"2. Create a New Account"),(0,l.kt)("p",null,"An address to receive the block rewards must be created. We can do this using ",(0,l.kt)("inlineCode",{parentName:"p"},"ckb-cli"),"."),(0,l.kt)("p",null,"Note: Be sure to record the ",(0,l.kt)("inlineCode",{parentName:"p"},"lock_arg")," value in the response which we will use in the next step."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"ckb-cli account new\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"Your new account is locked with a password. Please give a password. Do not forget this password.\nPassword: \nRepeat password: \naddress:\n mainnet: ckb1qyqyrm8w0w8uq7puwhdp7s6xqzdjuknhf2tqzdztph\n testnet: ckt1qyqyrm8w0w8uq7puwhdp7s6xqzdjuknhf2tqlgu5dt\nlock_arg: 0x41ecee7b8fc0783c75da1f4346009b2e5a774a96\nlock_hash: 0xeb31c5232b322905b9d52350c0d0cf55987f676d86704146ce67d92ddef05ed3\n"))),(0,l.kt)("h3",{id:"3-initialize-the-configuration-with-the-miner-account"},"3. Initialize the Configuration with the Miner Account"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"ckb init -c dev --ba-arg 0x41ecee7b8fc0783c75da1f4346009b2e5a774a96 // Change this to your lock_arg value. \n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"Initialized CKB directory in /PATH/ckb_v0.32.1_x86_64-apple-darwin\ncreate specs/dev.toml\ncreate ckb.toml\ncreate ckb-miner.toml\n"))),(0,l.kt)("h3",{id:"4-change-the-pow-function-to-eaglesong"},"4. Change the PoW Function to Eaglesong"),(0,l.kt)("p",null,"Modify the ",(0,l.kt)("inlineCode",{parentName:"p"},"func")," parameter in the ",(0,l.kt)("inlineCode",{parentName:"p"},"specs/dev.toml")," file under the ",(0,l.kt)("inlineCode",{parentName:"p"},"pow")," section:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'func = "Eaglesong"\n')),(0,l.kt)("p",null,"Replace the ",(0,l.kt)("inlineCode",{parentName:"p"},"miner.workers")," section in the ",(0,l.kt)("inlineCode",{parentName:"p"},"ckb-miner.toml")," file with the following:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'[[miner.workers]]\nworker_type = "EaglesongSimple"\nthreads = 1\n')),(0,l.kt)("h3",{id:"5-start-the-ckb-node-1"},"5. Start the CKB Node"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"ckb run\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},'2020-06-05 11:25:31.433 +08:00 main INFO sentry sentry is disabled\n2020-06-05 11:25:31.508 +08:00 main INFO ckb-db Initialize a new database\n2020-06-05 11:25:31.590 +08:00 main INFO ckb-db Init database version 20191127135521\n2020-06-05 11:25:31.604 +08:00 main INFO ckb-memory-tracker track current process: unsupported\n2020-06-05 11:25:31.604 +08:00 main INFO main ckb version: 0.32.1 (9ebc9ce 2020-05-29)\n2020-06-05 11:25:31.604 +08:00 main INFO main chain genesis hash: 0x823b2ff5785b12da8b1363cac9a5cbe566d8b715a4311441b119c39a0367488c\n2020-06-05 11:25:31.604 +08:00 main INFO ckb-network Generate random key\n2020-06-05 11:25:31.604 +08:00 main INFO ckb-network write random secret key to "/PATH/ckb_v0.32.1_x86_64-apple-darwin/data/network/secret_key"\n2020-06-05 11:25:31.608 +08:00 NetworkRuntime INFO ckb-network p2p service event: ListenStarted { address: "/ip4/0.0.0.0/tcp/8115" }\n2020-06-05 11:25:31.610 +08:00 NetworkRuntime INFO ckb-network Listen on address: /ip4/0.0.0.0/tcp/8115/p2p/QmcCGH7VeXbpV4jj7VgSEM7NANuud6TmGHV2DXPsSVrRkR\n2020-06-05 11:25:31.612 +08:00 main INFO ckb-db Initialize a new database\n2020-06-05 11:25:31.638 +08:00 main INFO ckb-db Init database version 20191201091330\n'))),(0,l.kt)("h3",{id:"6-start-the-ckb-miner-1"},"6. Start the CKB Miner"),(0,l.kt)("p",null,"This should be performed in a separate terminal."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"ckb miner\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"2020-06-05 11:25:37.867 +08:00 main INFO sentry sentry is disabled\nEaglesongSimple-Worker-0 \u2801 [00:00:00] \n2020-06-05 11:25:37.870 +08:00 main INFO ckb-memory-tracker track current proceFound! #1 0x57e6ad0f15bacc4f30e53811d488d895e6619c17222981eca5484f0115f84acd\nFound! #2 0xe5831f39f928dca599a02e490c482a881ccdc47a2376371dec4e440e363fa5c0\nFound! #3 0x605b3e6449954c2daa996c06b2412bbf60b8231763149742119fb623f9de27b2\nFound! #4 0x64064e7257ea4589e8cb177cf119c68ab1b4559de005a20dc13ef3d42949e04b\n"))),(0,l.kt)("h2",{id:"transferring-ckbytes-using-ckb-cli"},"Transferring CKBytes Using ",(0,l.kt)("inlineCode",{parentName:"h2"},"ckb-cli")),(0,l.kt)("p",null,"Included in CKB releases is the ",(0,l.kt)("inlineCode",{parentName:"p"},"ckb-cli")," command line tool. This is can be used to directly invoke RPC calls to perform actions such as managing accounts, transferring CKBytes, and checking account balances. We will demonstrate a CKBytes transfer below. Please refer to ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/ckb-cli"},"ckb-cli")," for full instructions."),(0,l.kt)("p",null,"Note: Using ",(0,l.kt)("inlineCode",{parentName:"p"},"ckb-cli")," to transfer CKBytes is recommended for developing and testing purposes only. For management of real funds and assets please use a wallet."),(0,l.kt)("h3",{id:"1-enter-the-ckb-cli-interface"},"1. Enter the ",(0,l.kt)("inlineCode",{parentName:"h3"},"ckb-cli")," Interface"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"ckb-cli\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"[ ckb-cli version ]: 0.31.0 (a531b3b 2020-04-17)\n[ url ]: http://127.0.0.1:8114 (network: Dev)\n[ pwd ]: /Users/zengbing/Documents/projects/ckb_v0.32.0-rc1_x86_64-apple-darwin-dev\n[ color ]: true\n[ debug ]: false\n[ output format ]: yaml\n[ completion style ]: List\n[ edit style ]: Emacs\n[ index db state ]: Waiting for first query\n"))),(0,l.kt)("h3",{id:"2-create-a-new-account-1"},"2. Create a New Account"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"account new\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"Your new account is locked with a password. Please give a password. Do not forget this password.\nPassword:\nRepeat password:\naddress:\nmainnet: ckb1qyq0g9p6nxf5cdy38fm35zech5f90jl5aueqw4c8mg\ntestnet: ckt1qyq0g9p6nxf5cdy38fm35zech5f90jl5aueqnsxch5\nlock_arg: 0xf4143a99934c34913a771a0b38bd1257cbf4ef32\nlock_hash: 0xea4db70029dd393789a6be0e4137a3e95cd8d20b2b028a0fc0eab07622a894f4\n"))),(0,l.kt)("ol",{start:3},(0,l.kt)("li",{parentName:"ol"},"Check the Balance of an Existing Account")),(0,l.kt)("p",null,"In the previous sections you created a miner account that collects all mining rewards. Using the following command with the correct address will show you the current CKByte balance:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'wallet get-capacity --address "miner\'s address" \n')),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},'CKB> wallet get-capacity --address "ckt1qyqg6cnaankwgwvh0gaq49uptd3aawhl9p6qpg5cus"\nimmature: 8027902.89083717 (CKB)\ntotal: 46253677.72927512 (CKB)\n'))),(0,l.kt)("h3",{id:"4-transfer-10000-ckbytes-to-the-new-account"},"4. Transfer 10,000 CKBytes to the New Account"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'wallet transfer --from-account "miner\'s address" --to-address "new account\'s address" --capacity 10000 --tx-fee 0.00001\n')),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"CKB> wallet transfer --from-account ckt1qyqg6cnaankwgwvh0gaq49uptd3aawhl9p6qpg5cus --to-address ckt1qyq0g9p6nxf5cdy38fm35zech5f90jl5aueqnsxch5 --capacity 10000 --max-tx-fee 0.00001\nPassword: \n0x1b66aafaaba5ce34de494f60374ef78e8f536bb3af9cab4fa63c0f29374c3f89\n"))),(0,l.kt)("h3",{id:"5-check-the-new-accounts-balance"},"5. Check the New Account's Balance"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'wallet get-capacity --address "new account\'s address"\n')),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"CKB> wallet get-capacity --address ckt1qyq0g9p6nxf5cdy38fm35zech5f90jl5aueqnsxch5\ntotal: 10000.0 (CKB)\n"))),(0,l.kt)("p",null,"The transfer is successful!"),(0,l.kt)("h2",{id:"adding-the-genesis-issued-cells"},"Adding the Genesis Issued Cells"),(0,l.kt)("p",null,"When the development blockchain configuration is generated with ",(0,l.kt)("inlineCode",{parentName:"p"},"ckb init --chain dev"),", a few Cells are created with large amounts of capacity. These are specified in ",(0,l.kt)("inlineCode",{parentName:"p"},"specs/dev.toml")," and exist only for your local development blockchain, and they can be useful for testing purposes."),(0,l.kt)("table",null,(0,l.kt)("tr",null,(0,l.kt)("td",{colspan:"2"},"Genesis Issued Cell #1")),(0,l.kt)("tr",null,(0,l.kt)("td",null,"Private Key"),(0,l.kt)("td",null,"0xd00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc")),(0,l.kt)("tr",null,(0,l.kt)("td",null,"Lock Arg"),(0,l.kt)("td",null,"0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7")),(0,l.kt)("tr",null,(0,l.kt)("td",null,"Testnet Address"),(0,l.kt)("td",null,"ckt1qyqvsv5240xeh85wvnau2eky8pwrhh4jr8ts8vyj37")),(0,l.kt)("tr",null,(0,l.kt)("td",null,"Capcity"),(0,l.kt)("td",null,"20,000,000,000 CKBytes"))),(0,l.kt)("table",null,(0,l.kt)("tr",null,(0,l.kt)("td",{colspan:"2"},"Genesis Issued Cell #2")),(0,l.kt)("tr",null,(0,l.kt)("td",null,"Private Key"),(0,l.kt)("td",null,"0x63d86723e08f0f813a36ce6aa123bb2289d90680ae1e99d4de8cdb334553f24d")),(0,l.kt)("tr",null,(0,l.kt)("td",null,"Lock Arg"),(0,l.kt)("td",null,"0x470dcdc5e44064909650113a274b3b36aecb6dc7")),(0,l.kt)("tr",null,(0,l.kt)("td",null,"Testnet Address"),(0,l.kt)("td",null,"ckt1qyqywrwdchjyqeysjegpzw38fvandtktdhrs0zaxl4")),(0,l.kt)("tr",null,(0,l.kt)("td",null,"Capcity"),(0,l.kt)("td",null,"5,198,735,037 CKBytes"))),(0,l.kt)("h3",{id:"1-create-private-key-files"},"1. Create Private Key Files"),(0,l.kt)("p",null,"Private keys must be added to a text file before they can be used."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"echo 0xd00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc > pk1\necho 0x63d86723e08f0f813a36ce6aa123bb2289d90680ae1e99d4de8cdb334553f24d > pk2\n")),(0,l.kt)("h3",{id:"2-import-the-private-keys"},"2. Import the Private Keys"),(0,l.kt)("p",null,"Import the private key files using ",(0,l.kt)("inlineCode",{parentName:"p"},"ckb-cli"),":"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"CKB> account import --privkey-path pk1\nCKB> account import --privkey-path pk2\n")),(0,l.kt)("details",null,(0,l.kt)("summary",null,"(click here to view result)"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"Password:\naddress:\n mainnet: ckb1qyqvsv5240xeh85wvnau2eky8pwrhh4jr8ts6f6daz\n testnet: ckt1qyqvsv5240xeh85wvnau2eky8pwrhh4jr8ts8vyj37\nlock_arg: 0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7\nPassword:\naddress:\n mainnet: ckb1qyqywrwdchjyqeysjegpzw38fvandtktdhrsj8renf\n testnet: ckt1qyqywrwdchjyqeysjegpzw38fvandtktdhrs0zaxl4\nlock_arg: 470dcdc5e44064909650113a274b3b36aecb6dc7\n"))))}k.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/4b2e3693.91b3b02e.js b/assets/js/4b2e3693.e95acd7d.js similarity index 75% rename from assets/js/4b2e3693.91b3b02e.js rename to assets/js/4b2e3693.e95acd7d.js index e7b412817..4435d1947 100644 --- a/assets/js/4b2e3693.91b3b02e.js +++ b/assets/js/4b2e3693.e95acd7d.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[2059],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>u});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var l=a.createContext({}),c=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=c(e.components);return a.createElement(l.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},h=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),h=c(n),u=r,m=h["".concat(l,".").concat(u)]||h[u]||d[u]||o;return n?a.createElement(m,i(i({ref:t},p),{},{components:n})):a.createElement(m,i({ref:t},p))}));function u(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,i=new Array(o);i[0]=h;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s.mdxType="string"==typeof e?e:r,i[1]=s;for(var c=2;c{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>l,default:()=>u,frontMatter:()=>s,metadata:()=>c,toc:()=>d});var a=n(7462),r=n(3366),o=(n(7294),n(3905)),i=["components"],s={id:"qa",title:"Q&A | For Wallets/Exchanges/Mining Pools"},l=void 0,c={unversionedId:"integrate/qa",id:"integrate/qa",title:"Q&A | For Wallets/Exchanges/Mining Pools",description:"External wallets, exchanges and mining pools typically face unique and different challenges when they integrate CKB into their system. This page will provide Q&A for wallets, exchanges and mining pools to integrate CKB. We are woking on detailed guides and helpful tips now, please be patient for a while.",source:"@site/docs/integrate/qa.md",sourceDirName:"integrate",slug:"/integrate/qa",permalink:"/docs/integrate/qa",draft:!1,editUrl:"https://github.com/nervosnetwork/docs-new/tree/develop/website/docs/integrate/qa.md",tags:[],version:"current",frontMatter:{id:"qa",title:"Q&A | For Wallets/Exchanges/Mining Pools"},sidebar:"Integrate",previous:{title:"Nervos CKB Mainnet - Integration Guide",permalink:"/docs/integrate/introduction"},next:{title:"Nervos CKB SDK",permalink:"/docs/integrate/sdk"}},p={},d=[],h={toc:d};function u(e){var t=e.components,n=(0,r.Z)(e,i);return(0,o.kt)("wrapper",(0,a.Z)({},h,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"External wallets, exchanges and mining pools typically face unique and different challenges when they integrate CKB into their system. This page will provide Q&A for wallets, exchanges and mining pools to integrate CKB. We are woking on detailed guides and helpful tips now, please be patient for a while."),(0,o.kt)("p",null,"The following three questions are related to transaction processing, you may refer to ",(0,o.kt)("a",{parentName:"p",href:"https://nervosnetwork.github.io/docs-new/docs/reference/transaction"},"Transaction")," for more details."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Q:"),"How do we use the two fields ",(0,o.kt)("inlineCode",{parentName:"p"},"code_hash")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"hash_type")," in the lock script of output cells ?"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"A:")," When the output cells are unlocked, CKB-VM should load the corresponding contracts by using ",(0,o.kt)("inlineCode",{parentName:"p"},"code_hash")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"hash_type"),".It is recommended to refer to ",(0,o.kt)("a",{parentName:"p",href:"https://nervosnetwork.github.io/docs-new/docs/reference/script#data-structure"},"Script")," for more details."),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"code_hash"),": A hash denoting which script in the transaction to execute. For space consideration, the actual script code is kept in the cell data part of a ",(0,o.kt)("a",{parentName:"li",href:"https://nervosnetwork.github.io/docs-new/docs/reference/cell#live-cell"},"live cell")," on CKB. The current transaction should reference the live cell using a ",(0,o.kt)("a",{parentName:"li",href:"https://nervosnetwork.github.io/docs-new/docs/reference/transaction"},"cell dep")," so as to locate and execute the script."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"hash_type"),": The interpretation of ",(0,o.kt)("inlineCode",{parentName:"li"},"code_hash")," when looking for script code to run from cell deps.",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},"If ",(0,o.kt)("inlineCode",{parentName:"li"},"hash_type")," contains ",(0,o.kt)("inlineCode",{parentName:"li"},"data"),", ",(0,o.kt)("inlineCode",{parentName:"li"},"code_hash")," should match the blake2b hash of data(which is also the actual script code) in a dep cell;"),(0,o.kt)("li",{parentName:"ul"},"If ",(0,o.kt)("inlineCode",{parentName:"li"},"hash_type")," contains ",(0,o.kt)("inlineCode",{parentName:"li"},"type"),", ",(0,o.kt)("inlineCode",{parentName:"li"},"code_hash")," should instead match the blake2b hash of type script contained by a a dep cell. Note CKB will throw a validation error when a) we are locating a script code using ",(0,o.kt)("inlineCode",{parentName:"li"},"type")," as ",(0,o.kt)("inlineCode",{parentName:"li"},"hash_type"),"; and b) more than one cell referenced by cell deps contains the specified hash of type script.")))),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Q:"),"Can we hardcode the ",(0,o.kt)("inlineCode",{parentName:"p"},"code_hash")," , ",(0,o.kt)("inlineCode",{parentName:"p"},"hash_type")," and the corresponding ",(0,o.kt)("inlineCode",{parentName:"p"},"cell_dep")," of two scripts? Are they the same on Testnet as on Mainnet\uff1f"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"A:")," ",(0,o.kt)("inlineCode",{parentName:"p"},"code_hash")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"hash_type")," can be hardcoded and they are the same on Testnet as on Mainnet. ",(0,o.kt)("inlineCode",{parentName:"p"},"cell_dep")," is not the same on the Testnet as on Manniet. But they are all get from the fixed position of the genesis block. The single signature is from the second transaction of the genesis block and the multisignature is from the second output cell, once the genesis block is confirmed, the value is fixed"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Q:")," How do we use ",(0,o.kt)("inlineCode",{parentName:"p"},"Type")," in the outputs?"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"A:")," ",(0,o.kt)("inlineCode",{parentName:"p"},"Type")," can be used in many ways, such as UDT(User Defined Token). We already have an RFC: ",(0,o.kt)("a",{parentName:"p",href:"https://talk.nervos.org/t/rfc-simple-udt-draft-spec/4333"},"Simple UDT Draft Spec")," you may refer it for more details, but currently there isn\u2019t a standard equivalent of ERC20 in Ethereum community, will have to wait until the community has developed a best practice. For wallets or exchanges, you may handle the transactions with ",(0,o.kt)("inlineCode",{parentName:"p"},"Type = null")," If the standard is generated, you also need filter transactions by whitelist and leave transactions with ",(0,o.kt)("inlineCode",{parentName:"p"},"Type = null")," in the future."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Q:")," What is the relationship between the short address, long address and lock script?"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"A:")," The long address and lock Script correspond one to one. All long addresses can be converted into a lock script and vice versa. All short addresses can be converted into long addresses, but the reverse is not necessarily true. CKB have provided single signature transfer and multisignature transfer scripts by default. Also you may refer to RFC:",(0,o.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0021-ckb-address-format/0021-ckb-address-format.md"},"CKB Address Format")," for more details."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Q:")," Are there some test cases for address resolution and generation in other programming languages?"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"A:")," Yes, you may refer to the test cases of ckb-sdk-java\uff1a\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/ckb-sdk-java/blob/develop/ckb/src/test/java/utils/AddressParserTest.java"},"https://github.com/nervosnetwork/ckb-sdk-java/blob/develop/ckb/src/test/java/utils/AddressParserTest.java"),"\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/ckb-sdk-java/blob/develop/ckb/src/test/java/utils/AddressGeneratorTest.java"},"https://github.com/nervosnetwork/ckb-sdk-java/blob/develop/ckb/src/test/java/utils/AddressGeneratorTest.java")),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Q:")," Why is it that the minimum transfer amount cannot be less than 61 CKB?"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"A:")," A cell is used to represent a balance on-chain, and one must hold 1 CKB for every 1 byte of space that the cell occupies. The data in every cell is broken down into four fields: capacity, lock script, type script, and data. Capacity and lock script are required, and type script and data are optional. For more detailed information about the structure of a cell, refer to the ",(0,o.kt)("a",{parentName:"p",href:"https://nervosnetwork.github.io/docs-new/docs/reference/cell"},"cell")," reference page."),(0,o.kt)("p",null,"The most common basic cell is one that represent a CKB balance. Often this will use the default lock script, which is used for short CKB addresses supported by most wallets. A basic cell like this does not require a type script or any additional data. The fields of this cell are as follows:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"capacity")," field is used to hold the number of CKB balance in the cell. This is a u64, which takes 8 bytes."),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"lock script")," field is ",(0,o.kt)("inlineCode",{parentName:"li"},"Script")," type. This inclues a ",(0,o.kt)("inlineCode",{parentName:"li"},"code_hash")," that is 32 bytes, a ",(0,o.kt)("inlineCode",{parentName:"li"},"hash_type")," that is 1 byte, and an ",(0,o.kt)("inlineCode",{parentName:"li"},"args")," field that is 20 bytes."),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"type script")," field is optional and is not used for this cell."),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"data")," field is optional and is not used for this cell.")),(0,o.kt)("p",null,"When you add these up, you get 61 bytes: 8 + 32 + 1 + 20 + 0 + 0 = 61."),(0,o.kt)("p",null,"This is why the minimum transfer is 61 CKB, because 61 bytes are required to represent this information on-chain."),(0,o.kt)("p",null,"While 61 CKB is the minimum, in many cases it is recommended that 62 CKB be sent as the minimum. This is because 61 CKB is the absolute minimum that is required for the cell to exist, and if there are no extra available, then transaction fees cannot be paid from this cell, if needed."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Q:")," If I have 100 CKB in my address and transfer 61 CKB, the balance remaining (39 CKB) isn\u2019t enough to create a change cell. How should I handle this?"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"A:")," There are several ways that this can be handled."),(0,o.kt)("p",null,"The most simple method is to inform users that they have an insufficient balance, and prompt them to add more CKB as needed. This requires only basic processing logic to be implemented."),(0,o.kt)("p",null,"A second option is to tranfer the entire balance of 100 CKB (minus tx fees) so that there is nothing left. If the balance is exactly 0 CKB, then the cell can be consumed and removed from the state completely. This works well if the user wants to withdraw their total balance."),(0,o.kt)("p",null,'A third option is to use a more specialized lock script that supports the "Anyone Can Pay" (ACP) protocol. When both the sender and receiver are setup to use ACP, a balance of any size can be transferred between two parties without the sender having to include any CKB for the cell itself. For more information on ACP, please see the ',(0,o.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0026-anyone-can-pay/0026-anyone-can-pay.md"},"Anyone Can Pay RFC"),"."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Q:")," Can ",(0,o.kt)("inlineCode",{parentName:"p"},"output_data")," be used as exchange entry certificate?"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"A:")," CKB Programming model is a generalized version of the UTXO model.It is recommended to generate different account addresses for each user instead of sharing one address and distinguish them by memo."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Q:")," Are there APIs similar to Bitcoin Wallet\u2019s APIs to manage CKB?"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"A:")," If you already have UTXO management framework for Bitcoin, you may continue to use it and scan every block of CKB blockchain.If you don\u2019t, you may refer to ",(0,o.kt)("a",{parentName:"p",href:"https://nervosnetwork.github.io/docs-new/docs/reference/cell#tools"},"Cell")," and use the tools to index or query."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Q:")," Which APIs need to be invoked if I want to get transaction lists, transaction balance, initiate transactions and etc."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"A:")," You may refer to our ",(0,o.kt)("a",{parentName:"p",href:"https://nervosnetwork.github.io/docs-new/docs/reference/rpc"},"JSON RPC")," document."))}u.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[2059],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>u});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var l=a.createContext({}),c=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=c(e.components);return a.createElement(l.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},h=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),h=c(n),u=r,m=h["".concat(l,".").concat(u)]||h[u]||d[u]||o;return n?a.createElement(m,i(i({ref:t},p),{},{components:n})):a.createElement(m,i({ref:t},p))}));function u(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,i=new Array(o);i[0]=h;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s.mdxType="string"==typeof e?e:r,i[1]=s;for(var c=2;c{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>l,default:()=>u,frontMatter:()=>s,metadata:()=>c,toc:()=>d});var a=n(7462),r=n(3366),o=(n(7294),n(3905)),i=["components"],s={id:"qa",title:"Q&A | For Wallets/Exchanges/Mining Pools"},l=void 0,c={unversionedId:"integrate/qa",id:"integrate/qa",title:"Q&A | For Wallets/Exchanges/Mining Pools",description:"External wallets, exchanges and mining pools typically face unique and different challenges when they integrate CKB into their system. This page will provide Q&A for wallets, exchanges and mining pools to integrate CKB. We are woking on detailed guides and helpful tips now, please be patient for a while.",source:"@site/docs/integrate/qa.md",sourceDirName:"integrate",slug:"/integrate/qa",permalink:"/docs/integrate/qa",draft:!1,editUrl:"https://github.com/nervosnetwork/docs-new/tree/develop/website/docs/integrate/qa.md",tags:[],version:"current",frontMatter:{id:"qa",title:"Q&A | For Wallets/Exchanges/Mining Pools"},sidebar:"Integrate",previous:{title:"Nervos CKB Mainnet - Integration Guide",permalink:"/docs/integrate/introduction"},next:{title:"Nervos CKB SDK",permalink:"/docs/integrate/sdk"}},p={},d=[],h={toc:d};function u(e){var t=e.components,n=(0,r.Z)(e,i);return(0,o.kt)("wrapper",(0,a.Z)({},h,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"External wallets, exchanges and mining pools typically face unique and different challenges when they integrate CKB into their system. This page will provide Q&A for wallets, exchanges and mining pools to integrate CKB. We are woking on detailed guides and helpful tips now, please be patient for a while."),(0,o.kt)("p",null,"The following three questions are related to transaction processing, you may refer to ",(0,o.kt)("a",{parentName:"p",href:"https://nervosnetwork.github.io/docs-new/docs/reference/transaction"},"Transaction")," for more details."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Q:"),"How do we use the two fields ",(0,o.kt)("inlineCode",{parentName:"p"},"code_hash")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"hash_type")," in the lock script of output cells ?"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"A:")," When the output cells are unlocked, CKB-VM should load the corresponding contracts by using ",(0,o.kt)("inlineCode",{parentName:"p"},"code_hash")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"hash_type"),".It is recommended to refer to ",(0,o.kt)("a",{parentName:"p",href:"https://nervosnetwork.github.io/docs-new/docs/reference/script#data-structure"},"Script")," for more details."),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"code_hash"),": A hash denoting which script in the transaction to execute. For space consideration, the actual script code is kept in the cell data part of a ",(0,o.kt)("a",{parentName:"li",href:"https://nervosnetwork.github.io/docs-new/docs/reference/cell#live-cell"},"live cell")," on CKB. The current transaction should reference the live cell using a ",(0,o.kt)("a",{parentName:"li",href:"https://nervosnetwork.github.io/docs-new/docs/reference/transaction"},"cell dep")," so as to locate and execute the script."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"hash_type"),": The interpretation of ",(0,o.kt)("inlineCode",{parentName:"li"},"code_hash")," when looking for script code to run from cell deps.",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},"If ",(0,o.kt)("inlineCode",{parentName:"li"},"hash_type")," contains ",(0,o.kt)("inlineCode",{parentName:"li"},"data"),", ",(0,o.kt)("inlineCode",{parentName:"li"},"code_hash")," should match the blake2b hash of data(which is also the actual script code) in a dep cell;"),(0,o.kt)("li",{parentName:"ul"},"If ",(0,o.kt)("inlineCode",{parentName:"li"},"hash_type")," contains ",(0,o.kt)("inlineCode",{parentName:"li"},"type"),", ",(0,o.kt)("inlineCode",{parentName:"li"},"code_hash")," should instead match the blake2b hash of type script contained by a a dep cell. Note CKB will throw a validation error when a) we are locating a script code using ",(0,o.kt)("inlineCode",{parentName:"li"},"type")," as ",(0,o.kt)("inlineCode",{parentName:"li"},"hash_type"),"; and b) more than one cell referenced by cell deps contains the specified hash of type script.")))),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Q:"),"Can we hardcode the ",(0,o.kt)("inlineCode",{parentName:"p"},"code_hash")," , ",(0,o.kt)("inlineCode",{parentName:"p"},"hash_type")," and the corresponding ",(0,o.kt)("inlineCode",{parentName:"p"},"cell_dep")," of two scripts? Are they the same on Testnet as on Mainnet\uff1f"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"A:")," ",(0,o.kt)("inlineCode",{parentName:"p"},"code_hash")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"hash_type")," can be hardcoded and they are the same on Testnet as on Mainnet. ",(0,o.kt)("inlineCode",{parentName:"p"},"cell_dep")," is not the same on the Testnet as on Manniet. But they are all get from the fixed position of the genesis block. The single signature is from the second transaction of the genesis block and the multisignature is from the second output cell, once the genesis block is confirmed, the value is fixed"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Q:")," How do we use ",(0,o.kt)("inlineCode",{parentName:"p"},"Type")," in the outputs?"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"A:")," ",(0,o.kt)("inlineCode",{parentName:"p"},"Type")," can be used in many ways, such as UDT(User Defined Token). We already have an RFC: ",(0,o.kt)("a",{parentName:"p",href:"https://talk.nervos.org/t/rfc-simple-udt-draft-spec/4333"},"Simple UDT Draft Spec")," you may refer it for more details, but currently there isn\u2019t a standard equivalent of ERC20 in Ethereum community, will have to wait until the community has developed a best practice. For wallets or exchanges, you may handle the transactions with ",(0,o.kt)("inlineCode",{parentName:"p"},"Type = null")," If the standard is generated, you also need filter transactions by whitelist and leave transactions with ",(0,o.kt)("inlineCode",{parentName:"p"},"Type = null")," in the future."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Q:")," What is the relationship between the short address, long address and lock script?"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"A:")," The long address and lock Script correspond one to one. All long addresses can be converted into a lock script and vice versa. All short addresses can be converted into long addresses, but the reverse is not necessarily true. CKB have provided single signature transfer and multisignature transfer scripts by default. Also you may refer to RFC:",(0,o.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0021-ckb-address-format/0021-ckb-address-format.md"},"CKB Address Format")," for more details."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Q:")," Are there some test cases for address resolution and generation in other programming languages?"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"A:")," Yes, you may refer to the test cases of ckb-sdk-java\uff1a\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/ckb-sdk-java/blob/develop/ckb/src/test/java/utils/AddressParserTest.java"},"https://github.com/nervosnetwork/ckb-sdk-java/blob/develop/ckb/src/test/java/utils/AddressParserTest.java"),"\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/ckb-sdk-java/blob/develop/ckb/src/test/java/utils/AddressGeneratorTest.java"},"https://github.com/nervosnetwork/ckb-sdk-java/blob/develop/ckb/src/test/java/utils/AddressGeneratorTest.java")),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Q:")," Why is it that the minimum transfer amount cannot be less than 61 CKB?"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"A:")," A cell is used to represent a balance on-chain, and one must hold 1 CKB for every 1 byte of space that the cell occupies. The data in every cell is broken down into four fields: capacity, lock script, type script, and data. Capacity and lock script are required, and type script and data are optional. For more detailed information about the structure of a cell, refer to the ",(0,o.kt)("a",{parentName:"p",href:"https://nervosnetwork.github.io/docs-new/docs/reference/cell"},"cell")," reference page."),(0,o.kt)("p",null,"The most common basic cell is one that represent a CKB balance. Often this will use the default lock script, which is used for short CKB addresses supported by most wallets. A basic cell like this does not require a type script or any additional data. The fields of this cell are as follows:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"capacity")," field is used to hold the number of CKB balance in the cell. This is a u64, which takes 8 bytes."),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"lock script")," field is ",(0,o.kt)("inlineCode",{parentName:"li"},"Script")," type. This includes a ",(0,o.kt)("inlineCode",{parentName:"li"},"code_hash")," that is 32 bytes, a ",(0,o.kt)("inlineCode",{parentName:"li"},"hash_type")," that is 1 byte, and an ",(0,o.kt)("inlineCode",{parentName:"li"},"args")," field that is 20 bytes."),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"type script")," field is optional and is not used for this cell."),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"data")," field is optional and is not used for this cell.")),(0,o.kt)("p",null,"When you add these up, you get 61 bytes: 8 + 32 + 1 + 20 + 0 + 0 = 61."),(0,o.kt)("p",null,"This is why the minimum transfer is 61 CKB, because 61 bytes are required to represent this information on-chain."),(0,o.kt)("p",null,"While 61 CKB is the minimum, in many cases it is recommended that 62 CKB be sent as the minimum. This is because 61 CKB is the absolute minimum that is required for the cell to exist, and if there are no extra available, then transaction fees cannot be paid from this cell, if needed."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Q:")," If I have 100 CKB in my address and transfer 61 CKB, the balance remaining (39 CKB) isn\u2019t enough to create a change cell. How should I handle this?"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"A:")," There are several ways that this can be handled."),(0,o.kt)("p",null,"The most simple method is to inform users that they have an insufficient balance, and prompt them to add more CKB as needed. This requires only basic processing logic to be implemented."),(0,o.kt)("p",null,"A second option is to transfer the entire balance of 100 CKB (minus tx fees) so that there is nothing left. If the balance is exactly 0 CKB, then the cell can be consumed and removed from the state completely. This works well if the user wants to withdraw their total balance."),(0,o.kt)("p",null,'A third option is to use a more specialized lock script that supports the "Anyone Can Pay" (ACP) protocol. When both the sender and receiver are setup to use ACP, a balance of any size can be transferred between two parties without the sender having to include any CKB for the cell itself. For more information on ACP, please see the ',(0,o.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0026-anyone-can-pay/0026-anyone-can-pay.md"},"Anyone Can Pay RFC"),"."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Q:")," Can ",(0,o.kt)("inlineCode",{parentName:"p"},"output_data")," be used as exchange entry certificate?"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"A:")," CKB Programming model is a generalized version of the UTXO model.It is recommended to generate different account addresses for each user instead of sharing one address and distinguish them by memo."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Q:")," Are there APIs similar to Bitcoin Wallet\u2019s APIs to manage CKB?"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"A:")," If you already have UTXO management framework for Bitcoin, you may continue to use it and scan every block of CKB blockchain.If you don\u2019t, you may refer to ",(0,o.kt)("a",{parentName:"p",href:"https://nervosnetwork.github.io/docs-new/docs/reference/cell#tools"},"Cell")," and use the tools to index or query."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Q:")," Which APIs need to be invoked if I want to get transaction lists, transaction balance, initiate transactions and etc."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"A:")," You may refer to our ",(0,o.kt)("a",{parentName:"p",href:"https://nervosnetwork.github.io/docs-new/docs/reference/rpc"},"JSON RPC")," document."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/5e2b223b.15433e20.js b/assets/js/5e2b223b.a4c94edd.js similarity index 95% rename from assets/js/5e2b223b.15433e20.js rename to assets/js/5e2b223b.a4c94edd.js index 40e717e66..292592848 100644 --- a/assets/js/5e2b223b.15433e20.js +++ b/assets/js/5e2b223b.a4c94edd.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[2205],{3905:(e,t,a)=>{a.d(t,{Zo:()=>p,kt:()=>h});var n=a(7294);function o(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function r(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function c(e){for(var t=1;t=0||(o[a]=e[a]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(o[a]=e[a])}return o}var l=n.createContext({}),s=function(e){var t=n.useContext(l),a=t;return e&&(a="function"==typeof e?e(t):c(c({},t),e)),a},p=function(e){var t=s(e.components);return n.createElement(l.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var a=e.components,o=e.mdxType,r=e.originalType,l=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),d=s(a),h=o,m=d["".concat(l,".").concat(h)]||d[h]||u[h]||r;return a?n.createElement(m,c(c({ref:t},p),{},{components:a})):n.createElement(m,c({ref:t},p))}));function h(e,t){var a=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=a.length,c=new Array(r);c[0]=d;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i.mdxType="string"==typeof e?e:o,c[1]=i;for(var s=2;s{a.r(t),a.d(t,{assets:()=>p,contentTitle:()=>l,default:()=>h,frontMatter:()=>i,metadata:()=>s,toc:()=>u});var n=a(7462),o=a(3366),r=(a(7294),a(3905)),c=["components"],i={id:"polyjuice",title:"Technical Bits on Polyjuice"},l=void 0,s={unversionedId:"essays/polyjuice",id:"essays/polyjuice",title:"Technical Bits on Polyjuice",description:"Polyjuice is an Ethereum compatible layer and has implemented most of the functions of Ethereum on CKB,\xa0including running an EVM contract on CKB-VM.\xa0We believe that we have achieved full-featured compatibility with the implementation of EVM,which is also the power of CKB-VM.By polyjuice we want to showcase that it is perfectly possible to use account model on Nervos CKB. The flexibility here actually enables countless opportunities.",source:"@site/docs/essays/polyjuice.mdx",sourceDirName:"essays",slug:"/essays/polyjuice",permalink:"/docs/essays/polyjuice",draft:!1,editUrl:"https://github.com/nervosnetwork/docs-new/tree/develop/website/docs/essays/polyjuice.mdx",tags:[],version:"current",frontMatter:{id:"polyjuice",title:"Technical Bits on Polyjuice"},sidebar:"Essays",previous:{title:"Script Dependencies",permalink:"/docs/essays/dependencies"},next:{title:"CKB FAQs",permalink:"/docs/essays/faq"}},p={},u=[{value:"Basic Concepts",id:"basic-concepts",level:2},{value:"Account",id:"account",level:3},{value:"Contract",id:"contract",level:3},{value:"Program",id:"program",level:3},{value:"Generator",id:"generator",level:3},{value:"Validator",id:"validator",level:3},{value:"Indexer",id:"indexer",level:3},{value:"Design Details",id:"design-details",level:2},{value:"How to organize cells in a CKB transaction?",id:"how-to-organize-cells-in-a-ckb-transaction",level:3},{value:"The CKB transaction generation process",id:"the-ckb-transaction-generation-process",level:3},{value:"The CKB transaction validation process",id:"the-ckb-transaction-validation-process",level:3},{value:"Communicate through ckb-vm syscalls",id:"communicate-through-ckb-vm-syscalls",level:3},{value:"Implementation Details",id:"implementation-details",level:2},{value:"How to handle contract creation?",id:"how-to-handle-contract-creation",level:3},{value:"How to handle contract destruction?",id:"how-to-handle-contract-destruction",level:3},{value:"How to generate a contract call contract CKB transaction?",id:"how-to-generate-a-contract-call-contract-ckb-transaction",level:3},{value:"How to validate contract call contract CKB transaction?",id:"how-to-validate-contract-call-contract-ckb-transaction",level:3},{value:"How to verify the contract sender (EoA account)?",id:"how-to-verify-the-contract-sender-eoa-account",level:3},{value:"How to handle logs?",id:"how-to-handle-logs",level:3}],d={toc:u};function h(e){var t=e.components,i=(0,o.Z)(e,c);return(0,r.kt)("wrapper",(0,n.Z)({},d,i,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("p",null,(0,r.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/polyjuice"},"Polyjuice")," is an Ethereum compatible layer and has implemented most of the functions of Ethereum on CKB,\xa0including running an EVM contract on CKB-VM.\xa0We believe that we have achieved full-featured compatibility with the implementation of EVM,which is also the power of CKB-VM.By polyjuice we want to showcase that it is perfectly possible to use account model on Nervos CKB. The flexibility here actually enables countless opportunities."),(0,r.kt)("h2",{id:"basic-concepts"},"Basic Concepts"),(0,r.kt)("h3",{id:"account"},"Account"),(0,r.kt)("p",null,"There are two kinds of accounts, contract account, and EoA account."),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Contract Account")),(0,r.kt)("p",null," The contract account in Polyjuice is a cell constrained by Polyjuice type script. The type script args is a ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0022-transaction-structure/0022-transaction-structure.md#type-id"},(0,r.kt)("inlineCode",{parentName:"a"},"type_id"))," value so that the type script is unique. The first 32 bytes of the cell data is the ",(0,r.kt)("inlineCode",{parentName:"p"},"storage root")," (sparse-merkle-tree) of the contract. The second 32 bytes of the cell data is the ",(0,r.kt)("inlineCode",{parentName:"p"},"code_hash")," (",(0,r.kt)("inlineCode",{parentName:"p"},"blake2b(code)"),") of the contract. Since we want everyone to use the contract, we default the use of an always success lock script. We can also use any lock script for access control or other purposes."),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"EoA Account")),(0,r.kt)("p",null,"The EoA account in Polyjuice is all live cells locked by default secp256k1 sighash lock script. The id of the account is the lock script args."),(0,r.kt)("h3",{id:"contract"},"Contract"),(0,r.kt)("p",null,"A contract in Polyjuice is mostly the same as an ethereum contract. You can write your contract in Solidity, Vyper, or Assembly, then compile to EVM byte code. There are some minor differences. Since it's ",(0,r.kt)("strong",{parentName:"p"},"impossible")," to read block information from the current block, we instead read block information from the most recent block. The most recent means the latest block of blocks includes the transaction inputs:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"max(block_number(inputs))\n")),(0,r.kt)("p",null,"It will effect following op codes:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"BLOCKHASH")," "),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"COINBASE")," "),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"TIMESTAMP")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"NUMBER")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"DIFFICULTY")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"GASLIMIT"))),(0,r.kt)("p",null,"The ",(0,r.kt)("inlineCode",{parentName:"p"},"DIFFICULTY")," value is the difficulty of ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0020-ckb-consensus-protocol/0020-ckb-consensus-protocol.md#dynamic-difficulty-adjustment-mechanism"},"Nervos CKB chain"),". The ",(0,r.kt)("inlineCode",{parentName:"p"},"GASLIMIT")," here is a constant value, which equals the max value of ",(0,r.kt)("inlineCode",{parentName:"p"},"int64_t "),"(9223372036854775807). The transaction cost is determined by its size and ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0014-vm-cycle-limits/0014-vm-cycle-limits.md"},"cycles"),", so gas limit is meaningless in Polyjuice."),(0,r.kt)("p",null," The ",(0,r.kt)("inlineCode",{parentName:"p"},"COINBASE")," return value and ",(0,r.kt)("inlineCode",{parentName:"p"},"SELFDESTRUCT")," beneficiary address are the first 20 bytes of lock script hash, which is:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"blake2b(lock_script)[0..20]\n")),(0,r.kt)("h3",{id:"program"},"Program"),(0,r.kt)("p",null,"A program is a ",(0,r.kt)("inlineCode",{parentName:"p"},"CREATE")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"CALL")," with parameters. Since polyjuice supports contract call contract, a polyjuice transaction can contain multiple programs, which will be serialized and put into witness."),(0,r.kt)("h3",{id:"generator"},"Generator"),(0,r.kt)("p",null,"Polyjuice generator can generate a Polyjuice transaction through JSONRPC API as below:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"fn create(sender: H160, code: Bytes) -> TransactionReceipt;\nfn call(sender: H160, contract_address: H160, input: Bytes) -> TransactionReceipt;\n")),(0,r.kt)("h3",{id:"validator"},"Validator"),(0,r.kt)("p",null,"Polyjuice validator is the type script that verifies the transformation of contract cells."),(0,r.kt)("h3",{id:"indexer"},"Indexer"),(0,r.kt)("p",null,"Indexer is a Polyjuice module for indexing every Polyjuice transaction in CKB block. The contract metadata, alteration, and all the logs emitted from the Polyjuice transaction will be saved. Also, all live cells will be indexed for running the generator (build Polyjuice transaction)."),(0,r.kt)("h2",{id:"design-details"},"Design Details"),(0,r.kt)("h3",{id:"how-to-organize-cells-in-a-ckb-transaction"},"How to organize cells in a CKB transaction?"),(0,r.kt)("img",{src:a(2322).Z,width:"600"}),(0,r.kt)("p",null,"If the picture is not clear, please click\uff1a\n",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("a",{parentName:"strong",href:"https://github.com/TheWaWaR/polyjuice/blob/docs/docs/assets/polyjuice-transaction-structure.pdf"},"Organize cells in a CKB transaction"))),(0,r.kt)("h3",{id:"the-ckb-transaction-generation-process"},"The CKB transaction generation process"),(0,r.kt)("img",{src:a(9105).Z,width:"600"}),(0,r.kt)("p",null,"If the picture is not clear, please click\uff1a\n",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("a",{parentName:"strong",href:"https://github.com/TheWaWaR/polyjuice/blob/docs/docs/assets/polyjuice-how-generator-works.pdf"},"CKB transaction generation process"))),(0,r.kt)("h3",{id:"the-ckb-transaction-validation-process"},"The CKB transaction validation process"),(0,r.kt)("img",{src:a(8192).Z,width:"600"}),(0,r.kt)("p",null,"If the picture is not clear, please click\uff1a\n",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("a",{parentName:"strong",href:"https://github.com/TheWaWaR/polyjuice/blob/docs/docs/assets/polyjuice-how-validator-works.pdf"},"CKB transaction validation process"))),(0,r.kt)("h3",{id:"communicate-through-ckb-vm-syscalls"},"Communicate through ckb-vm syscalls"),(0,r.kt)("p",null,"In Generator and Indexer, we use syscalls to handle the event emitted from the program execution process. The syscalls we currently used are shown below:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"2177 is for ckb_debug, useful when you want to debug the generator."),(0,r.kt)("li",{parentName:"ul"},"3075 is for returning the EVM result."),(0,r.kt)("li",{parentName:"ul"},"3076 is for logging."),(0,r.kt)("li",{parentName:"ul"},"3077 is for saving ",(0,r.kt)("inlineCode",{parentName:"li"},"SELFDESTRUCT")," beneficiary address."),(0,r.kt)("li",{parentName:"ul"},"3078 is for handle CALL and CREATE opcodes."),(0,r.kt)("li",{parentName:"ul"},"3079 is for returning code size of a contract to EVM."),(0,r.kt)("li",{parentName:"ul"},"3080 is for returning a coded slice of a contract to EVM.")),(0,r.kt)("h2",{id:"implementation-details"},"Implementation Details"),(0,r.kt)("h3",{id:"how-to-handle-contract-creation"},"How to handle contract creation?"),(0,r.kt)("p",null,"A ",(0,r.kt)("inlineCode",{parentName:"p"},"CREATE")," from a sender (EoA account) or contract will lead to contract creation. In generator, the created cell will be assigned a type_id type script, and the contract code hash will be saved in the data field next to the account storage root hash. In validator, type script will check the contract code hash match the code_hash in the data field."),(0,r.kt)("h3",{id:"how-to-handle-contract-destruction"},"How to handle contract destruction?"),(0,r.kt)("p",null,"Contract destruction only happens when a ",(0,r.kt)("inlineCode",{parentName:"p"},"SELFDESTRUCT")," opcode is executed. In the generator, the destructed contract cell is consumed as input, then put an output cell as the beneficiary cell, and the beneficiary address is the corresponding secp256k1 sighash lock script."),(0,r.kt)("h3",{id:"how-to-generate-a-contract-call-contract-ckb-transaction"},"How to generate a contract call contract CKB transaction?"),(0,r.kt)("p",null,"When CALL or CREATE opcode is invoked in EVM, we call it a contract call contract transaction. When invoking CALL opcode, generator load contract code and latest storage from the database or saved state (the contract has already been loaded from database) by destination and execute it. When CREATE opcode executed after EVM started, the generator will put an output cell just like how contract creation works."),(0,r.kt)("h3",{id:"how-to-validate-contract-call-contract-ckb-transaction"},"How to validate contract call contract CKB transaction?"),(0,r.kt)("p",null,"The first contract created or called by EoA account we call it ",(0,r.kt)("strong",{parentName:"p"},"entrance")," contract, other contracts if there is any, we call them normal contracts. Only one program is allowed in ",(0,r.kt)("strong",{parentName:"p"},"the entrance")," contract, and all its calls to normal contracts' programs must match the order and count. All normal contracts' calls to sub normal contracts' programs must check they match the request. Since multiple contracts may call one contract, the count can not be checked by a normal contract. Normal contracts only check their own programs, and ",(0,r.kt)("strong",{parentName:"p"},"the entrance")," contract will check all programs in current CKB transaction that are being called with the restricted sequence."),(0,r.kt)("h3",{id:"how-to-verify-the-contract-sender-eoa-account"},"How to verify the contract sender (EoA account)?"),(0,r.kt)("p",null,"Since EVM execution will use the sender information, we require the sender to sign the Polyjuice transaction and put the signature into witness. The sign content must include two parts:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"transaction hash "),(0,r.kt)("li",{parentName:"ol"},"all contracts' related witnesses ")),(0,r.kt)("p",null,"The contract-related witness is serialized as part of the ",(0,r.kt)("inlineCode",{parentName:"p"},"WitnessArgs")," molecule structure, and the information is located in input_type (contract call/destruction) field or output_type (contract creation) field."),(0,r.kt)("h3",{id:"how-to-handle-logs"},"How to handle logs?"),(0,r.kt)("p",null,"In validator, the logs are just being ignored. When the generator generates the Polyjuice transaction, the logs are saved and returned as part of the transaction receipt. When the Indexer processes the Polyjuice transaction, the logs are saved to the database for users to query."),(0,r.kt)("p",null," In generator and Indexer the logs are trigged by LOG opcode, then:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"callback function ",(0,r.kt)("inlineCode",{parentName:"li"},"emit_log")," is called"),(0,r.kt)("li",{parentName:"ol"},"emit_log invoke a log syscall with topics and data as arguments"),(0,r.kt)("li",{parentName:"ol"},"Rust syscall handler function is called, the arguments been extracted and saved")))}h.isMDXComponent=!0},9105:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/polyjuice-how-generator-works-1f5bc5615400ce064ec0747af04cbe33.jpg"},8192:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/polyjuice-how-validator-works-665c47b8a838a156c893e9cf0f39b894.jpg"},2322:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/polyjuice-transaction-structure-9234b8a127cfdd9fc26f7e7a9239e25a.jpg"}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[2205],{3905:(e,t,a)=>{a.d(t,{Zo:()=>p,kt:()=>h});var n=a(7294);function o(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function r(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function c(e){for(var t=1;t=0||(o[a]=e[a]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(o[a]=e[a])}return o}var l=n.createContext({}),s=function(e){var t=n.useContext(l),a=t;return e&&(a="function"==typeof e?e(t):c(c({},t),e)),a},p=function(e){var t=s(e.components);return n.createElement(l.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var a=e.components,o=e.mdxType,r=e.originalType,l=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),d=s(a),h=o,m=d["".concat(l,".").concat(h)]||d[h]||u[h]||r;return a?n.createElement(m,c(c({ref:t},p),{},{components:a})):n.createElement(m,c({ref:t},p))}));function h(e,t){var a=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=a.length,c=new Array(r);c[0]=d;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i.mdxType="string"==typeof e?e:o,c[1]=i;for(var s=2;s{a.r(t),a.d(t,{assets:()=>p,contentTitle:()=>l,default:()=>h,frontMatter:()=>i,metadata:()=>s,toc:()=>u});var n=a(7462),o=a(3366),r=(a(7294),a(3905)),c=["components"],i={id:"polyjuice",title:"Technical Bits on Polyjuice"},l=void 0,s={unversionedId:"essays/polyjuice",id:"essays/polyjuice",title:"Technical Bits on Polyjuice",description:"Polyjuice is an Ethereum compatible layer and has implemented most of the functions of Ethereum on CKB,\xa0including running an EVM contract on CKB-VM.\xa0We believe that we have achieved full-featured compatibility with the implementation of EVM,which is also the power of CKB-VM.By polyjuice we want to showcase that it is perfectly possible to use account model on Nervos CKB. The flexibility here actually enables countless opportunities.",source:"@site/docs/essays/polyjuice.mdx",sourceDirName:"essays",slug:"/essays/polyjuice",permalink:"/docs/essays/polyjuice",draft:!1,editUrl:"https://github.com/nervosnetwork/docs-new/tree/develop/website/docs/essays/polyjuice.mdx",tags:[],version:"current",frontMatter:{id:"polyjuice",title:"Technical Bits on Polyjuice"},sidebar:"Essays",previous:{title:"Script Dependencies",permalink:"/docs/essays/dependencies"},next:{title:"CKB FAQs",permalink:"/docs/essays/faq"}},p={},u=[{value:"Basic Concepts",id:"basic-concepts",level:2},{value:"Account",id:"account",level:3},{value:"Contract",id:"contract",level:3},{value:"Program",id:"program",level:3},{value:"Generator",id:"generator",level:3},{value:"Validator",id:"validator",level:3},{value:"Indexer",id:"indexer",level:3},{value:"Design Details",id:"design-details",level:2},{value:"How to organize cells in a CKB transaction?",id:"how-to-organize-cells-in-a-ckb-transaction",level:3},{value:"The CKB transaction generation process",id:"the-ckb-transaction-generation-process",level:3},{value:"The CKB transaction validation process",id:"the-ckb-transaction-validation-process",level:3},{value:"Communicate through ckb-vm syscalls",id:"communicate-through-ckb-vm-syscalls",level:3},{value:"Implementation Details",id:"implementation-details",level:2},{value:"How to handle contract creation?",id:"how-to-handle-contract-creation",level:3},{value:"How to handle contract destruction?",id:"how-to-handle-contract-destruction",level:3},{value:"How to generate a contract call contract CKB transaction?",id:"how-to-generate-a-contract-call-contract-ckb-transaction",level:3},{value:"How to validate contract call contract CKB transaction?",id:"how-to-validate-contract-call-contract-ckb-transaction",level:3},{value:"How to verify the contract sender (EoA account)?",id:"how-to-verify-the-contract-sender-eoa-account",level:3},{value:"How to handle logs?",id:"how-to-handle-logs",level:3}],d={toc:u};function h(e){var t=e.components,i=(0,o.Z)(e,c);return(0,r.kt)("wrapper",(0,n.Z)({},d,i,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("p",null,(0,r.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/polyjuice"},"Polyjuice")," is an Ethereum compatible layer and has implemented most of the functions of Ethereum on CKB,\xa0including running an EVM contract on CKB-VM.\xa0We believe that we have achieved full-featured compatibility with the implementation of EVM,which is also the power of CKB-VM.By polyjuice we want to showcase that it is perfectly possible to use account model on Nervos CKB. The flexibility here actually enables countless opportunities."),(0,r.kt)("h2",{id:"basic-concepts"},"Basic Concepts"),(0,r.kt)("h3",{id:"account"},"Account"),(0,r.kt)("p",null,"There are two kinds of accounts, contract account, and EoA account."),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Contract Account")),(0,r.kt)("p",null," The contract account in Polyjuice is a cell constrained by Polyjuice type script. The type script args is a ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0022-transaction-structure/0022-transaction-structure.md#type-id"},(0,r.kt)("inlineCode",{parentName:"a"},"type_id"))," value so that the type script is unique. The first 32 bytes of the cell data is the ",(0,r.kt)("inlineCode",{parentName:"p"},"storage root")," (sparse-merkle-tree) of the contract. The second 32 bytes of the cell data is the ",(0,r.kt)("inlineCode",{parentName:"p"},"code_hash")," (",(0,r.kt)("inlineCode",{parentName:"p"},"blake2b(code)"),") of the contract. Since we want everyone to use the contract, we default the use of an always success lock script. We can also use any lock script for access control or other purposes."),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"EoA Account")),(0,r.kt)("p",null,"The EoA account in Polyjuice is all live cells locked by default secp256k1 sighash lock script. The id of the account is the lock script args."),(0,r.kt)("h3",{id:"contract"},"Contract"),(0,r.kt)("p",null,"A contract in Polyjuice is mostly the same as an ethereum contract. You can write your contract in Solidity, Vyper, or Assembly, then compile to EVM byte code. There are some minor differences. Since it's ",(0,r.kt)("strong",{parentName:"p"},"impossible")," to read block information from the current block, we instead read block information from the most recent block. The most recent means the latest block of blocks includes the transaction inputs:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"max(block_number(inputs))\n")),(0,r.kt)("p",null,"It will effect following op codes:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"BLOCKHASH")," "),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"COINBASE")," "),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"TIMESTAMP")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"NUMBER")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"DIFFICULTY")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"GASLIMIT"))),(0,r.kt)("p",null,"The ",(0,r.kt)("inlineCode",{parentName:"p"},"DIFFICULTY")," value is the difficulty of ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0020-ckb-consensus-protocol/0020-ckb-consensus-protocol.md#dynamic-difficulty-adjustment-mechanism"},"Nervos CKB chain"),". The ",(0,r.kt)("inlineCode",{parentName:"p"},"GASLIMIT")," here is a constant value, which equals the max value of ",(0,r.kt)("inlineCode",{parentName:"p"},"int64_t "),"(9223372036854775807). The transaction cost is determined by its size and ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0014-vm-cycle-limits/0014-vm-cycle-limits.md"},"cycles"),", so gas limit is meaningless in Polyjuice."),(0,r.kt)("p",null," The ",(0,r.kt)("inlineCode",{parentName:"p"},"COINBASE")," return value and ",(0,r.kt)("inlineCode",{parentName:"p"},"SELFDESTRUCT")," beneficiary address are the first 20 bytes of lock script hash, which is:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"blake2b(lock_script)[0..20]\n")),(0,r.kt)("h3",{id:"program"},"Program"),(0,r.kt)("p",null,"A program is a ",(0,r.kt)("inlineCode",{parentName:"p"},"CREATE")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"CALL")," with parameters. Since polyjuice supports contract call contract, a polyjuice transaction can contain multiple programs, which will be serialized and put into witness."),(0,r.kt)("h3",{id:"generator"},"Generator"),(0,r.kt)("p",null,"Polyjuice generator can generate a Polyjuice transaction through JSONRPC API as below:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"fn create(sender: H160, code: Bytes) -> TransactionReceipt;\nfn call(sender: H160, contract_address: H160, input: Bytes) -> TransactionReceipt;\n")),(0,r.kt)("h3",{id:"validator"},"Validator"),(0,r.kt)("p",null,"Polyjuice validator is the type script that verifies the transformation of contract cells."),(0,r.kt)("h3",{id:"indexer"},"Indexer"),(0,r.kt)("p",null,"Indexer is a Polyjuice module for indexing every Polyjuice transaction in CKB block. The contract metadata, alteration, and all the logs emitted from the Polyjuice transaction will be saved. Also, all live cells will be indexed for running the generator (build Polyjuice transaction)."),(0,r.kt)("h2",{id:"design-details"},"Design Details"),(0,r.kt)("h3",{id:"how-to-organize-cells-in-a-ckb-transaction"},"How to organize cells in a CKB transaction?"),(0,r.kt)("img",{src:a(2322).Z,width:"600"}),(0,r.kt)("p",null,"If the picture is not clear, please click\uff1a\n",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("a",{parentName:"strong",href:"https://github.com/TheWaWaR/polyjuice/blob/docs/docs/assets/polyjuice-transaction-structure.pdf"},"Organize cells in a CKB transaction"))),(0,r.kt)("h3",{id:"the-ckb-transaction-generation-process"},"The CKB transaction generation process"),(0,r.kt)("img",{src:a(9105).Z,width:"600"}),(0,r.kt)("p",null,"If the picture is not clear, please click\uff1a\n",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("a",{parentName:"strong",href:"https://github.com/TheWaWaR/polyjuice/blob/docs/docs/assets/polyjuice-how-generator-works.pdf"},"CKB transaction generation process"))),(0,r.kt)("h3",{id:"the-ckb-transaction-validation-process"},"The CKB transaction validation process"),(0,r.kt)("img",{src:a(8192).Z,width:"600"}),(0,r.kt)("p",null,"If the picture is not clear, please click\uff1a\n",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("a",{parentName:"strong",href:"https://github.com/TheWaWaR/polyjuice/blob/docs/docs/assets/polyjuice-how-validator-works.pdf"},"CKB transaction validation process"))),(0,r.kt)("h3",{id:"communicate-through-ckb-vm-syscalls"},"Communicate through ckb-vm syscalls"),(0,r.kt)("p",null,"In Generator and Indexer, we use syscalls to handle the event emitted from the program execution process. The syscalls we currently used are shown below:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"2177 is for ckb_debug, useful when you want to debug the generator."),(0,r.kt)("li",{parentName:"ul"},"3075 is for returning the EVM result."),(0,r.kt)("li",{parentName:"ul"},"3076 is for logging."),(0,r.kt)("li",{parentName:"ul"},"3077 is for saving ",(0,r.kt)("inlineCode",{parentName:"li"},"SELFDESTRUCT")," beneficiary address."),(0,r.kt)("li",{parentName:"ul"},"3078 is for handle CALL and CREATE opcodes."),(0,r.kt)("li",{parentName:"ul"},"3079 is for returning code size of a contract to EVM."),(0,r.kt)("li",{parentName:"ul"},"3080 is for returning a coded slice of a contract to EVM.")),(0,r.kt)("h2",{id:"implementation-details"},"Implementation Details"),(0,r.kt)("h3",{id:"how-to-handle-contract-creation"},"How to handle contract creation?"),(0,r.kt)("p",null,"A ",(0,r.kt)("inlineCode",{parentName:"p"},"CREATE")," from a sender (EoA account) or contract will lead to contract creation. In generator, the created cell will be assigned a type_id type script, and the contract code hash will be saved in the data field next to the account storage root hash. In validator, type script will check the contract code hash match the code_hash in the data field."),(0,r.kt)("h3",{id:"how-to-handle-contract-destruction"},"How to handle contract destruction?"),(0,r.kt)("p",null,"Contract destruction only happens when a ",(0,r.kt)("inlineCode",{parentName:"p"},"SELFDESTRUCT")," opcode is executed. In the generator, the destructed contract cell is consumed as input, then put an output cell as the beneficiary cell, and the beneficiary address is the corresponding secp256k1 sighash lock script."),(0,r.kt)("h3",{id:"how-to-generate-a-contract-call-contract-ckb-transaction"},"How to generate a contract call contract CKB transaction?"),(0,r.kt)("p",null,"When CALL or CREATE opcode is invoked in EVM, we call it a contract call contract transaction. When invoking CALL opcode, generator load contract code and latest storage from the database or saved state (the contract has already been loaded from database) by destination and execute it. When CREATE opcode executed after EVM started, the generator will put an output cell just like how contract creation works."),(0,r.kt)("h3",{id:"how-to-validate-contract-call-contract-ckb-transaction"},"How to validate contract call contract CKB transaction?"),(0,r.kt)("p",null,"The first contract created or called by EoA account we call it ",(0,r.kt)("strong",{parentName:"p"},"entrance")," contract, other contracts if there is any, we call them normal contracts. Only one program is allowed in ",(0,r.kt)("strong",{parentName:"p"},"the entrance")," contract, and all its calls to normal contracts' programs must match the order and count. All normal contracts' calls to sub normal contracts' programs must check they match the request. Since multiple contracts may call one contract, the count can not be checked by a normal contract. Normal contracts only check their own programs, and ",(0,r.kt)("strong",{parentName:"p"},"the entrance")," contract will check all programs in current CKB transaction that are being called with the restricted sequence."),(0,r.kt)("h3",{id:"how-to-verify-the-contract-sender-eoa-account"},"How to verify the contract sender (EoA account)?"),(0,r.kt)("p",null,"Since EVM execution will use the sender information, we require the sender to sign the Polyjuice transaction and put the signature into witness. The sign content must include two parts:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"transaction hash "),(0,r.kt)("li",{parentName:"ol"},"all contracts' related witnesses ")),(0,r.kt)("p",null,"The contract-related witness is serialized as part of the ",(0,r.kt)("inlineCode",{parentName:"p"},"WitnessArgs")," molecule structure, and the information is located in input_type (contract call/destruction) field or output_type (contract creation) field."),(0,r.kt)("h3",{id:"how-to-handle-logs"},"How to handle logs?"),(0,r.kt)("p",null,"In validator, the logs are just being ignored. When the generator generates the Polyjuice transaction, the logs are saved and returned as part of the transaction receipt. When the Indexer processes the Polyjuice transaction, the logs are saved to the database for users to query."),(0,r.kt)("p",null," In generator and Indexer the logs are triggered by LOG opcode, then:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"callback function ",(0,r.kt)("inlineCode",{parentName:"li"},"emit_log")," is called"),(0,r.kt)("li",{parentName:"ol"},"emit_log invoke a log syscall with topics and data as arguments"),(0,r.kt)("li",{parentName:"ol"},"Rust syscall handler function is called, the arguments been extracted and saved")))}h.isMDXComponent=!0},9105:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/polyjuice-how-generator-works-1f5bc5615400ce064ec0747af04cbe33.jpg"},8192:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/polyjuice-how-validator-works-665c47b8a838a156c893e9cf0f39b894.jpg"},2322:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/polyjuice-transaction-structure-9234b8a127cfdd9fc26f7e7a9239e25a.jpg"}}]); \ No newline at end of file diff --git a/assets/js/6d9f7284.2f0c9ec9.js b/assets/js/6d9f7284.323f24f9.js similarity index 99% rename from assets/js/6d9f7284.2f0c9ec9.js rename to assets/js/6d9f7284.323f24f9.js index bd073acfd..a297323de 100644 --- a/assets/js/6d9f7284.2f0c9ec9.js +++ b/assets/js/6d9f7284.323f24f9.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[4673],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>k});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function l(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var p=r.createContext({}),s=function(e){var t=r.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},c=function(e){var t=s(e.components);return r.createElement(p.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},u=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,p=e.parentName,c=i(e,["components","mdxType","originalType","parentName"]),u=s(n),k=a,d=u["".concat(p,".").concat(k)]||u[k]||m[k]||o;return n?r.createElement(d,l(l({ref:t},c),{},{components:n})):r.createElement(d,l({ref:t},c))}));function k(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,l=new Array(o);l[0]=u;var i={};for(var p in t)hasOwnProperty.call(t,p)&&(i[p]=t[p]);i.originalType=e,i.mdxType="string"==typeof e?e:a,l[1]=i;for(var s=2;s{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>p,default:()=>k,frontMatter:()=>i,metadata:()=>s,toc:()=>m});var r=n(7462),a=n(3366),o=(n(7294),n(3905)),l=["components"],i={id:"ckb-core-dev",title:"Tips for CKB Development"},p=void 0,s={unversionedId:"essays/ckb-core-dev",id:"essays/ckb-core-dev",title:"Tips for CKB Development",description:"Nervos CKB is the layer 1 of Nervos Network, a public/permissionless blockchain, which is an open source project on github. There are some tips for ckb development below, hope it will be useful for you.",source:"@site/docs/essays/ckb-core-dev.md",sourceDirName:"essays",slug:"/essays/ckb-core-dev",permalink:"/docs/essays/ckb-core-dev",draft:!1,editUrl:"https://github.com/nervosnetwork/docs-new/tree/develop/website/docs/essays/ckb-core-dev.md",tags:[],version:"current",frontMatter:{id:"ckb-core-dev",title:"Tips for CKB Development"},sidebar:"Essays",previous:{title:"CKB FAQs",permalink:"/docs/essays/faq"},next:{title:"Integrity Check for CKB Release",permalink:"/docs/essays/integrity-check"}},c={},m=[{value:"Molecule",id:"molecule",level:2},{value:"Well-known Hashes",id:"well-known-hashes",level:2},{value:"Running Test",id:"running-test",level:2},{value:"Debug CKB",id:"debug-ckb",level:2},{value:"Track Memory Usage in Logs",id:"track-memory-usage-in-logs",level:3},{value:"Profile Memory",id:"profile-memory",level:3},{value:"References",id:"references",level:3}],u={toc:m};function k(e){var t=e.components,n=(0,a.Z)(e,l);return(0,o.kt)("wrapper",(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,(0,o.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/ckb"},"Nervos CKB")," is the layer 1 of Nervos Network, a public/permissionless blockchain, which is an open source project on github. There are some tips for ckb development below, hope it will be useful for you."),(0,o.kt)("h2",{id:"molecule"},"Molecule"),(0,o.kt)("p",null,"We have developed a particular serialization format called ",(0,o.kt)("strong",{parentName:"p"},"Molecule"),".It is recommended to check the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/molecule"},"molecule github repo")," for more details."),(0,o.kt)("h2",{id:"well-known-hashes"},"Well-known Hashes"),(0,o.kt)("p",null,"The command ",(0,o.kt)("inlineCode",{parentName:"p"},"ckb list-hashes")," prints the well-known hashes for current\neffective chain spec."),(0,o.kt)("p",null,"The file ",(0,o.kt)("inlineCode",{parentName:"p"},"docs/hashes.toml")," in ckb release package and source code repository\ncontains the well-known hashes for all the bundled chain specs. The file is\ngenerated by:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"cargo run list-hashes -b > docs/hashes.toml\n")),(0,o.kt)("h2",{id:"running-test"},"Running Test"),(0,o.kt)("p",null,"Install dependencies"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"rustup component add rustfmt\nrustup component add clippy\n")),(0,o.kt)("p",null,"Run tests"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"make ci\n")),(0,o.kt)("p",null,"Run acceptance integration tests"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"make integration\n")),(0,o.kt)("hr",null),(0,o.kt)("h2",{id:"debug-ckb"},"Debug CKB"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Note: Only support linux system.")),(0,o.kt)("h3",{id:"track-memory-usage-in-logs"},"Track Memory Usage in Logs"),(0,o.kt)("p",null,"Add the follow configuration into ",(0,o.kt)("inlineCode",{parentName:"p"},"ckb.toml"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-toml"},'[logger]\nfilter = "error,ckb-memory-tracker=trace"\n\n[memory_tracker]\n# Seconds between checking the process, 0 is disable, default is 0.\ninterval = 600\n')),(0,o.kt)("h3",{id:"profile-memory"},"Profile Memory"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Compile ",(0,o.kt)("inlineCode",{parentName:"p"},"ckb")," with feature ",(0,o.kt)("inlineCode",{parentName:"p"},"profiling"),"."),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"make build-for-profiling\n")),(0,o.kt)("p",{parentName:"li"},"After compiling, a script named ",(0,o.kt)("inlineCode",{parentName:"p"},"jeprof")," will be generated in ",(0,o.kt)("inlineCode",{parentName:"p"},"target")," direcotry."),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-sh"},'find target/ -name "jeprof"\n'))),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Enable RPC module ",(0,o.kt)("inlineCode",{parentName:"p"},"Debug")," in ",(0,o.kt)("inlineCode",{parentName:"p"},"ckb.toml"),"."),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-toml"},'[rpc]\nmodules = ["Debug"]\n'))),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Run ",(0,o.kt)("inlineCode",{parentName:"p"},"ckb"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Dump memory usage to a file via call RPC ",(0,o.kt)("inlineCode",{parentName:"p"},"jemalloc_profiling_dump"),"."),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-sh"},'curl -H \'content-type: application/json\' -d \'{ "id": 2, "jsonrpc": "2.0", "method": "jemalloc_profiling_dump", "params": [] }\' http://localhost:8114\n')),(0,o.kt)("p",{parentName:"li"},"Then, a file named ",(0,o.kt)("inlineCode",{parentName:"p"},"ckb-jeprof.$TIMESTAMP.heap")," will be generated in the working directory of the running ",(0,o.kt)("inlineCode",{parentName:"p"},"ckb"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Generate a PDF of the call graph."),(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},"Required"),": graphviz and ghostscript"),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"jeprof --show_bytes --pdf target/debug/ckb ckb-jeprof.$TIMESTAMP.heap > call-graph.pdf\n")))),(0,o.kt)("h3",{id:"references"},"References"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/jemalloc/jemalloc/wiki/Use-Case%3A-Leak-Checking"},"JEMALLOC: Use Case: Leak Checking")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/jemalloc/jemalloc/wiki/Use-Case%3A-Heap-Profiling"},"JEMALLOC: Use Case: Heap Profiling")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/facebook/rocksdb/wiki/Memory-usage-in-RocksDB"},"RocksDB: Memory usage in RocksDB"))))}k.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[4673],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>k});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function l(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var p=r.createContext({}),s=function(e){var t=r.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},c=function(e){var t=s(e.components);return r.createElement(p.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},u=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,p=e.parentName,c=i(e,["components","mdxType","originalType","parentName"]),u=s(n),k=a,d=u["".concat(p,".").concat(k)]||u[k]||m[k]||o;return n?r.createElement(d,l(l({ref:t},c),{},{components:n})):r.createElement(d,l({ref:t},c))}));function k(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,l=new Array(o);l[0]=u;var i={};for(var p in t)hasOwnProperty.call(t,p)&&(i[p]=t[p]);i.originalType=e,i.mdxType="string"==typeof e?e:a,l[1]=i;for(var s=2;s{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>p,default:()=>k,frontMatter:()=>i,metadata:()=>s,toc:()=>m});var r=n(7462),a=n(3366),o=(n(7294),n(3905)),l=["components"],i={id:"ckb-core-dev",title:"Tips for CKB Development"},p=void 0,s={unversionedId:"essays/ckb-core-dev",id:"essays/ckb-core-dev",title:"Tips for CKB Development",description:"Nervos CKB is the layer 1 of Nervos Network, a public/permissionless blockchain, which is an open source project on github. There are some tips for ckb development below, hope it will be useful for you.",source:"@site/docs/essays/ckb-core-dev.md",sourceDirName:"essays",slug:"/essays/ckb-core-dev",permalink:"/docs/essays/ckb-core-dev",draft:!1,editUrl:"https://github.com/nervosnetwork/docs-new/tree/develop/website/docs/essays/ckb-core-dev.md",tags:[],version:"current",frontMatter:{id:"ckb-core-dev",title:"Tips for CKB Development"},sidebar:"Essays",previous:{title:"CKB FAQs",permalink:"/docs/essays/faq"},next:{title:"Integrity Check for CKB Release",permalink:"/docs/essays/integrity-check"}},c={},m=[{value:"Molecule",id:"molecule",level:2},{value:"Well-known Hashes",id:"well-known-hashes",level:2},{value:"Running Test",id:"running-test",level:2},{value:"Debug CKB",id:"debug-ckb",level:2},{value:"Track Memory Usage in Logs",id:"track-memory-usage-in-logs",level:3},{value:"Profile Memory",id:"profile-memory",level:3},{value:"References",id:"references",level:3}],u={toc:m};function k(e){var t=e.components,n=(0,a.Z)(e,l);return(0,o.kt)("wrapper",(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,(0,o.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/ckb"},"Nervos CKB")," is the layer 1 of Nervos Network, a public/permissionless blockchain, which is an open source project on github. There are some tips for ckb development below, hope it will be useful for you."),(0,o.kt)("h2",{id:"molecule"},"Molecule"),(0,o.kt)("p",null,"We have developed a particular serialization format called ",(0,o.kt)("strong",{parentName:"p"},"Molecule"),".It is recommended to check the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/molecule"},"molecule github repo")," for more details."),(0,o.kt)("h2",{id:"well-known-hashes"},"Well-known Hashes"),(0,o.kt)("p",null,"The command ",(0,o.kt)("inlineCode",{parentName:"p"},"ckb list-hashes")," prints the well-known hashes for current\neffective chain spec."),(0,o.kt)("p",null,"The file ",(0,o.kt)("inlineCode",{parentName:"p"},"docs/hashes.toml")," in ckb release package and source code repository\ncontains the well-known hashes for all the bundled chain specs. The file is\ngenerated by:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"cargo run list-hashes -b > docs/hashes.toml\n")),(0,o.kt)("h2",{id:"running-test"},"Running Test"),(0,o.kt)("p",null,"Install dependencies"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"rustup component add rustfmt\nrustup component add clippy\n")),(0,o.kt)("p",null,"Run tests"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"make ci\n")),(0,o.kt)("p",null,"Run acceptance integration tests"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"make integration\n")),(0,o.kt)("hr",null),(0,o.kt)("h2",{id:"debug-ckb"},"Debug CKB"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Note: Only support linux system.")),(0,o.kt)("h3",{id:"track-memory-usage-in-logs"},"Track Memory Usage in Logs"),(0,o.kt)("p",null,"Add the follow configuration into ",(0,o.kt)("inlineCode",{parentName:"p"},"ckb.toml"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-toml"},'[logger]\nfilter = "error,ckb-memory-tracker=trace"\n\n[memory_tracker]\n# Seconds between checking the process, 0 is disable, default is 0.\ninterval = 600\n')),(0,o.kt)("h3",{id:"profile-memory"},"Profile Memory"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Compile ",(0,o.kt)("inlineCode",{parentName:"p"},"ckb")," with feature ",(0,o.kt)("inlineCode",{parentName:"p"},"profiling"),"."),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"make build-for-profiling\n")),(0,o.kt)("p",{parentName:"li"},"After compiling, a script named ",(0,o.kt)("inlineCode",{parentName:"p"},"jeprof")," will be generated in ",(0,o.kt)("inlineCode",{parentName:"p"},"target")," directory."),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-sh"},'find target/ -name "jeprof"\n'))),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Enable RPC module ",(0,o.kt)("inlineCode",{parentName:"p"},"Debug")," in ",(0,o.kt)("inlineCode",{parentName:"p"},"ckb.toml"),"."),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-toml"},'[rpc]\nmodules = ["Debug"]\n'))),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Run ",(0,o.kt)("inlineCode",{parentName:"p"},"ckb"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Dump memory usage to a file via call RPC ",(0,o.kt)("inlineCode",{parentName:"p"},"jemalloc_profiling_dump"),"."),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-sh"},'curl -H \'content-type: application/json\' -d \'{ "id": 2, "jsonrpc": "2.0", "method": "jemalloc_profiling_dump", "params": [] }\' http://localhost:8114\n')),(0,o.kt)("p",{parentName:"li"},"Then, a file named ",(0,o.kt)("inlineCode",{parentName:"p"},"ckb-jeprof.$TIMESTAMP.heap")," will be generated in the working directory of the running ",(0,o.kt)("inlineCode",{parentName:"p"},"ckb"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Generate a PDF of the call graph."),(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},"Required"),": graphviz and ghostscript"),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"jeprof --show_bytes --pdf target/debug/ckb ckb-jeprof.$TIMESTAMP.heap > call-graph.pdf\n")))),(0,o.kt)("h3",{id:"references"},"References"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/jemalloc/jemalloc/wiki/Use-Case%3A-Leak-Checking"},"JEMALLOC: Use Case: Leak Checking")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/jemalloc/jemalloc/wiki/Use-Case%3A-Heap-Profiling"},"JEMALLOC: Use Case: Heap Profiling")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/facebook/rocksdb/wiki/Memory-usage-in-RocksDB"},"RocksDB: Memory usage in RocksDB"))))}k.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/8af0162e.56b325a5.js b/assets/js/8af0162e.56b325a5.js new file mode 100644 index 000000000..c33be0be3 --- /dev/null +++ b/assets/js/8af0162e.56b325a5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[6049],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>m});var a=n(7294);function l(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function o(e){for(var t=1;t=0||(l[n]=e[n]);return l}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(l[n]=e[n])}return l}var s=a.createContext({}),u=function(e){var t=a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},c=function(e){var t=u(e.components);return a.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},d=a.forwardRef((function(e,t){var n=e.components,l=e.mdxType,r=e.originalType,s=e.parentName,c=i(e,["components","mdxType","originalType","parentName"]),d=u(n),m=l,k=d["".concat(s,".").concat(m)]||d[m]||p[m]||r;return n?a.createElement(k,o(o({ref:t},c),{},{components:n})):a.createElement(k,o({ref:t},c))}));function m(e,t){var n=arguments,l=t&&t.mdxType;if("string"==typeof e||l){var r=n.length,o=new Array(r);o[0]=d;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i.mdxType="string"==typeof e?e:l,o[1]=i;for(var u=2;u{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>m,frontMatter:()=>i,metadata:()=>u,toc:()=>p});var a=n(7462),l=n(3366),r=(n(7294),n(3905)),o=["components"],i={id:"sudtbycapsule",title:"Write an SUDT Script by Capsule"},s=void 0,u={unversionedId:"labs/sudtbycapsule",id:"labs/sudtbycapsule",title:"Write an SUDT Script by Capsule",description:"Introduction",source:"@site/docs/labs/sudtbycapsule.md",sourceDirName:"labs",slug:"/labs/sudtbycapsule",permalink:"/docs/labs/sudtbycapsule",draft:!1,editUrl:"https://github.com/nervosnetwork/docs-new/tree/develop/website/docs/labs/sudtbycapsule.md",tags:[],version:"current",frontMatter:{id:"sudtbycapsule",title:"Write an SUDT Script by Capsule"},sidebar:"Labs",previous:{title:"Introduction",permalink:"/docs/labs/introduction"},next:{title:"Introduction to Lumos via NervosDAO",permalink:"/docs/labs/lumos-nervosdao"}},c={},p=[{value:"Introduction",id:"introduction",level:2},{value:"Prepare to write the SUDT script",id:"prepare-to-write-the-sudt-script",level:2},{value:"Run a dev chain and ckb-cli",id:"run-a-dev-chain-and-ckb-cli",level:3},{value:"Install Capsule",id:"install-capsule",level:3},{value:"Prerequisites",id:"prerequisites",level:4},{value:"Create a project",id:"create-a-project",level:3},{value:"Build the project",id:"build-the-project",level:3},{value:"Write a SUDT script",id:"write-a-sudt-script",level:2},{value:"Check the used libraries",id:"check-the-used-libraries",level:3},{value:"Load Script",id:"load-script",level:3},{value:"Check inputs",id:"check-inputs",level:3},{value:"Load inputs / outputs UDT amount",id:"load-inputs--outputs-udt-amount",level:3},{value:"Use Iterator to query cells",id:"use-iterator-to-query-cells",level:3},{value:"Build the project",id:"build-the-project-1",level:3},{value:"Testing",id:"testing",level:2},{value:"Check the default tests",id:"check-the-default-tests",level:3},{value:"Write new tests",id:"write-new-tests",level:3},{value:"Deployment",id:"deployment",level:2},{value:"Run a dev chain and ckb-cli",id:"run-a-dev-chain-and-ckb-cli-1",level:3},{value:"Deploy",id:"deploy",level:3},{value:"Migration",id:"migration",level:3},{value:"Next Steps",id:"next-steps",level:2}],d={toc:p};function m(e){var t=e.components,n=(0,l.Z)(e,o);return(0,r.kt)("wrapper",(0,a.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h2",{id:"introduction"},"Introduction"),(0,r.kt)("p",null,(0,r.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/capsule"},"Capsule")," is a set of tools for Rust developers to develop scripts on CKB which covers the entire lifecycle of script development: writing,debugging,testing and deployment. We aim to improve the development experience of Rust developers."),(0,r.kt)("p",null,"In this tutorial, you will learn how to write a SUDT script using Capsule. SUDT is the abbreviation of Simple User Defined Token which defines a minimal standard that contains what\u2019s absolutely needed for dapp developers to issue custom tokens on Nervos CKB. You can refer to ",(0,r.kt)("a",{parentName:"p",href:"https://talk.nervos.org/t/rfc-simple-udt-draft-spec/4333"},"RFC: Simple UDT Draft Spec")," for more details."),(0,r.kt)("p",null,"We expect that:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"You are Rust developers and generally familiar with software development, writing code, and running your code."),(0,r.kt)("li",{parentName:"ul"},"You are generally familiar with Nervos CKB and have completed the ",(0,r.kt)("a",{parentName:"li",href:"/docs/basics/guides/devchain"},"How to use a development blockchain")),(0,r.kt)("li",{parentName:"ul"},"You are open to learning about the bleeding edge of blockchain development")),(0,r.kt)("p",null,"If you run into an issue on this tutorial you can ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/capsule"},"create a new issue")," or contact us on ",(0,r.kt)("a",{parentName:"p",href:"https://talk.nervos.org/"},"Nervos talk")," or ",(0,r.kt)("a",{parentName:"p",href:"https://discord.gg/n6tx7uC"},"Discord"),". "),(0,r.kt)("p",null,"What you will be doing:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Prepare to write the SUDT script "),(0,r.kt)("li",{parentName:"ul"},"Write a SUDT script"),(0,r.kt)("li",{parentName:"ul"},"Testing"),(0,r.kt)("li",{parentName:"ul"},"Deployment ")),(0,r.kt)("h2",{id:"prepare-to-write-the-sudt-script"},"Prepare to write the SUDT script"),(0,r.kt)("h3",{id:"run-a-dev-chain-and-ckb-cli"},"Run a dev chain and ckb-cli"),(0,r.kt)("p",null,"You should be able to run a dev chain and know about how to use ",(0,r.kt)("inlineCode",{parentName:"p"},"ckb-cli")," to send transactions. If you do not, please refer to this tutorial\uff1a",(0,r.kt)("a",{parentName:"p",href:"/docs/basics/guides/devchain"},"How to use a development blockchain"),". Please don't forget to add ",(0,r.kt)("inlineCode",{parentName:"p"},"ckb-cli")," to the PATH environment variable"),(0,r.kt)("h3",{id:"install-capsule"},"Install Capsule"),(0,r.kt)("h4",{id:"prerequisites"},"Prerequisites"),(0,r.kt)("p",null,"The following must be installed and available to use Capsule."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Cargo and Rust - Capsule uses cargo to generate Rust contracts and run tests. ",(0,r.kt)("a",{parentName:"li",href:"https://www.rust-lang.org/tools/install."},"Install Rust")),(0,r.kt)("li",{parentName:"ul"},"Docker - Capsule uses ",(0,r.kt)("inlineCode",{parentName:"li"},"docker")," container to reproducible build contracts. It's also used by ",(0,r.kt)("inlineCode",{parentName:"li"},"cross"),". ",(0,r.kt)("a",{parentName:"li",href:"https://docs.docker.com/get-docker/"},"https://docs.docker.com/get-docker/")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"cross-rs")," - Capsule uses ",(0,r.kt)("inlineCode",{parentName:"li"},"cross")," to build rust contracts. Install with ")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"# Do this after you installed cargo\ncargo install cross --git https://github.com/cross-rs/cross\n")),(0,r.kt)("p",null,"Note: The current user must have permission to manage Docker instances. For more information, see ",(0,r.kt)("a",{parentName:"p",href:"https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user"},"Manage Docker as a non-root user"),"."),(0,r.kt)("h3",{id:""}),(0,r.kt)("p",null,"Now you can proceed to install Capsule. It is recommended to download the binary ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/capsule/releases"},"here"),"."),(0,r.kt)("p",null,"Or you can install Capsule from it's source:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"cargo install capsule --git https://github.com/nervosnetwork/capsule.git --tag v0.1.3\n")),(0,r.kt)("p",null,"Then check if it works with the following command:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"capsule check\n")),(0,r.kt)("details",null,(0,r.kt)("summary",null,"(click here to view response)"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"------------------------------\ncargo installed\ndocker installed\ncross-util installed\nckb-cli installed v1.4.0 (required v1.2.0)\n------------------------------\n"))),(0,r.kt)("h3",{id:"create-a-project"},"Create a project"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"capsule new my-sudt\n")),(0,r.kt)("details",null,(0,r.kt)("summary",null,"(click here to view response)"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},'New project "my-sudt"\nCreated file "capsule.toml"\nCreated file "deployment.toml"\nCreated file "README.md"\nCreated file "rust-toolchain"\nCreated file "Cross.toml"\nCreated file "Cargo.toml"\nCreated file ".gitignore"\nInitialized empty Git repository in ./my-sudt/.git/\nCreated "./my-sudt"\nCreated tests\nNew contract "my-sudt"\nRewrite Cargo.toml\nRewrite capsule.toml\nDone\n'))),(0,r.kt)("p",null,"You can check the project\u2019s layout\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"ls my-sudt\n")),(0,r.kt)("details",null,(0,r.kt)("summary",null,"(click here to view response)"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"\nbuild capsule.toml Cargo.toml contracts deployment.toml migrations README.md tests\n"))),(0,r.kt)("p",null,"The default contract is under ",(0,r.kt)("inlineCode",{parentName:"p"},"my-sudt/contracts/my-sudt")," directory which is a normal cargo project:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"ls my-sudt/contracts/my-sudt\n")),(0,r.kt)("details",null,(0,r.kt)("summary",null,"(click here to view response)"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"\nCargo.toml src\n"))),(0,r.kt)("p",null,"You can open ",(0,r.kt)("inlineCode",{parentName:"p"},"my-sudt/contracts/my-sudt/src/main.rs")," to see some pre-generated code:"),(0,r.kt)("details",null,(0,r.kt)("summary",null,"(click here to view full code)"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},"//! Generated by capsule\n//!\n//! `main.rs` is used to define rust lang items and modules.\n//! See `entry.rs` for the `main` function. \n//! See `error.rs` for the `Error` type.\n\n#![no_std]\n#![cfg_attr(not(test), no_main)]\n\n// define modules\nmod entry;\nmod error;\n\n#[cfg(test)]\nextern crate alloc;\n\n#[cfg(not(test))]\nuse ckb_std::default_alloc;\n#[cfg(not(test))]\nckb_std::entry!(program_entry);\n#[cfg(not(test))]\ndefault_alloc!();\n\n/// program entry\npub fn program_entry() -> i8 {\n // Call main function and return error code\n match entry::main() {\n Ok(_) => 0,\n Err(err) => err as i8,\n }\n}\n"))),(0,r.kt)("p",null,"and also ",(0,r.kt)("inlineCode",{parentName:"p"},"my-sudt/contracts/my-sudt/src/entry.rs")),(0,r.kt)("details",null,(0,r.kt)("summary",null,"(click here to view full code)"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},'// Import from `core` instead of from `std` since we are in no-std mode\nuse core::result::Result;\n\n// Import heap related library from `alloc`\n// https://doc.rust-lang.org/alloc/index.html\nuse alloc::{vec, vec::Vec};\n\n// Import CKB syscalls and structures\n// https://docs.rs/ckb-std/\nuse ckb_std::{\n debug,\n high_level::{load_script, load_tx_hash},\n ckb_types::{bytes::Bytes, prelude::*},\n};\n\nuse crate::error::Error;\n\npub fn main() -> Result<(), Error> {\n // remove below examples and write your code here\n\n let script = load_script()?;\n let args: Bytes = script.args().unpack();\n debug!("script args is {:?}", args);\n\n // return an error if args is invalid\n if args.is_empty() {\n return Err(Error::MyError);\n }\n\n let tx_hash = load_tx_hash()?;\n debug!("tx hash is {:?}", tx_hash);\n\n let _buf: Vec<_> = vec![0u8; 32];\n\n Ok(())\n}\n\n// Unit tests are supported.\n#[test]\nfn test_foo() {\n assert!(true);\n}\n'))),(0,r.kt)("h3",{id:"build-the-project"},"Build the project"),(0,r.kt)("p",null,"Enter into the project ",(0,r.kt)("inlineCode",{parentName:"p"},"my-sudt")," and build it."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"cd my-sudt\ncapsule build\n")),(0,r.kt)("details",null,(0,r.kt)("summary",null,"(click here to view full console log)"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"Building contract demo\n$ cross build -p demo\ninfo: syncing channel updates for '1.69.0-x86_64-unknown-linux-gnu'\ninfo: latest update on 2023-04-20, rust version 1.69.0 (84c898d65 2023-04-16)\ninfo: downloading component 'cargo'\ninfo: downloading component 'rust-std'\n 27.2 MiB / 27.2 MiB (100 %) 14.7 MiB/s in 1s ETA: 0s\ninfo: downloading component 'rustc'\n 60.0 MiB / 60.0 MiB (100 %) 18.8 MiB/s in 3s ETA: 0s\ninfo: installing component 'cargo'\ninfo: installing component 'rust-std'\n 27.2 MiB / 27.2 MiB (100 %) 20.7 MiB/s in 1s ETA: 0s\ninfo: installing component 'rustc'\n 60.0 MiB / 60.0 MiB (100 %) 23.6 MiB/s in 2s ETA: 0s\n\n 1.69.0-x86_64-unknown-linux-gnu installed - (error reading rustc version)\n\ninfo: checking for self-updates\ninfo: downloading self-update\ninfo: downloading component 'rust-std' for 'riscv64imac-unknown-none-elf'\ninfo: installing component 'rust-std' for 'riscv64imac-unknown-none-elf'\nUnable to find image 'nervos/ckb-riscv-gnu-toolchain:focal-20230214' locally\nfocal-20230214: Pulling from nervos/ckb-riscv-gnu-toolchain\n7608715873ec: Pull complete\na237f683deea: Pull complete\n84750871be6c: Pull complete\n3056067387e4: Pull complete\n258c66296219: Pull complete\ne8ea3d081562: Pull complete\n32afd1383aeb: Pull complete\n6f6c3bd439ca: Pull complete\nDigest: sha256:5732afe996b2b88a37ed3c0e4deb948e9d2a6936fb4b52d4e7a0dc5ad330c306\nStatus: Downloaded newer image for nervos/ckb-riscv-gnu-toolchain:focal-20230214\n Compiling cfg-if v1.0.0\n Compiling cc v1.0.79\n Compiling buddy-alloc v0.5.1\n Compiling molecule v0.7.5\n Compiling ckb-standalone-types v0.1.2\n Compiling ckb-std v0.13.0\n Compiling my-sudt v0.1.0 (./my-sudt/contracts/my-sudt)\n Finished dev [unoptimized + debuginfo] target(s) in 33.53s\nDone\n"))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Note: You might see some warning log like ",(0,r.kt)("inlineCode",{parentName:"li"},": MADV_DONTNEED does not work (memset will be used instead)"),", this isn't an abnormal behaviour, and won't make any trouble to us. It is caused by jemalloc under QEMU env, which is expected if you're running non-native docker containers under ",(0,r.kt)("inlineCode",{parentName:"li"},"aarch64")," architecture(for example an x86-64 container).")),(0,r.kt)("p",null,"You will find a new generated contract binary in the ",(0,r.kt)("inlineCode",{parentName:"p"},"build/debug")," directory:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"ls build/debug\n")),(0,r.kt)("details",null,(0,r.kt)("summary",null,"(click here to view response)"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"my-sudt\n"))),(0,r.kt)("p",null,"You're all done? Great, let's get coding."),(0,r.kt)("h2",{id:"write-a-sudt-script"},"Write a SUDT script"),(0,r.kt)("p",null,"SUDT scripts can be in ",(0,r.kt)("strong",{parentName:"p"},"owner mode")," and ",(0,r.kt)("strong",{parentName:"p"},"normal mode")," which include different verification rules, we should deal with that when we're coding."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"owner mode"),"\uff1aIf one of the transaction input has a lock script matching the SUDT script argument, the SUDT script will be in owner mode. We don\u2019t need to perform checks, the owner can perform any operations such as issuing more SUDTs or burning SUDTs. "),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"normal mode\uff1a"),"Otherwise, the SUDT script will be in normal mode. We need to ensure the sum of all inputs\u2019 capacity is not smaller than the sum of all outputs capacity. Please note that only one type of SUDT can be issued for each unique lock script. ")),(0,r.kt)("p",null,"The script is consisted of four parts\uff1aload script\u3001check inputs\u3001load inputs / outputs UDT amount\u3001error handling. We should check the used libraries before coding."),(0,r.kt)("h3",{id:"check-the-used-libraries"},"Check the used libraries"),(0,r.kt)("p",null,"Open ",(0,r.kt)("inlineCode",{parentName:"p"},"contracts/my-sudt/Cargo.toml"),", we already have a dependency:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'[dependencies]\nckb-std = "0.13"\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ckb-std")," is a crate used to handling CKB syscalls."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ckb-standalone-types")," is a crate which re-exported as the ",(0,r.kt)("inlineCode",{parentName:"li"},"ckb_std::ckb_types")," provides the definition of CKB structures.")),(0,r.kt)("p",null,"You may refer to ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/capsule/wiki/Rust-libraries"},"Rust libraries")," for more useful crates. We can only use crates which supports ",(0,r.kt)("inlineCode",{parentName:"p"},"no-std")," in scripts."),(0,r.kt)("h3",{id:"load-script"},"Load Script"),(0,r.kt)("p",null,"At the beginning of the script, we need to check the SUDT\u2019s mode, if it is owner mode, we simply skip the verification code and return ",(0,r.kt)("inlineCode",{parentName:"p"},"0"),", which represents the verification is successful, otherwise we check the amount of UDT."),(0,r.kt)("p",null,"To achieve this, we need to load ",(0,r.kt)("inlineCode",{parentName:"p"},"args")," of the current script, which the generated code already did for us. So we just remove the unused lines from the ",(0,r.kt)("inlineCode",{parentName:"p"},"main")," function."),(0,r.kt)("p",null,"In the code below, we load the current script(SUDT)'s args field, and invoke ",(0,r.kt)("inlineCode",{parentName:"p"},"check_owner_mode")," which we have not defined yet."),(0,r.kt)("p",null,"Notice since we are using no-std Rust, we can't directly use the ",(0,r.kt)("inlineCode",{parentName:"p"},"std")," in the code. Instead, we need to import the ",(0,r.kt)("inlineCode",{parentName:"p"},"Vec")," struct from the ",(0,r.kt)("a",{parentName:"p",href:"https://doc.rust-lang.org/stable/alloc/index.html"},"alloc")," crate, which is a rust builtin crate contains heap related structs."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},"// contracts/my-sudt/src/entry.rs\nfn main() -> Result<(), Error> {\n // load current script\n // check verification branch is owner mode or normal mode\n let script = load_script()?;\n let args: Bytes = script.args().unpack();\n\n // unpack the Script#args field\n let args: Vec = script.args().unpack();\n\n // return success if owner mode is true\n if check_owner_mode(&args)? {\n return Ok(());\n }\n\n // more verifications ...\n return Ok(());\n}\n")),(0,r.kt)("h3",{id:"check-inputs"},"Check inputs"),(0,r.kt)("p",null,"Now we should check the owner mode status by defining the ",(0,r.kt)("inlineCode",{parentName:"p"},"check_owner_mode")," function\uff1a"),(0,r.kt)("p",null,"We need to load every input's lock hash and compare it to the script's args. If we find an input's lock hash corresponds to the script's args, we are in owner mode; otherwise, we iterate all the inputs and finally got an ",(0,r.kt)("inlineCode",{parentName:"p"},"IndexOutOfBound")," error, which means we are in normal mode."),(0,r.kt)("p",null,"We use ",(0,r.kt)("a",{parentName:"p",href:"https://nervosnetwork.github.io/ckb-std/riscv64imac-unknown-none-elf/doc/ckb_std/high_level/fn.load_cell_lock_hash.html"},"load_cell_lock_hash")," to load cell's lock hash from CKB. The ",(0,r.kt)("inlineCode",{parentName:"p"},"Source::Input")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"i")," args denote we load ",(0,r.kt)("inlineCode",{parentName:"p"},"input")," from ",(0,r.kt)("inlineCode",{parentName:"p"},"i-th")," inputs."),(0,r.kt)("p",null,"The error ",(0,r.kt)("inlineCode",{parentName:"p"},"SysError::IndexOutOfBound")," represents that we request an index that does not exist, which means we cannot find a matched input cell, so we return ",(0,r.kt)("inlineCode",{parentName:"p"},"Ok(false)"),"."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},"use ckb_std::{\n high_level::{load_cell_lock_hash},\n ckb_constants::Source,\n};\n\nfn check_owner_mode(args: &Bytes) -> Result {\n // With owner lock script extracted, we will look through each input in the\n // current transaction to see if any unlocked cell uses owner lock.\n for i in 0.. {\n // check input's lock_hash with script args\n let lock_hash = match load_cell_lock_hash(\n i,\n Source::Input,\n ) {\n Ok(lock_hash) => lock_hash,\n Err(SysError::IndexOutOfBound) => return Ok(false),\n Err(err) => return Err(err.into()),\n };\n // invalid length of loaded data\n if args[..] == lock_hash[..] {\n return Ok(true);\n }\n }\n Ok(false)\n}\n")),(0,r.kt)("h3",{id:"load-inputs--outputs-udt-amount"},"Load inputs / outputs UDT amount"),(0,r.kt)("p",null,"If the owner mode is ",(0,r.kt)("inlineCode",{parentName:"p"},"false"),", we should continue the verification: check the total input SUDT amount is greater than or equals to the total output SUDT amount."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Define two methods:"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"collect_inputs_amount")," \uff1acollect total input SUDT amount"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"collect_outputs_amount")," \uff1acollect total output SUDT amount."))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Since we aim to read all SUDT inputs which type is the current script(SUDT), we can use ",(0,r.kt)("inlineCode",{parentName:"p"},"Source::GroupInput")," instead of ",(0,r.kt)("inlineCode",{parentName:"p"},"Source::Input"),".")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"Source::GroupInput")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"i")," means load the ",(0,r.kt)("inlineCode",{parentName:"p"},"i-th"),' input from the "input group". '))),(0,r.kt)("p",null,"Tips\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"By using ",(0,r.kt)("inlineCode",{parentName:"li"},"Source::GroupInput")," in the syscall, CKB verification engine will automatically group the inputs/outputs by ",(0,r.kt)("inlineCode",{parentName:"li"},"lock")," and ",(0,r.kt)("inlineCode",{parentName:"li"},"type")," script."),(0,r.kt)("li",{parentName:"ul"},"The data type of SUDT is ",(0,r.kt)("inlineCode",{parentName:"li"},"u128"),", which is 16 bytes so we use the 16 bytes buffer."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"i-th")," input of ",(0,r.kt)("inlineCode",{parentName:"li"},"Source::Input"),"(index of all inputs) may be or may not be the same cell of the ",(0,r.kt)("inlineCode",{parentName:"li"},"i-th")," input of ",(0,r.kt)("inlineCode",{parentName:"li"},"Source::GroupInput")," (index of inputs which lock/type is the current script).")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},"const UDT_LEN: usize = 16;\n\nfn collect_inputs_amount() -> Result {\n // let's loop through all input cells containing current UDTs,\n // and gather the sum of all input tokens.\n let mut inputs_amount: u128 = 0;\n let mut buf = [0u8; UDT_LEN];\n\n // u128 is 16 bytes\n for i in 0.. {\n let data = match load_cell_data(i, Source::GroupInput) {\n Ok(data) => data,\n Err(SysError::IndexOutOfBound) => break,\n Err(err) => return Err(err.into()),\n };\n\n if data.len() != UDT_LEN {\n return Err(Error::Encoding);\n }\n buf.copy_from_slice(&data);\n inputs_amount += u128::from_le_bytes(buf);\n }\n Ok(inputs_amount)\n}\n")),(0,r.kt)("p",null,"The ",(0,r.kt)("inlineCode",{parentName:"p"},"collect_outputs_amount")," function is similar, except we load data from outputs:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},"fn collect_outputs_amount() -> Result {\n // With the sum of all input UDT tokens gathered, let's now iterate through\n // output cells to grab the sum of all output UDT tokens.\n let mut outputs_amount: u128 = 0;\n let mut i = 0;\n\n // u128 is 16 bytes\n let mut buf = [0u8; UDT_LEN];\n for i in 0.. {\n let data = match load_cell_data(i, Source::GroupOutput) {\n Ok(data) => data,\n Err(SysError::IndexOutOfBound) => break,\n Err(err) => return Err(err.into()),\n };\n\n if data.len() != UDT_LEN {\n return Err(Error::Encoding);\n }\n buf.copy_from_slice(&data);\n outputs_amount += u128::from_le_bytes(buf);\n }\n Ok(outputs_amount)\n}\n")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Update the ",(0,r.kt)("inlineCode",{parentName:"li"},"error.rs"),' to add an error stands for "Not enough amount"')),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},'use ckb_std::error::SysError;\n\n/// Error\n#[repr(i8)]\npub enum Error {\n IndexOutOfBound = 1,\n ItemMissing,\n LengthNotEnough,\n Encoding,\n // Add customized errors here...\n Amount,\n}\n\nimpl From for Error {\n fn from(err: SysError) -> Self {\n use SysError::*;\n match err {\n IndexOutOfBound => Self::IndexOutOfBound,\n ItemMissing => Self::ItemMissing,\n LengthNotEnough(_) => Self::LengthNotEnough,\n Encoding => Self::Encoding,\n Unknown(err_code) => panic!("unexpected sys error {}", err_code),\n }\n }\n}\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Update the ",(0,r.kt)("inlineCode",{parentName:"li"},"main")," function in ",(0,r.kt)("inlineCode",{parentName:"li"},"entry.rs")," to check inputs / outputs UDT amount:")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},'pub fn main() -> Result<(), Error> {\n // remove below examples and write your code here\n\n let script = load_script()?;\n let args: Bytes = script.args().unpack();\n debug!("script args is {:?}", args);\n\n // return an error if args is invalid\n if args.is_empty() {\n return Err(Error::LengthNotEnough);\n }\n\n let tx_hash = load_tx_hash()?;\n debug!("tx hash is {:?}", tx_hash);\n\n let _buf: Vec<_> = vec![0u8; 32];\n\n // return success if owner mode is true\n if check_owner_mode(&args)? {\n return Ok(())\n }\n\n let inputs_amount = collect_inputs_amount()?;\n let outputs_amount = collect_outputs_amount()?;\n\n if inputs_amount < outputs_amount {\n return Err(Error::Amount);\n }\n // more verifications ...\n Ok(())\n}\n')),(0,r.kt)("h3",{id:"use-iterator-to-query-cells"},"Use Iterator to query cells"),(0,r.kt)("p",null,"In the previous code, we use ",(0,r.kt)("inlineCode",{parentName:"p"},"for")," loop to iterate inputs and outputs, since iteration over cells is a common pattern in CKB programming, ",(0,r.kt)("inlineCode",{parentName:"p"},"ckb-std")," provides a high-level interface ",(0,r.kt)("a",{parentName:"p",href:"https://nervosnetwork.github.io/ckb-std/riscv64imac-unknown-none-elf/doc/ckb_std/high_level/struct.QueryIter.html"},"QueryIter")," to handle it."),(0,r.kt)("p",null,"QueryIter needs two args, the first is a loading function, the seconds is ",(0,r.kt)("inlineCode",{parentName:"p"},"Source"),". This is an example to load all grouped inputs cells data ",(0,r.kt)("inlineCode",{parentName:"p"},"QueryIter::new(load_cell_data, Source::GroupInput)"),"."),(0,r.kt)("p",null,"Rewrite our functions in ",(0,r.kt)("inlineCode",{parentName:"p"},"entry.rs"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},"\n// import this\nuse ckb_std::high_level::QueryIter;\n\n// Other codes...\n\nfn check_owner_mode(args: &Bytes) -> Result {\n // With owner lock script extracted, we will look through each input in the\n // current transaction to see if any unlocked cell uses owner lock.\n let is_owner_mode = QueryIter::new(load_cell_lock_hash, Source::Input)\n .find(|lock_hash| args[..] == lock_hash[..]).is_some();\n Ok(is_owner_mode)\n}\n\nfn collect_inputs_amount() -> Result {\n // let's loop through all input cells containing current UDTs,\n // and gather the sum of all input tokens.\n let mut buf = [0u8; UDT_LEN];\n\n let udt_list = QueryIter::new(load_cell_data, Source::GroupInput)\n .map(|data|{\n if data.len() == UDT_LEN {\n buf.copy_from_slice(&data);\n // u128 is 16 bytes\n Ok(u128::from_le_bytes(buf))\n } else {\n Err(Error::Encoding)\n }\n }).collect::, Error>>()?;\n Ok(udt_list.into_iter().sum::())\n}\n\nfn collect_outputs_amount() -> Result {\n // With the sum of all input UDT tokens gathered, let's now iterate through\n // output cells to grab the sum of all output UDT tokens.\n let mut buf = [0u8; UDT_LEN];\n\n let udt_list = QueryIter::new(load_cell_data, Source::GroupOutput)\n .map(|data|{\n if data.len() == UDT_LEN {\n buf.copy_from_slice(&data);\n // u128 is 16 bytes\n Ok(u128::from_le_bytes(buf))\n } else {\n Err(Error::Encoding)\n }\n }).collect::, Error>>()?;\n Ok(udt_list.into_iter().sum::())\n}\n\n")),(0,r.kt)("p",null,"Now we have finished the SUDT script, you may refer to ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/jjyr/my-sudt/blob/master/contracts/my-sudt/src/main.rs"},"Full code of my-sudt")," to check the full script code. If you are interested, you may also check ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/ckb-miscellaneous-scripts/blob/master/c/simple_udt.c"},"the SUDT script written in C"),"."),(0,r.kt)("h3",{id:"build-the-project-1"},"Build the project"),(0,r.kt)("p",null,"Run ",(0,r.kt)("inlineCode",{parentName:"p"},"capsule build")," under the project directory to build the script.If no error occurred, we can find the script binary at ",(0,r.kt)("inlineCode",{parentName:"p"},"my-usdt/build/debug/my-sudt"),". "),(0,r.kt)("h2",{id:"testing"},"Testing"),(0,r.kt)("p",null,"We will use the ",(0,r.kt)("inlineCode",{parentName:"p"},"ckb-testtool")," crate to construct transactions and context for our testing."),(0,r.kt)("h3",{id:"check-the-default-tests"},"Check the default tests"),(0,r.kt)("p",null,"When create the project ",(0,r.kt)("inlineCode",{parentName:"p"},"my-sudt"),",",(0,r.kt)("inlineCode",{parentName:"p"},"capsule")," have generated the default tests.The default tests create mock cells and unlock them for testing."),(0,r.kt)("p",null,"Use ",(0,r.kt)("inlineCode",{parentName:"p"},"capsule build")," under the project directory to build the script,\nthen use ",(0,r.kt)("inlineCode",{parentName:"p"},"capsule test")," to run the default tests.We will find the error message:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"failures:\n\n---- tests::test_basic stdout ----\nthread 'tests::test_basic' panicked at 'pass verification: Error { kind: ValidationFailure(4)Script }', tests/src/tests.rs:52:5\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace\n\n\nfailures:\n tests::test_basic\n")),(0,r.kt)("p",null,"The error number ",(0,r.kt)("inlineCode",{parentName:"p"},"4")," in ",(0,r.kt)("inlineCode",{parentName:"p"},"Error { kind: ValidationFailure(4)")," refers to ",(0,r.kt)("inlineCode",{parentName:"p"},"Error::Encoding"),", which means the cell\u2019s data type is not ",(0,r.kt)("inlineCode",{parentName:"p"},"u128"),". "),(0,r.kt)("p",null,"Let\u2019s check the default tests code ",(0,r.kt)("inlineCode",{parentName:"p"},"tests/src/tests.rs")," to find out how to write the tests, then we can write new tests adapted ",(0,r.kt)("inlineCode",{parentName:"p"},"my-sudt"),"\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"In the beginning part, initialize the ",(0,r.kt)("inlineCode",{parentName:"li"},"Context")," which is a structure to simulate the chain environment. We can use ",(0,r.kt)("inlineCode",{parentName:"li"},"Context")," to deploy exists cells and mock block headers.",(0,r.kt)("inlineCode",{parentName:"li"},"deploy_contract")," will return the ",(0,r.kt)("inlineCode",{parentName:"li"},"out_point")," of the script.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},'// deploy contract\n let mut context = Context::default();\n let contract_bin: Bytes = Loader::default().load_binary("my-sudt");\n let contract_out_point = context.deploy_contract(contract_bin);\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Then ",(0,r.kt)("inlineCode",{parentName:"li"},"build_script")," is called with the script's ",(0,r.kt)("inlineCode",{parentName:"li"},"out_point")," , this function returns the ",(0,r.kt)("inlineCode",{parentName:"li"},"Script")," which uses our script as the code. ",(0,r.kt)("inlineCode",{parentName:"li"},"create_cell")," creates an existing cell in the context, which uses our script as the ",(0,r.kt)("inlineCode",{parentName:"li"},"lock_script"),".")),(0,r.kt)("p",null,(0,r.kt)("em",{parentName:"p"},"Please note the default tests assume the script is a lock_script, but in our case, ",(0,r.kt)("inlineCode",{parentName:"em"},"my-sudt")," is a type_script. We'll fix it later.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},'// prepare scripts\n let lock_script = context.build_script(&contract_out_point, Default::default()).expect("script");\n let lock_script_dep = CellDep::new_builder().out_point(contract_out_point).build();\n\n // prepare cells\n let input_out_point = context.create_cell(\n CellOutput::new_builder()\n .capacity(1000u64.pack())\n .lock(lock_script.clone())\n .build(),\n Bytes::new(),\n );\n let input = CellInput::new_builder()\n .previous_output(input_out_point)\n .build();\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"After that, build two outputs cells and a transaction structure.It is necessary to include ",(0,r.kt)("inlineCode",{parentName:"li"},"cell_deps")," field in the transaction which should contain all the referenced scripts, in this case, we can only refer to ",(0,r.kt)("inlineCode",{parentName:"li"},"my-sudt"),". ",(0,r.kt)("inlineCode",{parentName:"li"},"complete_tx")," also implement ",(0,r.kt)("inlineCode",{parentName:"li"},"cell_deps"),", while the field is already completed manually, this line is not necessary.")),(0,r.kt)("p",null,"Please note that the transaction's ",(0,r.kt)("inlineCode",{parentName:"p"},"outputs_data")," must have the same length with the ",(0,r.kt)("inlineCode",{parentName:"p"},"outputs"),", even the data is empty."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},"let outputs = vec![\n CellOutput::new_builder()\n .capacity(500u64.pack())\n .lock(lock_script.clone())\n .build(),\n CellOutput::new_builder()\n .capacity(500u64.pack())\n .lock(lock_script)\n .build(),\n ];\n\n let outputs_data = vec![Bytes::new(); 2];\n\n // build transaction\n let tx = TransactionBuilder::default()\n .input(input)\n .outputs(outputs)\n .outputs_data(outputs_data.pack())\n .cell_dep(lock_script_dep)\n .build();\n let tx = context.complete_tx(tx);\n")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Finally, verify the transaction:")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'// run\n context\n .verify_tx(&tx, MAX_CYCLES)\n .expect("pass verification");\n')),(0,r.kt)("h3",{id:"write-new-tests"},"Write new tests"),(0,r.kt)("p",null,"We should create mock SUDT cells and spend them for testing SUDT verification.\nAs ",(0,r.kt)("inlineCode",{parentName:"p"},"my-sudt")," script is a ",(0,r.kt)("inlineCode",{parentName:"p"},"type_script")," we need another script as ",(0,r.kt)("inlineCode",{parentName:"p"},"lock_script")," for mock cells, it is recommended to use ",(0,r.kt)("inlineCode",{parentName:"p"},"always success")," script returned ",(0,r.kt)("inlineCode",{parentName:"p"},"0"),". ",(0,r.kt)("inlineCode",{parentName:"p"},"always success")," is built-in in the ",(0,r.kt)("inlineCode",{parentName:"p"},"ckb-testtool"),"."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},"use ckb_testtool::{builtin::ALWAYS_SUCCESS, context::Context};\n\n // deploy always_success script\n let always_success_out_point = context.deploy_contract(ALWAYS_SUCCESS.clone());\n")),(0,r.kt)("p",null,"Before writing the code, let's think about our test cases:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Return success when input tokens equals to output tokens."),(0,r.kt)("li",{parentName:"ol"},"Return success when input tokens is greater than output tokens."),(0,r.kt)("li",{parentName:"ol"},"Return failure when input tokens is less than output tokens."),(0,r.kt)("li",{parentName:"ol"},"Return success when input tokens is less than output tokens with ",(0,r.kt)("inlineCode",{parentName:"li"},"owner mode")," activated.")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Define ",(0,r.kt)("inlineCode",{parentName:"p"},"build_test_context")," to build transactions. There are three args: "),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"The data type of ",(0,r.kt)("inlineCode",{parentName:"li"},"inputs_token")," and ",(0,r.kt)("inlineCode",{parentName:"li"},"outputs_token")," is ",(0,r.kt)("inlineCode",{parentName:"li"},"u128"),". The function can generate SUDT inputs cells and outputs cells according to the two args."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"is_owner_mode")," refers to the current transaction is in SUDT owner mode or normal mode."))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Deploy the SUDT and ",(0,r.kt)("inlineCode",{parentName:"p"},"always-success")," scripts."))),(0,r.kt)("p",null,"Please note that if ",(0,r.kt)("inlineCode",{parentName:"p"},"is_owner_mode")," is true, we will set ",(0,r.kt)("inlineCode",{parentName:"p"},"lock_script"),"'s ",(0,r.kt)("inlineCode",{parentName:"p"},"lock_hash")," as ",(0,r.kt)("inlineCode",{parentName:"p"},"owner script hash"),"; otherwise, we will set ",(0,r.kt)("inlineCode",{parentName:"p"},"[0u8; 32]")," which implies can't enter into owner mode."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},'fn build_test_context(\n inputs_token: Vec,\n outputs_token: Vec,\n is_owner_mode: bool,\n) -> (Context, TransactionView) {\n // deploy my-sudt script\n let mut context = Context::default();\n let sudt_bin: Bytes = Loader::default().load_binary("my-sudt");\n let sudt_out_point = context.deploy_contract(sudt_bin);\n // deploy always_success script\n let always_success_out_point = context.deploy_contract(ALWAYS_SUCCESS.clone());\n\n // build lock script\n let lock_script = context\n .build_script(&always_success_out_point, Default::default())\n .expect("script");\n let lock_script_dep = CellDep::new_builder()\n .out_point(always_success_out_point)\n .build();\n\n // build sudt script\n let sudt_script_args: Bytes = if is_owner_mode {\n // use always_success script hash as owner\'s lock\n let lock_hash: [u8; 32] = lock_script.calc_script_hash().unpack();\n lock_hash.to_vec().into()\n } else {\n // use zero hash as owner\'s lock which implies we can never enter owner mode\n [0u8; 32].to_vec().into()\n };\n\n let sudt_script = context\n .build_script(&sudt_out_point, sudt_script_args)\n .expect("script");\n let sudt_script_dep = CellDep::new_builder().out_point(sudt_out_point).build();\n\n //... more code below\n//}\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Build inputs and outputs according to the ",(0,r.kt)("inlineCode",{parentName:"li"},"inputs_token")," and ",(0,r.kt)("inlineCode",{parentName:"li"},"outputs_token")," ")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},"// ...\n // prepare inputs\n // assign 1000 Bytes to per input\n let input_ckb = Capacity::bytes(1000).unwrap().as_u64();\n let inputs = inputs_token.iter().map(|token| {\n let input_out_point = context.create_cell(\n CellOutput::new_builder()\n .capacity(input_ckb.pack())\n .lock(lock_script.clone())\n .type_(Some(sudt_script.clone()).pack())\n .build(),\n token.to_le_bytes().to_vec().into(),\n );\n let input = CellInput::new_builder()\n .previous_output(input_out_point)\n .build();\n input\n });\n\n // prepare outputs\n let output_ckb = input_ckb * inputs_token.len() as u64 / outputs_token.len() as u64;\n let outputs = outputs_token.iter().map(|_token| {\n CellOutput::new_builder()\n .capacity(output_ckb.pack())\n .lock(lock_script.clone())\n .type_(Some(sudt_script.clone()).pack())\n .build()\n });\n let outputs_data: Vec<_> = outputs_token\n .iter()\n .map(|token| Bytes::from(token.to_le_bytes().to_vec()))\n .collect();\n // ...\n")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Finally construct the transaction and return it with context.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"// build transaction\n let tx = TransactionBuilder::default()\n .inputs(inputs)\n .outputs(outputs)\n .outputs_data(outputs_data.pack())\n .cell_dep(lock_script_dep)\n .cell_dep(sudt_script_dep)\n .build();\n (context, tx)\n")),(0,r.kt)("p",null,"Now the helper function ",(0,r.kt)("inlineCode",{parentName:"p"},"build_test_context")," is finished, we can write our tests: "),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},'#[test]\nfn test_basic() {\n let (mut context, tx) = build_test_context(vec![1000], vec![400, 600], false);\n let tx = context.complete_tx(tx);\n\n // run\n context\n .verify_tx(&tx, MAX_CYCLES)\n .expect("pass verification");\n}\n\n#[test]\nfn test_destroy_udt() {\n let (mut context, tx) = build_test_context(vec![1000], vec![800, 100, 50], false);\n let tx = context.complete_tx(tx);\n\n // run\n context\n .verify_tx(&tx, MAX_CYCLES)\n .expect("pass verification");\n}\n\n#[test]\nfn test_create_sudt_without_owner_mode() {\n let (mut context, tx) = build_test_context(vec![1000], vec![1200], false);\n let tx = context.complete_tx(tx);\n\n // run\n let err = context.verify_tx(&tx, MAX_CYCLES).unwrap_err();\n assert_error_eq!(err, ScriptError::ValidationFailure(ERROR_AMOUNT));\n}\n\n#[test]\nfn test_create_sudt_with_owner_mode() {\n let (mut context, tx) = build_test_context(vec![1000], vec![1200], true);\n let tx = context.complete_tx(tx);\n\n // run\n context\n .verify_tx(&tx, MAX_CYCLES)\n .expect("pass verification");\n}\n')),(0,r.kt)("p",null,"You may refer to ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/jjyr/my-sudt/blob/master/tests/src/tests.rs"},"my-sudt tests")," for the full tests. Run ",(0,r.kt)("inlineCode",{parentName:"p"},"capsule test")," all tests will be passed."),(0,r.kt)("h2",{id:"deployment"},"Deployment"),(0,r.kt)("h3",{id:"run-a-dev-chain-and-ckb-cli-1"},"Run a dev chain and ckb-cli"),(0,r.kt)("p",null,"You should be running a dev chain and know about how to use ",(0,r.kt)("inlineCode",{parentName:"p"},"ckb-cli")," to send transactions before deployment. "),(0,r.kt)("h3",{id:"deploy"},"Deploy"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Update the deployment configurations"),(0,r.kt)("p",{parentName:"li"},"Open ",(0,r.kt)("inlineCode",{parentName:"p"},"deployment.toml")," :"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"cells")," describes which cells to be deployed."),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"name"),": Define the reference name used in the deployment configuration."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"enable_type_id")," : If it is set to ",(0,r.kt)("inlineCode",{parentName:"li"},"true")," means create a ",(0,r.kt)("inlineCode",{parentName:"li"},"type_id")," for the cell."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"location")," : Define the script binary path."))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"dep_groups")," describes which dep_groups to be created. Dep Group is a cell which bundles several cells as its members. When a dep group cell is used in ",(0,r.kt)("inlineCode",{parentName:"p"},"cell_deps"),", it has the same effect as adding all its members into ",(0,r.kt)("inlineCode",{parentName:"p"},"cell_deps"),". In our case, we don\u2019t need ",(0,r.kt)("inlineCode",{parentName:"p"},"dep_groups"),".")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"lock")," describes the ",(0,r.kt)("inlineCode",{parentName:"p"},"lock")," field of the new deployed cells.It is recommended to set ",(0,r.kt)("inlineCode",{parentName:"p"},"lock")," to the deployer's address(an address that you can unlock) in the dev chain and in the testnet, which is easier to update the script.")))),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Uncomment the configuration file and replace the cell name and location with ",(0,r.kt)("inlineCode",{parentName:"p"},"my-usdt"),"."))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'# [[cells]]\n# name = "my_cell"\n# enable_type_id = false\n# location = { file = "build/release/my_cell" }\n\n# # Dep group cells\n# [[dep_groups]]\n# name = "my_dep_group"\n# cells = [\n# "my_cell",\n# "secp256k1_data"\n# ]\n\n# # Replace with your own lock if you want to unlock deployed cells.\n# # The deployment code_hash is secp256k1 lock\n# [lock]\n# code_hash = "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8"\n# args = "0x0000000000000000000000000000000000000000"\n# hash_type = "type"\n')),(0,r.kt)("ol",{start:3},(0,r.kt)("li",{parentName:"ol"},"Build release version of the script")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"The release version of script doesn\u2019t include debug symbols which makes the size smaller.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"capsule build --release\n")),(0,r.kt)("ol",{start:4},(0,r.kt)("li",{parentName:"ol"},"Deploy the script ")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"capsule deploy --address \n")),(0,r.kt)("p",null,"If the ",(0,r.kt)("inlineCode",{parentName:"p"},"ckb-cli")," has been installed and dev-chain RPC is connectable, you will see the ",(0,r.kt)("inlineCode",{parentName:"p"},"deployment plan"),":"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"new_occupied_capacity")," and ",(0,r.kt)("inlineCode",{parentName:"li"},"total_occupied_capacity")," refer how much CKB to store cells and data."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"txs_fee_capacity")," refers how much CKB to pay the transaction fee.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"Deployment plan:\n---\nmigrated_capacity: 0.0 (CKB)\nnew_occupied_capacity: 33629.0 (CKB)\ntxs_fee_capacity: 0.0001 (CKB)\ntotal_occupied_capacity: 33629.0 (CKB)\nrecipe:\n cells:\n - name: my-sudt\n index: 0\n tx_hash: 0x8b496cb19018c475cdc4605ee9cef83cbfe578dce4f81f3367395906eba52c29\n occupied_capacity: 33629.0 (CKB)\n data_hash: 0xaa3d472025e6afefdf3f65c5f9beefd206b4283b30551baef83cbb4762e6d397\n type_id: ~\n dep_groups: []\nConfirm deployment? (Yes/No)\n")),(0,r.kt)("ol",{start:5},(0,r.kt)("li",{parentName:"ol"},"Type ",(0,r.kt)("inlineCode",{parentName:"li"},"yes")," or ",(0,r.kt)("inlineCode",{parentName:"li"},"y")," and input the password to unlock the account.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"send cell_tx 8b496cb19018c475cdc4605ee9cef83cbfe578dce4f81f3367395906eba52c29\nDeployment complete\n")),(0,r.kt)("p",null,"Now the SUDT script has been deployed, you can refer to this script by using ",(0,r.kt)("inlineCode",{parentName:"p"},"tx_hash: 0xaa3d472025e6afefdf3f65c5f9beefd206b4283b30551baef83cbb4762e6d397 index: 0")," as ",(0,r.kt)("inlineCode",{parentName:"p"},"out_point"),"(your ",(0,r.kt)("inlineCode",{parentName:"p"},"tx_hash")," should be another value)."),(0,r.kt)("h3",{id:"migration"},"Migration"),(0,r.kt)("p",null,"If you want to update the script code and deploy again, you can simply run this command again:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"capsule deploy --address ckt1qyq075y5ctzlgahu8pgsqxrqnglajgwa9zksmqdupd\n")),(0,r.kt)("p",null,"The new script will be automatically migrated which means destroy the old script cells and create new cells.\nYou will find ",(0,r.kt)("inlineCode",{parentName:"p"},"new_occupied_capacity")," is ",(0,r.kt)("inlineCode",{parentName:"p"},"0")," because ",(0,r.kt)("inlineCode",{parentName:"p"},"capacity")," is already covered by the old script cells.Please don\u2019t forget the transaction fee you still need to pay it."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"Deployment plan:\n---\nmigrated_capacity: 33629.0 (CKB)\nnew_occupied_capacity: 0.0 (CKB)\ntxs_fee_capacity: 0.0001 (CKB)\ntotal_occupied_capacity: 33629.0 (CKB)\nrecipe:\n cells:\n - name: my-sudt\n index: 0\n tx_hash: 0x10d508a0b44d3c1e02982f85a3e9b5d23d3961fddbf554d20abb4bf54f61950a\n occupied_capacity: 33629.0 (CKB)\n data_hash: 0xaa3d472025e6afefdf3f65c5f9beefd206b4283b30551baef83cbb4762e6d397\n type_id: ~\n dep_groups: []\nConfirm deployment? (Yes/No)\n")),(0,r.kt)("h2",{id:"next-steps"},"Next Steps"),(0,r.kt)("p",null,"This is the end of our journey into writing a SUDT script by Capsule. We have launched the ",(0,r.kt)("a",{parentName:"p",href:"https://www.nervos.org/grants/"},"Nervos Grants Program")," and ",(0,r.kt)("a",{parentName:"p",href:"https://medium.com/nervosnetwork/introducing-cklabs-the-nervos-incubator-3e5a2c443c7c"},"CKLabs")," to empower innovation and development and support the growth of a diverse and thriving ecosystem. We can't wait to see what you build next!"))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/8af0162e.755af75f.js b/assets/js/8af0162e.755af75f.js deleted file mode 100644 index 3dc231701..000000000 --- a/assets/js/8af0162e.755af75f.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[6049],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>m});var a=n(7294);function l(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function o(e){for(var t=1;t=0||(l[n]=e[n]);return l}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(l[n]=e[n])}return l}var s=a.createContext({}),u=function(e){var t=a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},c=function(e){var t=u(e.components);return a.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},d=a.forwardRef((function(e,t){var n=e.components,l=e.mdxType,r=e.originalType,s=e.parentName,c=i(e,["components","mdxType","originalType","parentName"]),d=u(n),m=l,k=d["".concat(s,".").concat(m)]||d[m]||p[m]||r;return n?a.createElement(k,o(o({ref:t},c),{},{components:n})):a.createElement(k,o({ref:t},c))}));function m(e,t){var n=arguments,l=t&&t.mdxType;if("string"==typeof e||l){var r=n.length,o=new Array(r);o[0]=d;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i.mdxType="string"==typeof e?e:l,o[1]=i;for(var u=2;u{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>m,frontMatter:()=>i,metadata:()=>u,toc:()=>p});var a=n(7462),l=n(3366),r=(n(7294),n(3905)),o=["components"],i={id:"sudtbycapsule",title:"Write an SUDT Script by Capsule"},s=void 0,u={unversionedId:"labs/sudtbycapsule",id:"labs/sudtbycapsule",title:"Write an SUDT Script by Capsule",description:"Introduction",source:"@site/docs/labs/sudtbycapsule.md",sourceDirName:"labs",slug:"/labs/sudtbycapsule",permalink:"/docs/labs/sudtbycapsule",draft:!1,editUrl:"https://github.com/nervosnetwork/docs-new/tree/develop/website/docs/labs/sudtbycapsule.md",tags:[],version:"current",frontMatter:{id:"sudtbycapsule",title:"Write an SUDT Script by Capsule"},sidebar:"Labs",previous:{title:"Introduction",permalink:"/docs/labs/introduction"},next:{title:"Introduction to Lumos via NervosDAO",permalink:"/docs/labs/lumos-nervosdao"}},c={},p=[{value:"Introduction",id:"introduction",level:2},{value:"Prepare to write the SUDT script",id:"prepare-to-write-the-sudt-script",level:2},{value:"Run a dev chain and ckb-cli",id:"run-a-dev-chain-and-ckb-cli",level:3},{value:"Install Capsule",id:"install-capsule",level:3},{value:"Prerequisites",id:"prerequisites",level:4},{value:"Create a project",id:"create-a-project",level:3},{value:"Build the project",id:"build-the-project",level:3},{value:"Write a SUDT script",id:"write-a-sudt-script",level:2},{value:"Check the used libraries",id:"check-the-used-libraries",level:3},{value:"Load Script",id:"load-script",level:3},{value:"Check inputs",id:"check-inputs",level:3},{value:"Load inputs / outputs UDT amount",id:"load-inputs--outputs-udt-amount",level:3},{value:"Use Iterator to query cells",id:"use-iterator-to-query-cells",level:3},{value:"Build the project",id:"build-the-project-1",level:3},{value:"Testing",id:"testing",level:2},{value:"Check the default tests",id:"check-the-default-tests",level:3},{value:"Write new tests",id:"write-new-tests",level:3},{value:"Deployment",id:"deployment",level:2},{value:"Run a dev chain and ckb-cli",id:"run-a-dev-chain-and-ckb-cli-1",level:3},{value:"Deploy",id:"deploy",level:3},{value:"Migration",id:"migration",level:3},{value:"Next Steps",id:"next-steps",level:2}],d={toc:p};function m(e){var t=e.components,n=(0,l.Z)(e,o);return(0,r.kt)("wrapper",(0,a.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h2",{id:"introduction"},"Introduction"),(0,r.kt)("p",null,(0,r.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/capsule"},"Capsule")," is a set of tools for Rust developers to develop scripts on CKB which covers the entire lifecycle of script development: writing,debugging,testing and deployment. We aim to improve the development experience of Rust developers."),(0,r.kt)("p",null,"In this tutorial, you will learn how to write a SUDT script using Capsule. SUDT is the abbreviation of Simple User Defined Token which defines a minimal standard that contains what\u2019s absolutely needed for dapp developers to issue custom tokens on Nervos CKB. You can refer to ",(0,r.kt)("a",{parentName:"p",href:"https://talk.nervos.org/t/rfc-simple-udt-draft-spec/4333"},"RFC: Simple UDT Draft Spec")," for more details."),(0,r.kt)("p",null,"We expect that:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"You are Rust developers and generally familiar with software development, writing code, and running your code."),(0,r.kt)("li",{parentName:"ul"},"You are generally familiar with Nervos CKB and have completed the ",(0,r.kt)("a",{parentName:"li",href:"/docs/basics/guides/devchain"},"How to use a development blockchain")),(0,r.kt)("li",{parentName:"ul"},"You are open to learning about the bleeding edge of blockchain development")),(0,r.kt)("p",null,"If you run into an issue on this tutorial you can ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/capsule"},"create a new issue")," or contact us on ",(0,r.kt)("a",{parentName:"p",href:"https://talk.nervos.org/"},"Nervos talk")," or ",(0,r.kt)("a",{parentName:"p",href:"https://discord.gg/n6tx7uC"},"Discord"),". "),(0,r.kt)("p",null,"What you will be doing:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Prepare to write the SUDT script "),(0,r.kt)("li",{parentName:"ul"},"Write a SUDT script"),(0,r.kt)("li",{parentName:"ul"},"Testing"),(0,r.kt)("li",{parentName:"ul"},"Deployment ")),(0,r.kt)("h2",{id:"prepare-to-write-the-sudt-script"},"Prepare to write the SUDT script"),(0,r.kt)("h3",{id:"run-a-dev-chain-and-ckb-cli"},"Run a dev chain and ckb-cli"),(0,r.kt)("p",null,"You should be able to run a dev chain and know about how to use ",(0,r.kt)("inlineCode",{parentName:"p"},"ckb-cli")," to send transactions. If you do not, please refer to this tutorial\uff1a",(0,r.kt)("a",{parentName:"p",href:"/docs/basics/guides/devchain"},"How to use a development blockchain"),". Please don't forget to add ",(0,r.kt)("inlineCode",{parentName:"p"},"ckb-cli")," to the PATH environment variable"),(0,r.kt)("h3",{id:"install-capsule"},"Install Capsule"),(0,r.kt)("h4",{id:"prerequisites"},"Prerequisites"),(0,r.kt)("p",null,"The following must be installed and available to use Capsule."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Cargo and Rust - Capsule uses cargo to generate Rust contracts and run tests. ",(0,r.kt)("a",{parentName:"li",href:"https://www.rust-lang.org/tools/install."},"Install Rust")),(0,r.kt)("li",{parentName:"ul"},"Docker - Capsule uses ",(0,r.kt)("inlineCode",{parentName:"li"},"docker")," container to reproducible build contracts. It's also used by ",(0,r.kt)("inlineCode",{parentName:"li"},"cross"),". ",(0,r.kt)("a",{parentName:"li",href:"https://docs.docker.com/get-docker/"},"https://docs.docker.com/get-docker/")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"cross-rs")," - Capsule uses ",(0,r.kt)("inlineCode",{parentName:"li"},"cross")," to build rust contracts. Install with ")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"# Do this after you installed cargo\ncargo install cross --git https://github.com/cross-rs/cross\n")),(0,r.kt)("p",null,"Note: The current user must have permission to manage Docker instances. For more information, see ",(0,r.kt)("a",{parentName:"p",href:"https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user"},"Manage Docker as a non-root user"),"."),(0,r.kt)("h3",{id:""}),(0,r.kt)("p",null,"Now you can proceed to install Capsule. It is recommended to download the binary ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/capsule/releases"},"here"),"."),(0,r.kt)("p",null,"Or you can install Capsule from it's source:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"cargo install capsule --git https://github.com/nervosnetwork/capsule.git --tag v0.1.3\n")),(0,r.kt)("p",null,"Then check if it works with the following command:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"capsule check\n")),(0,r.kt)("details",null,(0,r.kt)("summary",null,"(click here to view response)"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"------------------------------\ncargo installed\ndocker installed\ncross-util installed\nckb-cli installed v1.4.0 (required v1.2.0)\n------------------------------\n"))),(0,r.kt)("h3",{id:"create-a-project"},"Create a project"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"capsule new my-sudt\n")),(0,r.kt)("details",null,(0,r.kt)("summary",null,"(click here to view response)"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},'New project "my-sudt"\nCreated file "capsule.toml"\nCreated file "deployment.toml"\nCreated file "README.md"\nCreated file "rust-toolchain"\nCreated file "Cross.toml"\nCreated file "Cargo.toml"\nCreated file ".gitignore"\nInitialized empty Git repository in ./my-sudt/.git/\nCreated "./my-sudt"\nCreated tests\nNew contract "my-sudt"\nRewrite Cargo.toml\nRewrite capsule.toml\nDone\n'))),(0,r.kt)("p",null,"You can check the project\u2019s layout\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"ls my-sudt\n")),(0,r.kt)("details",null,(0,r.kt)("summary",null,"(click here to view response)"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"\nbuild capsule.toml Cargo.toml contracts deployment.toml migrations README.md tests\n"))),(0,r.kt)("p",null,"The default contract is under ",(0,r.kt)("inlineCode",{parentName:"p"},"my-sudt/contracts/my-sudt")," directory which is a normal cargo project:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"ls my-sudt/contracts/my-sudt\n")),(0,r.kt)("details",null,(0,r.kt)("summary",null,"(click here to view response)"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"\nCargo.toml src\n"))),(0,r.kt)("p",null,"You can open ",(0,r.kt)("inlineCode",{parentName:"p"},"my-sudt/contracts/my-sudt/src/main.rs")," to see some pre-generated code:"),(0,r.kt)("details",null,(0,r.kt)("summary",null,"(click here to view full code)"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},"//! Generated by capsule\n//!\n//! `main.rs` is used to define rust lang items and modules.\n//! See `entry.rs` for the `main` function. \n//! See `error.rs` for the `Error` type.\n\n#![no_std]\n#![cfg_attr(not(test), no_main)]\n\n// define modules\nmod entry;\nmod error;\n\n#[cfg(test)]\nextern crate alloc;\n\n#[cfg(not(test))]\nuse ckb_std::default_alloc;\n#[cfg(not(test))]\nckb_std::entry!(program_entry);\n#[cfg(not(test))]\ndefault_alloc!();\n\n/// program entry\npub fn program_entry() -> i8 {\n // Call main function and return error code\n match entry::main() {\n Ok(_) => 0,\n Err(err) => err as i8,\n }\n}\n"))),(0,r.kt)("p",null,"and also ",(0,r.kt)("inlineCode",{parentName:"p"},"my-sudt/contracts/my-sudt/src/entry.rs")),(0,r.kt)("details",null,(0,r.kt)("summary",null,"(click here to view full code)"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},'// Import from `core` instead of from `std` since we are in no-std mode\nuse core::result::Result;\n\n// Import heap related library from `alloc`\n// https://doc.rust-lang.org/alloc/index.html\nuse alloc::{vec, vec::Vec};\n\n// Import CKB syscalls and structures\n// https://docs.rs/ckb-std/\nuse ckb_std::{\n debug,\n high_level::{load_script, load_tx_hash},\n ckb_types::{bytes::Bytes, prelude::*},\n};\n\nuse crate::error::Error;\n\npub fn main() -> Result<(), Error> {\n // remove below examples and write your code here\n\n let script = load_script()?;\n let args: Bytes = script.args().unpack();\n debug!("script args is {:?}", args);\n\n // return an error if args is invalid\n if args.is_empty() {\n return Err(Error::MyError);\n }\n\n let tx_hash = load_tx_hash()?;\n debug!("tx hash is {:?}", tx_hash);\n\n let _buf: Vec<_> = vec![0u8; 32];\n\n Ok(())\n}\n\n// Unit tests are supported.\n#[test]\nfn test_foo() {\n assert!(true);\n}\n'))),(0,r.kt)("h3",{id:"build-the-project"},"Build the project"),(0,r.kt)("p",null,"Enter into the project ",(0,r.kt)("inlineCode",{parentName:"p"},"my-sudt")," and build it."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"cd my-sudt\ncapsule build\n")),(0,r.kt)("details",null,(0,r.kt)("summary",null,"(click here to view full console log)"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"Building contract demo\n$ cross build -p demo\ninfo: syncing channel updates for '1.69.0-x86_64-unknown-linux-gnu'\ninfo: latest update on 2023-04-20, rust version 1.69.0 (84c898d65 2023-04-16)\ninfo: downloading component 'cargo'\ninfo: downloading component 'rust-std'\n 27.2 MiB / 27.2 MiB (100 %) 14.7 MiB/s in 1s ETA: 0s\ninfo: downloading component 'rustc'\n 60.0 MiB / 60.0 MiB (100 %) 18.8 MiB/s in 3s ETA: 0s\ninfo: installing component 'cargo'\ninfo: installing component 'rust-std'\n 27.2 MiB / 27.2 MiB (100 %) 20.7 MiB/s in 1s ETA: 0s\ninfo: installing component 'rustc'\n 60.0 MiB / 60.0 MiB (100 %) 23.6 MiB/s in 2s ETA: 0s\n\n 1.69.0-x86_64-unknown-linux-gnu installed - (error reading rustc version)\n\ninfo: checking for self-updates\ninfo: downloading self-update\ninfo: downloading component 'rust-std' for 'riscv64imac-unknown-none-elf'\ninfo: installing component 'rust-std' for 'riscv64imac-unknown-none-elf'\nUnable to find image 'nervos/ckb-riscv-gnu-toolchain:focal-20230214' locally\nfocal-20230214: Pulling from nervos/ckb-riscv-gnu-toolchain\n7608715873ec: Pull complete\na237f683deea: Pull complete\n84750871be6c: Pull complete\n3056067387e4: Pull complete\n258c66296219: Pull complete\ne8ea3d081562: Pull complete\n32afd1383aeb: Pull complete\n6f6c3bd439ca: Pull complete\nDigest: sha256:5732afe996b2b88a37ed3c0e4deb948e9d2a6936fb4b52d4e7a0dc5ad330c306\nStatus: Downloaded newer image for nervos/ckb-riscv-gnu-toolchain:focal-20230214\n Compiling cfg-if v1.0.0\n Compiling cc v1.0.79\n Compiling buddy-alloc v0.5.1\n Compiling molecule v0.7.5\n Compiling ckb-standalone-types v0.1.2\n Compiling ckb-std v0.13.0\n Compiling my-sudt v0.1.0 (./my-sudt/contracts/my-sudt)\n Finished dev [unoptimized + debuginfo] target(s) in 33.53s\nDone\n"))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Note: You might see some warning log like ",(0,r.kt)("inlineCode",{parentName:"li"},": MADV_DONTNEED does not work (memset will be used instead)"),", this isn't an abnormal behaviour, and won't make any trouble to us. It is caused by jemalloc under QEMU env, which is expected if you're running non-native docker containers under ",(0,r.kt)("inlineCode",{parentName:"li"},"aarch64")," architechture(for example an x86-64 container).")),(0,r.kt)("p",null,"You will find a new generated contract binary in the ",(0,r.kt)("inlineCode",{parentName:"p"},"build/debug")," directory:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"ls build/debug\n")),(0,r.kt)("details",null,(0,r.kt)("summary",null,"(click here to view response)"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"my-sudt\n"))),(0,r.kt)("p",null,"You're all done? Great, let's get coding."),(0,r.kt)("h2",{id:"write-a-sudt-script"},"Write a SUDT script"),(0,r.kt)("p",null,"SUDT scripts can be in ",(0,r.kt)("strong",{parentName:"p"},"owner mode")," and ",(0,r.kt)("strong",{parentName:"p"},"normal mode")," which include different verification rules, we should deal with that when we're coding."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"owner mode"),"\uff1aIf one of the transaction input has a lock script matching the SUDT script argument, the SUDT script will be in owner mode. We don\u2019t need to perform checks, the owner can perform any operations such as issuing more SUDTs or burning SUDTs. "),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"normal mode\uff1a"),"Otherwise, the SUDT script will be in normal mode. We need to ensure the sum of all inputs\u2019 capacity is not smaller than the sum of all outputs capacity. Please note that only one type of SUDT can be issued for each unique lock script. ")),(0,r.kt)("p",null,"The script is consisted of four parts\uff1aload script\u3001check inputs\u3001load inputs / outputs UDT amount\u3001error handling. We should check the used libraries before coding."),(0,r.kt)("h3",{id:"check-the-used-libraries"},"Check the used libraries"),(0,r.kt)("p",null,"Open ",(0,r.kt)("inlineCode",{parentName:"p"},"contracts/my-sudt/Cargo.toml"),", we already have a dependency:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'[dependencies]\nckb-std = "0.13"\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ckb-std")," is a crate used to handling CKB syscalls."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ckb-standalone-types")," is a crate which re-exported as the ",(0,r.kt)("inlineCode",{parentName:"li"},"ckb_std::ckb_types")," provides the definition of CKB structures.")),(0,r.kt)("p",null,"You may refer to ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/capsule/wiki/Rust-libraries"},"Rust libraries")," for more useful crates. We can only use crates which supports ",(0,r.kt)("inlineCode",{parentName:"p"},"no-std")," in scripts."),(0,r.kt)("h3",{id:"load-script"},"Load Script"),(0,r.kt)("p",null,"At the beginning of the script, we need to check the SUDT\u2019s mode, if it is owner mode, we simply skip the verification code and return ",(0,r.kt)("inlineCode",{parentName:"p"},"0"),", which represents the verification is successful, otherwise we check the amount of UDT."),(0,r.kt)("p",null,"To achieve this, we need to load ",(0,r.kt)("inlineCode",{parentName:"p"},"args")," of the current script, which the generated code already did for us. So we just remove the unused lines from the ",(0,r.kt)("inlineCode",{parentName:"p"},"main")," function."),(0,r.kt)("p",null,"In the code below, we load the current script(SUDT)'s args field, and invoke ",(0,r.kt)("inlineCode",{parentName:"p"},"check_owner_mode")," which we have not defined yet."),(0,r.kt)("p",null,"Notice since we are using no-std Rust, we can't directly use the ",(0,r.kt)("inlineCode",{parentName:"p"},"std")," in the code. Instead, we need to import the ",(0,r.kt)("inlineCode",{parentName:"p"},"Vec")," struct from the ",(0,r.kt)("a",{parentName:"p",href:"https://doc.rust-lang.org/stable/alloc/index.html"},"alloc")," crate, which is a rust builtin crate contains heap related structs."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},"// contracts/my-sudt/src/entry.rs\nfn main() -> Result<(), Error> {\n // load current script\n // check verification branch is owner mode or normal mode\n let script = load_script()?;\n let args: Bytes = script.args().unpack();\n\n // unpack the Script#args field\n let args: Vec = script.args().unpack();\n\n // return success if owner mode is true\n if check_owner_mode(&args)? {\n return Ok(());\n }\n\n // more verifications ...\n return Ok(());\n}\n")),(0,r.kt)("h3",{id:"check-inputs"},"Check inputs"),(0,r.kt)("p",null,"Now we should check the owner mode status by defining the ",(0,r.kt)("inlineCode",{parentName:"p"},"check_owner_mode")," function\uff1a"),(0,r.kt)("p",null,"We need to load every input's lock hash and compare it to the script's args. If we find an input's lock hash corresponds to the script's args, we are in owner mode; otherwise, we iterate all the inputs and finally got an ",(0,r.kt)("inlineCode",{parentName:"p"},"IndexOutOfBound")," error, which means we are in normal mode."),(0,r.kt)("p",null,"We use ",(0,r.kt)("a",{parentName:"p",href:"https://nervosnetwork.github.io/ckb-std/riscv64imac-unknown-none-elf/doc/ckb_std/high_level/fn.load_cell_lock_hash.html"},"load_cell_lock_hash")," to load cell's lock hash from CKB. The ",(0,r.kt)("inlineCode",{parentName:"p"},"Source::Input")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"i")," args denote we load ",(0,r.kt)("inlineCode",{parentName:"p"},"input")," from ",(0,r.kt)("inlineCode",{parentName:"p"},"i-th")," inputs."),(0,r.kt)("p",null,"The error ",(0,r.kt)("inlineCode",{parentName:"p"},"SysError::IndexOutOfBound")," represents that we request an index that does not exist, which means we cannot find a matched input cell, so we return ",(0,r.kt)("inlineCode",{parentName:"p"},"Ok(false)"),"."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},"use ckb_std::{\n high_level::{load_cell_lock_hash},\n ckb_constants::Source,\n};\n\nfn check_owner_mode(args: &Bytes) -> Result {\n // With owner lock script extracted, we will look through each input in the\n // current transaction to see if any unlocked cell uses owner lock.\n for i in 0.. {\n // check input's lock_hash with script args\n let lock_hash = match load_cell_lock_hash(\n i,\n Source::Input,\n ) {\n Ok(lock_hash) => lock_hash,\n Err(SysError::IndexOutOfBound) => return Ok(false),\n Err(err) => return Err(err.into()),\n };\n // invalid length of loaded data\n if args[..] == lock_hash[..] {\n return Ok(true);\n }\n }\n Ok(false)\n}\n")),(0,r.kt)("h3",{id:"load-inputs--outputs-udt-amount"},"Load inputs / outputs UDT amount"),(0,r.kt)("p",null,"If the owner mode is ",(0,r.kt)("inlineCode",{parentName:"p"},"false"),", we should continue the verification: check the total input SUDT amount is greater than or equals to the total output SUDT amount."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Define two methods:"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"collect_inputs_amount")," \uff1acollect total input SUDT amount"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"collect_outputs_amount")," \uff1acollect total output SUDT amount."))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Since we aim to read all SUDT inputs which type is the current script(SUDT), we can use ",(0,r.kt)("inlineCode",{parentName:"p"},"Source::GroupInput")," instead of ",(0,r.kt)("inlineCode",{parentName:"p"},"Source::Input"),".")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"Source::GroupInput")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"i")," means load the ",(0,r.kt)("inlineCode",{parentName:"p"},"i-th"),' input from the "input group". '))),(0,r.kt)("p",null,"Tips\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"By using ",(0,r.kt)("inlineCode",{parentName:"li"},"Source::GroupInput")," in the syscall, CKB verification engine will automatically group the inputs/outputs by ",(0,r.kt)("inlineCode",{parentName:"li"},"lock")," and ",(0,r.kt)("inlineCode",{parentName:"li"},"type")," script."),(0,r.kt)("li",{parentName:"ul"},"The data type of SUDT is ",(0,r.kt)("inlineCode",{parentName:"li"},"u128"),", which is 16 bytes so we use the 16 bytes buffer."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"i-th")," input of ",(0,r.kt)("inlineCode",{parentName:"li"},"Source::Input"),"(index of all inputs) may be or may not be the same cell of the ",(0,r.kt)("inlineCode",{parentName:"li"},"i-th")," input of ",(0,r.kt)("inlineCode",{parentName:"li"},"Source::GroupInput")," (index of inputs which lock/type is the current script).")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},"const UDT_LEN: usize = 16;\n\nfn collect_inputs_amount() -> Result {\n // let's loop through all input cells containing current UDTs,\n // and gather the sum of all input tokens.\n let mut inputs_amount: u128 = 0;\n let mut buf = [0u8; UDT_LEN];\n\n // u128 is 16 bytes\n for i in 0.. {\n let data = match load_cell_data(i, Source::GroupInput) {\n Ok(data) => data,\n Err(SysError::IndexOutOfBound) => break,\n Err(err) => return Err(err.into()),\n };\n\n if data.len() != UDT_LEN {\n return Err(Error::Encoding);\n }\n buf.copy_from_slice(&data);\n inputs_amount += u128::from_le_bytes(buf);\n }\n Ok(inputs_amount)\n}\n")),(0,r.kt)("p",null,"The ",(0,r.kt)("inlineCode",{parentName:"p"},"collect_outputs_amount")," function is similar, except we load data from outputs:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},"fn collect_outputs_amount() -> Result {\n // With the sum of all input UDT tokens gathered, let's now iterate through\n // output cells to grab the sum of all output UDT tokens.\n let mut outputs_amount: u128 = 0;\n let mut i = 0;\n\n // u128 is 16 bytes\n let mut buf = [0u8; UDT_LEN];\n for i in 0.. {\n let data = match load_cell_data(i, Source::GroupOutput) {\n Ok(data) => data,\n Err(SysError::IndexOutOfBound) => break,\n Err(err) => return Err(err.into()),\n };\n\n if data.len() != UDT_LEN {\n return Err(Error::Encoding);\n }\n buf.copy_from_slice(&data);\n outputs_amount += u128::from_le_bytes(buf);\n }\n Ok(outputs_amount)\n}\n")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Update the ",(0,r.kt)("inlineCode",{parentName:"li"},"error.rs"),' to add an error stands for "Not enough amount"')),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},'use ckb_std::error::SysError;\n\n/// Error\n#[repr(i8)]\npub enum Error {\n IndexOutOfBound = 1,\n ItemMissing,\n LengthNotEnough,\n Encoding,\n // Add customized errors here...\n Amount,\n}\n\nimpl From for Error {\n fn from(err: SysError) -> Self {\n use SysError::*;\n match err {\n IndexOutOfBound => Self::IndexOutOfBound,\n ItemMissing => Self::ItemMissing,\n LengthNotEnough(_) => Self::LengthNotEnough,\n Encoding => Self::Encoding,\n Unknown(err_code) => panic!("unexpected sys error {}", err_code),\n }\n }\n}\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Update the ",(0,r.kt)("inlineCode",{parentName:"li"},"main")," function in ",(0,r.kt)("inlineCode",{parentName:"li"},"entry.rs")," to check inputs / outputs UDT amount:")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},'pub fn main() -> Result<(), Error> {\n // remove below examples and write your code here\n\n let script = load_script()?;\n let args: Bytes = script.args().unpack();\n debug!("script args is {:?}", args);\n\n // return an error if args is invalid\n if args.is_empty() {\n return Err(Error::LengthNotEnough);\n }\n\n let tx_hash = load_tx_hash()?;\n debug!("tx hash is {:?}", tx_hash);\n\n let _buf: Vec<_> = vec![0u8; 32];\n\n // return success if owner mode is true\n if check_owner_mode(&args)? {\n return Ok(())\n }\n\n let inputs_amount = collect_inputs_amount()?;\n let outputs_amount = collect_outputs_amount()?;\n\n if inputs_amount < outputs_amount {\n return Err(Error::Amount);\n }\n // more verifications ...\n Ok(())\n}\n')),(0,r.kt)("h3",{id:"use-iterator-to-query-cells"},"Use Iterator to query cells"),(0,r.kt)("p",null,"In the previous code, we use ",(0,r.kt)("inlineCode",{parentName:"p"},"for")," loop to iterate inputs and outputs, since iteration over cells is a common pattern in CKB programming, ",(0,r.kt)("inlineCode",{parentName:"p"},"ckb-std")," provides a high-level interface ",(0,r.kt)("a",{parentName:"p",href:"https://nervosnetwork.github.io/ckb-std/riscv64imac-unknown-none-elf/doc/ckb_std/high_level/struct.QueryIter.html"},"QueryIter")," to handle it."),(0,r.kt)("p",null,"QueryIter needs two args, the first is a loading function, the seconds is ",(0,r.kt)("inlineCode",{parentName:"p"},"Source"),". This is an example to load all grouped inputs cells data ",(0,r.kt)("inlineCode",{parentName:"p"},"QueryIter::new(load_cell_data, Source::GroupInput)"),"."),(0,r.kt)("p",null,"Rewrite our functions in ",(0,r.kt)("inlineCode",{parentName:"p"},"entry.rs"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},"\n// import this\nuse ckb_std::high_level::QueryIter;\n\n// Other codes...\n\nfn check_owner_mode(args: &Bytes) -> Result {\n // With owner lock script extracted, we will look through each input in the\n // current transaction to see if any unlocked cell uses owner lock.\n let is_owner_mode = QueryIter::new(load_cell_lock_hash, Source::Input)\n .find(|lock_hash| args[..] == lock_hash[..]).is_some();\n Ok(is_owner_mode)\n}\n\nfn collect_inputs_amount() -> Result {\n // let's loop through all input cells containing current UDTs,\n // and gather the sum of all input tokens.\n let mut buf = [0u8; UDT_LEN];\n\n let udt_list = QueryIter::new(load_cell_data, Source::GroupInput)\n .map(|data|{\n if data.len() == UDT_LEN {\n buf.copy_from_slice(&data);\n // u128 is 16 bytes\n Ok(u128::from_le_bytes(buf))\n } else {\n Err(Error::Encoding)\n }\n }).collect::, Error>>()?;\n Ok(udt_list.into_iter().sum::())\n}\n\nfn collect_outputs_amount() -> Result {\n // With the sum of all input UDT tokens gathered, let's now iterate through\n // output cells to grab the sum of all output UDT tokens.\n let mut buf = [0u8; UDT_LEN];\n\n let udt_list = QueryIter::new(load_cell_data, Source::GroupOutput)\n .map(|data|{\n if data.len() == UDT_LEN {\n buf.copy_from_slice(&data);\n // u128 is 16 bytes\n Ok(u128::from_le_bytes(buf))\n } else {\n Err(Error::Encoding)\n }\n }).collect::, Error>>()?;\n Ok(udt_list.into_iter().sum::())\n}\n\n")),(0,r.kt)("p",null,"Now we have finished the SUDT script, you may refer to ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/jjyr/my-sudt/blob/master/contracts/my-sudt/src/main.rs"},"Full code of my-sudt")," to check the full script code. If you are interested, you may also check ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/ckb-miscellaneous-scripts/blob/master/c/simple_udt.c"},"the SUDT script written in C"),"."),(0,r.kt)("h3",{id:"build-the-project-1"},"Build the project"),(0,r.kt)("p",null,"Run ",(0,r.kt)("inlineCode",{parentName:"p"},"capsule build")," under the project directory to build the script.If no error occurred, we can find the script binary at ",(0,r.kt)("inlineCode",{parentName:"p"},"my-usdt/build/debug/my-sudt"),". "),(0,r.kt)("h2",{id:"testing"},"Testing"),(0,r.kt)("p",null,"We will use the ",(0,r.kt)("inlineCode",{parentName:"p"},"ckb-testtool")," crate to construct transactions and context for our testing."),(0,r.kt)("h3",{id:"check-the-default-tests"},"Check the default tests"),(0,r.kt)("p",null,"When create the project ",(0,r.kt)("inlineCode",{parentName:"p"},"my-sudt"),",",(0,r.kt)("inlineCode",{parentName:"p"},"capsule")," have generated the default tests.The default tests create mock cells and unlock them for testing."),(0,r.kt)("p",null,"Use ",(0,r.kt)("inlineCode",{parentName:"p"},"capsule build")," under the project directory to build the script,\nthen use ",(0,r.kt)("inlineCode",{parentName:"p"},"capsule test")," to run the default tests.We will find the error message:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"failures:\n\n---- tests::test_basic stdout ----\nthread 'tests::test_basic' panicked at 'pass verification: Error { kind: ValidationFailure(4)Script }', tests/src/tests.rs:52:5\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace\n\n\nfailures:\n tests::test_basic\n")),(0,r.kt)("p",null,"The error number ",(0,r.kt)("inlineCode",{parentName:"p"},"4")," in ",(0,r.kt)("inlineCode",{parentName:"p"},"Error { kind: ValidationFailure(4)")," refers to ",(0,r.kt)("inlineCode",{parentName:"p"},"Error::Encoding"),", which means the cell\u2019s data type is not ",(0,r.kt)("inlineCode",{parentName:"p"},"u128"),". "),(0,r.kt)("p",null,"Let\u2019s check the default tests code ",(0,r.kt)("inlineCode",{parentName:"p"},"tests/src/tests.rs")," to find out how to write the tests, then we can write new tests adapted ",(0,r.kt)("inlineCode",{parentName:"p"},"my-sudt"),"\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"In the beginning part, initialize the ",(0,r.kt)("inlineCode",{parentName:"li"},"Context")," which is a structure to simulate the chain environment. We can use ",(0,r.kt)("inlineCode",{parentName:"li"},"Context")," to deploy exists cells and mock block headers.",(0,r.kt)("inlineCode",{parentName:"li"},"deploy_contract")," will return the ",(0,r.kt)("inlineCode",{parentName:"li"},"out_point")," of the script.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},'// deploy contract\n let mut context = Context::default();\n let contract_bin: Bytes = Loader::default().load_binary("my-sudt");\n let contract_out_point = context.deploy_contract(contract_bin);\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Then ",(0,r.kt)("inlineCode",{parentName:"li"},"build_script")," is called with the script's ",(0,r.kt)("inlineCode",{parentName:"li"},"out_point")," , this function returns the ",(0,r.kt)("inlineCode",{parentName:"li"},"Script")," which uses our script as the code. ",(0,r.kt)("inlineCode",{parentName:"li"},"create_cell")," creates an existing cell in the context, which uses our script as the ",(0,r.kt)("inlineCode",{parentName:"li"},"lock_script"),".")),(0,r.kt)("p",null,(0,r.kt)("em",{parentName:"p"},"Please note the default tests assume the script is a lock_script, but in our case, ",(0,r.kt)("inlineCode",{parentName:"em"},"my-sudt")," is a type_script. We'll fix it later.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},'// prepare scripts\n let lock_script = context.build_script(&contract_out_point, Default::default()).expect("script");\n let lock_script_dep = CellDep::new_builder().out_point(contract_out_point).build();\n\n // prepare cells\n let input_out_point = context.create_cell(\n CellOutput::new_builder()\n .capacity(1000u64.pack())\n .lock(lock_script.clone())\n .build(),\n Bytes::new(),\n );\n let input = CellInput::new_builder()\n .previous_output(input_out_point)\n .build();\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"After that, build two outputs cells and a transaction structure.It is necessary to include ",(0,r.kt)("inlineCode",{parentName:"li"},"cell_deps")," field in the transaction which should contain all the referenced scripts, in this case, we can only refer to ",(0,r.kt)("inlineCode",{parentName:"li"},"my-sudt"),". ",(0,r.kt)("inlineCode",{parentName:"li"},"complete_tx")," also implement ",(0,r.kt)("inlineCode",{parentName:"li"},"cell_deps"),", while the field is already completed manually, this line is not necessary.")),(0,r.kt)("p",null,"Please note that the transaction's ",(0,r.kt)("inlineCode",{parentName:"p"},"outputs_data")," must have the same length with the ",(0,r.kt)("inlineCode",{parentName:"p"},"outputs"),", even the data is empty."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},"let outputs = vec![\n CellOutput::new_builder()\n .capacity(500u64.pack())\n .lock(lock_script.clone())\n .build(),\n CellOutput::new_builder()\n .capacity(500u64.pack())\n .lock(lock_script)\n .build(),\n ];\n\n let outputs_data = vec![Bytes::new(); 2];\n\n // build transaction\n let tx = TransactionBuilder::default()\n .input(input)\n .outputs(outputs)\n .outputs_data(outputs_data.pack())\n .cell_dep(lock_script_dep)\n .build();\n let tx = context.complete_tx(tx);\n")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Finally, verify the transaction:")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'// run\n context\n .verify_tx(&tx, MAX_CYCLES)\n .expect("pass verification");\n')),(0,r.kt)("h3",{id:"write-new-tests"},"Write new tests"),(0,r.kt)("p",null,"We should create mock SUDT cells and spend them for testing SUDT verification.\nAs ",(0,r.kt)("inlineCode",{parentName:"p"},"my-sudt")," script is a ",(0,r.kt)("inlineCode",{parentName:"p"},"type_script")," we need another script as ",(0,r.kt)("inlineCode",{parentName:"p"},"lock_script")," for mock cells, it is recommended to use ",(0,r.kt)("inlineCode",{parentName:"p"},"always success")," script returned ",(0,r.kt)("inlineCode",{parentName:"p"},"0"),". ",(0,r.kt)("inlineCode",{parentName:"p"},"always success")," is built-in in the ",(0,r.kt)("inlineCode",{parentName:"p"},"ckb-testtool"),"."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},"use ckb_testtool::{builtin::ALWAYS_SUCCESS, context::Context};\n\n // deploy always_success script\n let always_success_out_point = context.deploy_contract(ALWAYS_SUCCESS.clone());\n")),(0,r.kt)("p",null,"Before writing the code, let's think about our test cases:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Return success when input tokens equals to output tokens."),(0,r.kt)("li",{parentName:"ol"},"Return success when input tokens is greater than output tokens."),(0,r.kt)("li",{parentName:"ol"},"Return failure when input tokens is less than output tokens."),(0,r.kt)("li",{parentName:"ol"},"Return success when input tokens is less than output tokens with ",(0,r.kt)("inlineCode",{parentName:"li"},"owner mode")," activated.")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Define ",(0,r.kt)("inlineCode",{parentName:"p"},"build_test_context")," to build transactions. There are three args: "),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"The data type of ",(0,r.kt)("inlineCode",{parentName:"li"},"inputs_token")," and ",(0,r.kt)("inlineCode",{parentName:"li"},"outputs_token")," is ",(0,r.kt)("inlineCode",{parentName:"li"},"u128"),". The function can generate SUDT inputs cells and outputs cells according to the two args."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"is_owner_mode")," refers to the current transaction is in SUDT owner mode or normal mode."))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Deploy the SUDT and ",(0,r.kt)("inlineCode",{parentName:"p"},"always-success")," scripts."))),(0,r.kt)("p",null,"Please note that if ",(0,r.kt)("inlineCode",{parentName:"p"},"is_owner_mode")," is true, we will set ",(0,r.kt)("inlineCode",{parentName:"p"},"lock_script"),"'s ",(0,r.kt)("inlineCode",{parentName:"p"},"lock_hash")," as ",(0,r.kt)("inlineCode",{parentName:"p"},"owner script hash"),"; otherwise, we will set ",(0,r.kt)("inlineCode",{parentName:"p"},"[0u8; 32]")," which implies can't enter into owner mode."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},'fn build_test_context(\n inputs_token: Vec,\n outputs_token: Vec,\n is_owner_mode: bool,\n) -> (Context, TransactionView) {\n // deploy my-sudt script\n let mut context = Context::default();\n let sudt_bin: Bytes = Loader::default().load_binary("my-sudt");\n let sudt_out_point = context.deploy_contract(sudt_bin);\n // deploy always_success script\n let always_success_out_point = context.deploy_contract(ALWAYS_SUCCESS.clone());\n\n // build lock script\n let lock_script = context\n .build_script(&always_success_out_point, Default::default())\n .expect("script");\n let lock_script_dep = CellDep::new_builder()\n .out_point(always_success_out_point)\n .build();\n\n // build sudt script\n let sudt_script_args: Bytes = if is_owner_mode {\n // use always_success script hash as owner\'s lock\n let lock_hash: [u8; 32] = lock_script.calc_script_hash().unpack();\n lock_hash.to_vec().into()\n } else {\n // use zero hash as owner\'s lock which implies we can never enter owner mode\n [0u8; 32].to_vec().into()\n };\n\n let sudt_script = context\n .build_script(&sudt_out_point, sudt_script_args)\n .expect("script");\n let sudt_script_dep = CellDep::new_builder().out_point(sudt_out_point).build();\n\n //... more code below\n//}\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Build inputs and outputs according to the ",(0,r.kt)("inlineCode",{parentName:"li"},"inputs_token")," and ",(0,r.kt)("inlineCode",{parentName:"li"},"outputs_token")," ")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},"// ...\n // prepare inputs\n // assign 1000 Bytes to per input\n let input_ckb = Capacity::bytes(1000).unwrap().as_u64();\n let inputs = inputs_token.iter().map(|token| {\n let input_out_point = context.create_cell(\n CellOutput::new_builder()\n .capacity(input_ckb.pack())\n .lock(lock_script.clone())\n .type_(Some(sudt_script.clone()).pack())\n .build(),\n token.to_le_bytes().to_vec().into(),\n );\n let input = CellInput::new_builder()\n .previous_output(input_out_point)\n .build();\n input\n });\n\n // prepare outputs\n let output_ckb = input_ckb * inputs_token.len() as u64 / outputs_token.len() as u64;\n let outputs = outputs_token.iter().map(|_token| {\n CellOutput::new_builder()\n .capacity(output_ckb.pack())\n .lock(lock_script.clone())\n .type_(Some(sudt_script.clone()).pack())\n .build()\n });\n let outputs_data: Vec<_> = outputs_token\n .iter()\n .map(|token| Bytes::from(token.to_le_bytes().to_vec()))\n .collect();\n // ...\n")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Finally construct the transaction and return it with context.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"// build transaction\n let tx = TransactionBuilder::default()\n .inputs(inputs)\n .outputs(outputs)\n .outputs_data(outputs_data.pack())\n .cell_dep(lock_script_dep)\n .cell_dep(sudt_script_dep)\n .build();\n (context, tx)\n")),(0,r.kt)("p",null,"Now the helper function ",(0,r.kt)("inlineCode",{parentName:"p"},"build_test_context")," is finished, we can write our tests: "),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},'#[test]\nfn test_basic() {\n let (mut context, tx) = build_test_context(vec![1000], vec![400, 600], false);\n let tx = context.complete_tx(tx);\n\n // run\n context\n .verify_tx(&tx, MAX_CYCLES)\n .expect("pass verification");\n}\n\n#[test]\nfn test_destroy_udt() {\n let (mut context, tx) = build_test_context(vec![1000], vec![800, 100, 50], false);\n let tx = context.complete_tx(tx);\n\n // run\n context\n .verify_tx(&tx, MAX_CYCLES)\n .expect("pass verification");\n}\n\n#[test]\nfn test_create_sudt_without_owner_mode() {\n let (mut context, tx) = build_test_context(vec![1000], vec![1200], false);\n let tx = context.complete_tx(tx);\n\n // run\n let err = context.verify_tx(&tx, MAX_CYCLES).unwrap_err();\n assert_error_eq!(err, ScriptError::ValidationFailure(ERROR_AMOUNT));\n}\n\n#[test]\nfn test_create_sudt_with_owner_mode() {\n let (mut context, tx) = build_test_context(vec![1000], vec![1200], true);\n let tx = context.complete_tx(tx);\n\n // run\n context\n .verify_tx(&tx, MAX_CYCLES)\n .expect("pass verification");\n}\n')),(0,r.kt)("p",null,"You may refer to ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/jjyr/my-sudt/blob/master/tests/src/tests.rs"},"my-sudt tests")," for the full tests. Run ",(0,r.kt)("inlineCode",{parentName:"p"},"capsule test")," all tests will be passed."),(0,r.kt)("h2",{id:"deployment"},"Deployment"),(0,r.kt)("h3",{id:"run-a-dev-chain-and-ckb-cli-1"},"Run a dev chain and ckb-cli"),(0,r.kt)("p",null,"You should be running a dev chain and know about how to use ",(0,r.kt)("inlineCode",{parentName:"p"},"ckb-cli")," to send transactions before deployment. "),(0,r.kt)("h3",{id:"deploy"},"Deploy"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Update the deployment configurations"),(0,r.kt)("p",{parentName:"li"},"Open ",(0,r.kt)("inlineCode",{parentName:"p"},"deployment.toml")," :"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"cells")," describes which cells to be deployed."),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"name"),": Define the reference name used in the deployment configuration."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"enable_type_id")," : If it is set to ",(0,r.kt)("inlineCode",{parentName:"li"},"true")," means create a ",(0,r.kt)("inlineCode",{parentName:"li"},"type_id")," for the cell."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"location")," : Define the script binary path."))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"dep_groups")," describes which dep_groups to be created. Dep Group is a cell which bundles several cells as its members. When a dep group cell is used in ",(0,r.kt)("inlineCode",{parentName:"p"},"cell_deps"),", it has the same effect as adding all its members into ",(0,r.kt)("inlineCode",{parentName:"p"},"cell_deps"),". In our case, we don\u2019t need ",(0,r.kt)("inlineCode",{parentName:"p"},"dep_groups"),".")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"lock")," describes the ",(0,r.kt)("inlineCode",{parentName:"p"},"lock")," field of the new deployed cells.It is recommended to set ",(0,r.kt)("inlineCode",{parentName:"p"},"lock")," to the deployer's address(an address that you can unlock) in the dev chain and in the testnet, which is easier to update the script.")))),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Uncomment the configuration file and replace the cell name and location with ",(0,r.kt)("inlineCode",{parentName:"p"},"my-usdt"),"."))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'# [[cells]]\n# name = "my_cell"\n# enable_type_id = false\n# location = { file = "build/release/my_cell" }\n\n# # Dep group cells\n# [[dep_groups]]\n# name = "my_dep_group"\n# cells = [\n# "my_cell",\n# "secp256k1_data"\n# ]\n\n# # Replace with your own lock if you want to unlock deployed cells.\n# # The deployment code_hash is secp256k1 lock\n# [lock]\n# code_hash = "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8"\n# args = "0x0000000000000000000000000000000000000000"\n# hash_type = "type"\n')),(0,r.kt)("ol",{start:3},(0,r.kt)("li",{parentName:"ol"},"Build release version of the script")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"The release version of script doesn\u2019t include debug symbols which makes the size smaller.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"capsule build --release\n")),(0,r.kt)("ol",{start:4},(0,r.kt)("li",{parentName:"ol"},"Deploy the script ")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"capsule deploy --address \n")),(0,r.kt)("p",null,"If the ",(0,r.kt)("inlineCode",{parentName:"p"},"ckb-cli")," has been installed and dev-chain RPC is connectable, you will see the ",(0,r.kt)("inlineCode",{parentName:"p"},"deployment plan"),":"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"new_occupied_capacity")," and ",(0,r.kt)("inlineCode",{parentName:"li"},"total_occupied_capacity")," refer how much CKB to store cells and data."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"txs_fee_capacity")," refers how much CKB to pay the transaction fee.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"Deployment plan:\n---\nmigrated_capacity: 0.0 (CKB)\nnew_occupied_capacity: 33629.0 (CKB)\ntxs_fee_capacity: 0.0001 (CKB)\ntotal_occupied_capacity: 33629.0 (CKB)\nrecipe:\n cells:\n - name: my-sudt\n index: 0\n tx_hash: 0x8b496cb19018c475cdc4605ee9cef83cbfe578dce4f81f3367395906eba52c29\n occupied_capacity: 33629.0 (CKB)\n data_hash: 0xaa3d472025e6afefdf3f65c5f9beefd206b4283b30551baef83cbb4762e6d397\n type_id: ~\n dep_groups: []\nConfirm deployment? (Yes/No)\n")),(0,r.kt)("ol",{start:5},(0,r.kt)("li",{parentName:"ol"},"Type ",(0,r.kt)("inlineCode",{parentName:"li"},"yes")," or ",(0,r.kt)("inlineCode",{parentName:"li"},"y")," and input the password to unlock the account.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"send cell_tx 8b496cb19018c475cdc4605ee9cef83cbfe578dce4f81f3367395906eba52c29\nDeployment complete\n")),(0,r.kt)("p",null,"Now the SUDT script has been deployed, you can refer to this script by using ",(0,r.kt)("inlineCode",{parentName:"p"},"tx_hash: 0xaa3d472025e6afefdf3f65c5f9beefd206b4283b30551baef83cbb4762e6d397 index: 0")," as ",(0,r.kt)("inlineCode",{parentName:"p"},"out_point"),"(your ",(0,r.kt)("inlineCode",{parentName:"p"},"tx_hash")," should be another value)."),(0,r.kt)("h3",{id:"migration"},"Migration"),(0,r.kt)("p",null,"If you want to update the script code and deploy again, you can simply run this command again:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"capsule deploy --address ckt1qyq075y5ctzlgahu8pgsqxrqnglajgwa9zksmqdupd\n")),(0,r.kt)("p",null,"The new script will be automatically migrated which means destroy the old script cells and create new cells.\nYou will find ",(0,r.kt)("inlineCode",{parentName:"p"},"new_occupied_capacity")," is ",(0,r.kt)("inlineCode",{parentName:"p"},"0")," because ",(0,r.kt)("inlineCode",{parentName:"p"},"capacity")," is already covered by the old script cells.Please don\u2019t forget the transaction fee you still need to pay it."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"Deployment plan:\n---\nmigrated_capacity: 33629.0 (CKB)\nnew_occupied_capacity: 0.0 (CKB)\ntxs_fee_capacity: 0.0001 (CKB)\ntotal_occupied_capacity: 33629.0 (CKB)\nrecipe:\n cells:\n - name: my-sudt\n index: 0\n tx_hash: 0x10d508a0b44d3c1e02982f85a3e9b5d23d3961fddbf554d20abb4bf54f61950a\n occupied_capacity: 33629.0 (CKB)\n data_hash: 0xaa3d472025e6afefdf3f65c5f9beefd206b4283b30551baef83cbb4762e6d397\n type_id: ~\n dep_groups: []\nConfirm deployment? (Yes/No)\n")),(0,r.kt)("h2",{id:"next-steps"},"Next Steps"),(0,r.kt)("p",null,"This is the end of our journey into writing a SUDT script by Capsule. We have launched the ",(0,r.kt)("a",{parentName:"p",href:"https://www.nervos.org/grants/"},"Nervos Grants Program")," and ",(0,r.kt)("a",{parentName:"p",href:"https://medium.com/nervosnetwork/introducing-cklabs-the-nervos-incubator-3e5a2c443c7c"},"CKLabs")," to empower innovation and development and support the growth of a diverse and thriving ecosystem. We can't wait to see what you build next!"))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/98916265.fb9290c4.js b/assets/js/98916265.77c49894.js similarity index 99% rename from assets/js/98916265.fb9290c4.js rename to assets/js/98916265.77c49894.js index fbec5c748..74190967d 100644 --- a/assets/js/98916265.fb9290c4.js +++ b/assets/js/98916265.77c49894.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[9190],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>u});var a=n(7294);function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function r(e){for(var t=1;t=0||(s[n]=e[n]);return s}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var i=a.createContext({}),c=function(e){var t=a.useContext(i),n=t;return e&&(n="function"==typeof e?e(t):r(r({},t),e)),n},d=function(e){var t=c(e.components);return a.createElement(i.Provider,{value:t},e.children)},h={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},p=a.forwardRef((function(e,t){var n=e.components,s=e.mdxType,o=e.originalType,i=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),p=c(n),u=s,m=p["".concat(i,".").concat(u)]||p[u]||h[u]||o;return n?a.createElement(m,r(r({ref:t},d),{},{components:n})):a.createElement(m,r({ref:t},d))}));function u(e,t){var n=arguments,s=t&&t.mdxType;if("string"==typeof e||s){var o=n.length,r=new Array(o);r[0]=p;var l={};for(var i in t)hasOwnProperty.call(t,i)&&(l[i]=t[i]);l.originalType=e,l.mdxType="string"==typeof e?e:s,r[1]=l;for(var c=2;c{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>i,default:()=>u,frontMatter:()=>l,metadata:()=>c,toc:()=>h});var a=n(7462),s=n(3366),o=(n(7294),n(3905)),r=["components"],l={id:"cell-model",title:"Cell Model"},i=void 0,c={unversionedId:"basics/concepts/cell-model",id:"basics/concepts/cell-model",title:"Cell Model",description:"What is a Cell?",source:"@site/docs/basics/concepts/cell-model.md",sourceDirName:"basics/concepts",slug:"/basics/concepts/cell-model",permalink:"/docs/basics/concepts/cell-model",draft:!1,editUrl:"https://github.com/nervosnetwork/docs-new/tree/develop/website/docs/basics/concepts/cell-model.md",tags:[],version:"current",frontMatter:{id:"cell-model",title:"Cell Model"},sidebar:"Basics",previous:{title:"Nervos Blockchain",permalink:"/docs/basics/concepts/nervos-blockchain"},next:{title:"Consensus",permalink:"/docs/basics/concepts/consensus"}},d={},h=[{value:"What is a Cell?",id:"what-is-a-cell",level:2},{value:"What is the Cell Model?",id:"what-is-the-cell-model",level:2},{value:"First-Class Assets",id:"first-class-assets",level:2},{value:"Transaction Fees Paid by Anyone",id:"transaction-fees-paid-by-anyone",level:2},{value:"Scalability",id:"scalability",level:2},{value:"Further Reading",id:"further-reading",level:2}],p={toc:h};function u(e){var t=e.components,n=(0,s.Z)(e,r);return(0,o.kt)("wrapper",(0,a.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"what-is-a-cell"},"What is a Cell?"),(0,o.kt)("p",null,"Cell is the most basic structure for representing a single piece of data in Nervos. The data contained in a Cell can take many forms, including CKBytes, tokens, code in Javascript, or even serialized data like JSON strings. As there is no restriction on the type of data included, developers have full flexibility in their choices."),(0,o.kt)("p",null,"Each Cell contains a small program called a ",(0,o.kt)("strong",{parentName:"p"},"Lock Script")," that defines who has permission to use it. In general, the Lock Script defines one user as the owner of a Cell, it can also do more complex operations such as having multiple owners (multi-sig) or conditional uses of time-locking within particular time-frames."),(0,o.kt)("p",null,"A Cell can opt to include a second program, called a ",(0,o.kt)("strong",{parentName:"p"},"Type Script"),", to execute a set of rules on the usage of cell. As a result, developers are empowered to create complex smart contracts across a wide range of use cases, from CryptoKitties to tokens, DeFi, and everything in between."),(0,o.kt)("h2",{id:"what-is-the-cell-model"},"What is the Cell Model?"),(0,o.kt)("p",null,"The cell model defines how each cell in Nervos acts and interacts with each other, and the process must be followed for updating the data contained within the cells. People familiar with Bitcoin\u2019s UTXO model may notice the similarities, because the cell model was inspired by it."),(0,o.kt)("p",null,"Cells are immutable. This means no changes can be made once cells have been added to the blockchain. For any data update, the containing cell must undergo a process called ",(0,o.kt)("strong",{parentName:"p"},"consumption"),". When a Cell is ",(0,o.kt)("strong",{parentName:"p"},"consumed"),", data gets extracted and the cell gets destroyed. The data can be updated as needed while being extracted. A new cell with updated data will then be created and added to the blockchain."),(0,o.kt)("p",null,"Each Cell can be consumed only once. A non-consumed cell is known as a ",(0,o.kt)("strong",{parentName:"p"},"live cell"),". A consumed cell is known as a ",(0,o.kt)("strong",{parentName:"p"},"dead cell"),". Once dead, the cell can no longer be used."),(0,o.kt)("p",null,"Transactions serve to explain the changes in cell data. The transaction specifies a group of live cells to consume and a group of new cells to create by using the updated data. The network validates the transaction by executing all lock scripts and type scripts of each cell contained in the transaction. This ensures that all rules defined by the developers are being followed without any fraud."),(0,o.kt)("h2",{id:"first-class-assets"},"First-Class Assets"),(0,o.kt)("p",null,"Nervos\u2019 cell model treats all digital assets, such as CKBytes, tokens, and digital collectibles, as the exclusive property and responsibility of their owner. Assets must adhere to smart contract rules when being included in transactions, but the asset inherently belongs to the user instead of the smart contract. The difference is subtle but critical. "),(0,o.kt)("p",null,"When a user owns an asset, then only that user has permission to use the asset. Even the smart contract that defines the token has no permission to the asset. This means that even if an attacker found an exploit in the contract code, he or she would remain locked out of the asset because the asset is under user control. The impact of the attack is fully mitigated."),(0,o.kt)("p",null,"Having a defined ownership of the asset also clarifies who is responsible for its upkeep. As assets take up space on Nervos, there will be a small recurring upkeep fee, commonly known as ",(0,o.kt)("strong",{parentName:"p"},"state rent"),". User is the owner and is responsible as such, not the smart contract. More about state rent will be covered in the ",(0,o.kt)("a",{parentName:"p",href:"economics"},"Economics")," section."),(0,o.kt)("h2",{id:"transaction-fees-paid-by-anyone"},"Transaction Fees Paid by Anyone"),(0,o.kt)("p",null,"In most cases, people who send funds or execute smart contracts pay the transaction fees. However, to have a different party cover the associated fees can be beneficial in some cases."),(0,o.kt)("p",null,"A common scenario is the transfer of tokens from one party to another. The sender must own the tokens wanted to be transferred and sufficient CKBytes to cover the transaction cost. This creates an usability problem to users."),(0,o.kt)("p",null,"The flexibility of the cell model allows any party to pay the transaction fees. This can significantly improve the user experience since owning CKBytes is no longer an absolute requirement. The receiver or a third-party can pay the fee, easing the process for users."),(0,o.kt)("h2",{id:"scalability"},"Scalability"),(0,o.kt)("p",null,"The cell model separates the concepts of computation and validation for smart contract execution. Computation is the process of generating new data, which is done off-chain before the transaction gets sent to the network. Validation ensures that the data conforms to the rules set by the developers, which is done on-chain by full nodes after being received by the network. Offloading computation reduces the burden on full nodes and improves the total processing capacity of the network."),(0,o.kt)("p",null,"Smart contract execution is parallel in the cell model. Each transaction runs independently in its own virtual machine. And, multiple virtual machines run simultaneously rather than sequentially. This gives the cell model dramatic scaling improvements on modern computers - computers that increase the number of CPU cores with each generation."),(0,o.kt)("p",null,"Transactions are very flexible in the cell model. Multiple smart contract operations can often be batched into a single transaction, eliminating the need to construct multiple distinct transactions. This decreases the overhead involved in transactions and simplifies the process by reducing the required processing and transaction fees."),(0,o.kt)("p",null,"The unique structure of the cell model grants an inherent scalability. The conbination of these methods enables Nervos to achieve a greater level of smart contract scalability. A level that would not be possible in other ways."),(0,o.kt)("h2",{id:"further-reading"},"Further Reading"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"For more information, please see Nervos Network\u2019s blog post on the ",(0,o.kt)("a",{parentName:"li",href:"https://medium.com/nervosnetwork/https-medium-com-nervosnetwork-cell-model-7323fca57571"},"Cell Model"),".")))}u.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[9190],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>u});var a=n(7294);function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function r(e){for(var t=1;t=0||(s[n]=e[n]);return s}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var i=a.createContext({}),c=function(e){var t=a.useContext(i),n=t;return e&&(n="function"==typeof e?e(t):r(r({},t),e)),n},d=function(e){var t=c(e.components);return a.createElement(i.Provider,{value:t},e.children)},h={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},p=a.forwardRef((function(e,t){var n=e.components,s=e.mdxType,o=e.originalType,i=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),p=c(n),u=s,m=p["".concat(i,".").concat(u)]||p[u]||h[u]||o;return n?a.createElement(m,r(r({ref:t},d),{},{components:n})):a.createElement(m,r({ref:t},d))}));function u(e,t){var n=arguments,s=t&&t.mdxType;if("string"==typeof e||s){var o=n.length,r=new Array(o);r[0]=p;var l={};for(var i in t)hasOwnProperty.call(t,i)&&(l[i]=t[i]);l.originalType=e,l.mdxType="string"==typeof e?e:s,r[1]=l;for(var c=2;c{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>i,default:()=>u,frontMatter:()=>l,metadata:()=>c,toc:()=>h});var a=n(7462),s=n(3366),o=(n(7294),n(3905)),r=["components"],l={id:"cell-model",title:"Cell Model"},i=void 0,c={unversionedId:"basics/concepts/cell-model",id:"basics/concepts/cell-model",title:"Cell Model",description:"What is a Cell?",source:"@site/docs/basics/concepts/cell-model.md",sourceDirName:"basics/concepts",slug:"/basics/concepts/cell-model",permalink:"/docs/basics/concepts/cell-model",draft:!1,editUrl:"https://github.com/nervosnetwork/docs-new/tree/develop/website/docs/basics/concepts/cell-model.md",tags:[],version:"current",frontMatter:{id:"cell-model",title:"Cell Model"},sidebar:"Basics",previous:{title:"Nervos Blockchain",permalink:"/docs/basics/concepts/nervos-blockchain"},next:{title:"Consensus",permalink:"/docs/basics/concepts/consensus"}},d={},h=[{value:"What is a Cell?",id:"what-is-a-cell",level:2},{value:"What is the Cell Model?",id:"what-is-the-cell-model",level:2},{value:"First-Class Assets",id:"first-class-assets",level:2},{value:"Transaction Fees Paid by Anyone",id:"transaction-fees-paid-by-anyone",level:2},{value:"Scalability",id:"scalability",level:2},{value:"Further Reading",id:"further-reading",level:2}],p={toc:h};function u(e){var t=e.components,n=(0,s.Z)(e,r);return(0,o.kt)("wrapper",(0,a.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"what-is-a-cell"},"What is a Cell?"),(0,o.kt)("p",null,"Cell is the most basic structure for representing a single piece of data in Nervos. The data contained in a Cell can take many forms, including CKBytes, tokens, code in Javascript, or even serialized data like JSON strings. As there is no restriction on the type of data included, developers have full flexibility in their choices."),(0,o.kt)("p",null,"Each Cell contains a small program called a ",(0,o.kt)("strong",{parentName:"p"},"Lock Script")," that defines who has permission to use it. In general, the Lock Script defines one user as the owner of a Cell, it can also do more complex operations such as having multiple owners (multi-sig) or conditional uses of time-locking within particular time-frames."),(0,o.kt)("p",null,"A Cell can opt to include a second program, called a ",(0,o.kt)("strong",{parentName:"p"},"Type Script"),", to execute a set of rules on the usage of cell. As a result, developers are empowered to create complex smart contracts across a wide range of use cases, from CryptoKitties to tokens, DeFi, and everything in between."),(0,o.kt)("h2",{id:"what-is-the-cell-model"},"What is the Cell Model?"),(0,o.kt)("p",null,"The cell model defines how each cell in Nervos acts and interacts with each other, and the process must be followed for updating the data contained within the cells. People familiar with Bitcoin\u2019s UTXO model may notice the similarities, because the cell model was inspired by it."),(0,o.kt)("p",null,"Cells are immutable. This means no changes can be made once cells have been added to the blockchain. For any data update, the containing cell must undergo a process called ",(0,o.kt)("strong",{parentName:"p"},"consumption"),". When a Cell is ",(0,o.kt)("strong",{parentName:"p"},"consumed"),", data gets extracted and the cell gets destroyed. The data can be updated as needed while being extracted. A new cell with updated data will then be created and added to the blockchain."),(0,o.kt)("p",null,"Each Cell can be consumed only once. A non-consumed cell is known as a ",(0,o.kt)("strong",{parentName:"p"},"live cell"),". A consumed cell is known as a ",(0,o.kt)("strong",{parentName:"p"},"dead cell"),". Once dead, the cell can no longer be used."),(0,o.kt)("p",null,"Transactions serve to explain the changes in cell data. The transaction specifies a group of live cells to consume and a group of new cells to create by using the updated data. The network validates the transaction by executing all lock scripts and type scripts of each cell contained in the transaction. This ensures that all rules defined by the developers are being followed without any fraud."),(0,o.kt)("h2",{id:"first-class-assets"},"First-Class Assets"),(0,o.kt)("p",null,"Nervos\u2019 cell model treats all digital assets, such as CKBytes, tokens, and digital collectibles, as the exclusive property and responsibility of their owner. Assets must adhere to smart contract rules when being included in transactions, but the asset inherently belongs to the user instead of the smart contract. The difference is subtle but critical. "),(0,o.kt)("p",null,"When a user owns an asset, then only that user has permission to use the asset. Even the smart contract that defines the token has no permission to the asset. This means that even if an attacker found an exploit in the contract code, he or she would remain locked out of the asset because the asset is under user control. The impact of the attack is fully mitigated."),(0,o.kt)("p",null,"Having a defined ownership of the asset also clarifies who is responsible for its upkeep. As assets take up space on Nervos, there will be a small recurring upkeep fee, commonly known as ",(0,o.kt)("strong",{parentName:"p"},"state rent"),". User is the owner and is responsible as such, not the smart contract. More about state rent will be covered in the ",(0,o.kt)("a",{parentName:"p",href:"economics"},"Economics")," section."),(0,o.kt)("h2",{id:"transaction-fees-paid-by-anyone"},"Transaction Fees Paid by Anyone"),(0,o.kt)("p",null,"In most cases, people who send funds or execute smart contracts pay the transaction fees. However, to have a different party cover the associated fees can be beneficial in some cases."),(0,o.kt)("p",null,"A common scenario is the transfer of tokens from one party to another. The sender must own the tokens wanted to be transferred and sufficient CKBytes to cover the transaction cost. This creates an usability problem to users."),(0,o.kt)("p",null,"The flexibility of the cell model allows any party to pay the transaction fees. This can significantly improve the user experience since owning CKBytes is no longer an absolute requirement. The receiver or a third-party can pay the fee, easing the process for users."),(0,o.kt)("h2",{id:"scalability"},"Scalability"),(0,o.kt)("p",null,"The cell model separates the concepts of computation and validation for smart contract execution. Computation is the process of generating new data, which is done off-chain before the transaction gets sent to the network. Validation ensures that the data conforms to the rules set by the developers, which is done on-chain by full nodes after being received by the network. Offloading computation reduces the burden on full nodes and improves the total processing capacity of the network."),(0,o.kt)("p",null,"Smart contract execution is parallel in the cell model. Each transaction runs independently in its own virtual machine. And, multiple virtual machines run simultaneously rather than sequentially. This gives the cell model dramatic scaling improvements on modern computers - computers that increase the number of CPU cores with each generation."),(0,o.kt)("p",null,"Transactions are very flexible in the cell model. Multiple smart contract operations can often be batched into a single transaction, eliminating the need to construct multiple distinct transactions. This decreases the overhead involved in transactions and simplifies the process by reducing the required processing and transaction fees."),(0,o.kt)("p",null,"The unique structure of the cell model grants an inherent scalability. The combination of these methods enables Nervos to achieve a greater level of smart contract scalability. A level that would not be possible in other ways."),(0,o.kt)("h2",{id:"further-reading"},"Further Reading"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"For more information, please see Nervos Network\u2019s blog post on the ",(0,o.kt)("a",{parentName:"li",href:"https://medium.com/nervosnetwork/https-medium-com-nervosnetwork-cell-model-7323fca57571"},"Cell Model"),".")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/c4f5d8e4.1547c3df.js b/assets/js/c4f5d8e4.9f338d1a.js similarity index 85% rename from assets/js/c4f5d8e4.1547c3df.js rename to assets/js/c4f5d8e4.9f338d1a.js index 2e8876ba4..5715a9bc5 100644 --- a/assets/js/c4f5d8e4.1547c3df.js +++ b/assets/js/c4f5d8e4.9f338d1a.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[4195],{2841:(e,t,r)=>{r.r(t),r.d(t,{default:()=>i});var n=r(4578),a=r(7294),c=r(3659),o=function(e){function t(){return e.apply(this,arguments)||this}return(0,n.Z)(t,e),t.prototype.render=function(){var e=this.props.config,t=e.baseUrl,r=function(e){return a.createElement("div",{className:"coverLogo"},a.createElement("img",{src:e.img_src,alt:"Nervos Logo"}))},n=function(e){return a.createElement("h2",{className:"projectTitle"},e.title)},c=function(e){return a.createElement("div",{id:e.id,className:"card"},a.createElement("div",{className:"cardHeader"},a.createElement("h2",null,e.title)),a.createElement("div",{className:"cardBody"},e.body),a.createElement("div",{className:"cardFooter"},e.footer))};return a.createElement("div",null,a.createElement("div",{className:"homeContainer"},a.createElement("div",{className:"homeSplashFade"},a.createElement("div",{className:"wrapper homeWrapper"},a.createElement(r,{img_src:t+"img/cover_logo.png"}),a.createElement("div",{className:"projectDescription"},a.createElement(n,{title:e.title}),a.createElement("p",null,"Nervos CKB is a public permissionless blockchain and the layer 1 of Nervos."),a.createElement("p",null,"CKB generates trust and extends this trust to upper layers, making Nervos a trust network. It's also the value store of the Nervos network, providing public, secure and censorship-resistant custody services for assets, identities and other common knowledge created in the network. We will also vigorously develop the developer community and aim to offer blockchain developers exciting new capabilities."),a.createElement("p",null,"If you run into an issue on our documentation website you can contact us on ",a.createElement("a",{href:"https://talk.nervos.org/"},"Nervos talk")," or ",a.createElement("a",{href:"https://discord.gg/AqGTUE9"},"Discord"),"."))))),a.createElement("div",{className:"mainContainer cards"},a.createElement("div",{className:"cardRow"},a.createElement(c,{id:"getting-started",title:"Getting Started",body:a.createElement("p",null,"If you are a beginner who just started experimenting with CKB for the first time, ",a.createElement("a",{href:"docs/basics/introduction"},"Basics")," will help you get to know CKB, and get the chain running. ",a.createElement("a",{href:"docs/reference/introduction"},"Reference")," contains advanced concepts that might also be of interest."),footer:a.createElement("p",null,a.createElement("a",{href:"docs/basics/introduction"},a.createElement("img",{src:"img/doc_basic.png",alt:"basics"})," Basics"),a.createElement("a",{href:"docs/reference/introduction"},a.createElement("img",{src:"img/doc_reference.png",alt:"reference"})," Reference"))}),a.createElement(c,{id:"wallet-integration",title:"Exchange & Wallet Integration",body:a.createElement("p",null,a.createElement("a",{href:"docs/integrate/introduction"},"Integrate")," section provides first hand experience gained in integrating CKB into existing exchanges and wallets. ",a.createElement("a",{href:"docs/reference/introduction"},"Reference")," might also help you learn more about CKB specific behavior."),footer:a.createElement("p",null,a.createElement("a",{href:"docs/integrate/introduction"},a.createElement("img",{src:"img/doc_integrate.png",alt:"integrate"})," Integrate"),a.createElement("a",{href:"docs/reference/introduction"},a.createElement("img",{src:"img/doc_reference.png",alt:"reference"})," Reference"))})),a.createElement("div",{className:"cardRow"},a.createElement(c,{id:"building-dapps",title:"Building Dapps",body:a.createElement("p",null,"If you are developers who want to build dapps on CKB, ",a.createElement("a",{href:"docs/labs/introduction"},"Labs")," provides hands-on tutorials which you can follow. ",a.createElement("a",{href:"docs/reference/introduction"},"Reference")," also contains explanations for CKB concepts and specific blockchain behaviors."),footer:a.createElement("p",null,a.createElement("a",{href:"docs/labs/introduction"},a.createElement("img",{src:"img/doc_basic.png",alt:"basics"})," Labs"),a.createElement("a",{href:"docs/reference/introduction"},a.createElement("img",{src:"img/doc_reference.png",alt:"reference"})," Reference"))}),a.createElement(c,{id:"clarification",title:"Clarification",body:a.createElement("p",null,"As dapp developers, you might need clarifications on specific part from time to time, ",a.createElement("a",{href:"docs/reference/introduction"},"Reference")," will be your best friend on this topc."),footer:a.createElement("p",null,a.createElement("a",{href:"docs/reference/introduction"},a.createElement("img",{src:"img/doc_reference.png",alt:"reference"})," Reference"))}),a.createElement(c,{id:"random-browsing",title:"Random Browsing",body:a.createElement("p",null,"For users who are just browing to get a glimpse of CKB's design, or developers who want to learn one or two tips, ",a.createElement("a",{href:"docs/essays/introduction"},"Essays")," will provide all sorts of articles explaining CKB related topics. ",a.createElement("a",{href:"docs/reference/introduction"},"Reference")," might also be of interest since it aims to describe specific constructs in CKB."),footer:a.createElement("p",null,a.createElement("a",{href:"docs/essays/introduction"},a.createElement("img",{src:"img/doc_essay.png",alt:"essays"}),"Essays"),a.createElement("a",{href:"docs/reference/introduction"},a.createElement("img",{src:"img/doc_reference.png",alt:"reference"}),"Reference"))}))))},t}(a.Component);const i=function(e){return a.createElement(c.Z,null,a.createElement(o,e))}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[4195],{2841:(e,t,r)=>{r.r(t),r.d(t,{default:()=>i});var n=r(4578),a=r(7294),c=r(3659),o=function(e){function t(){return e.apply(this,arguments)||this}return(0,n.Z)(t,e),t.prototype.render=function(){var e=this.props.config,t=e.baseUrl,r=function(e){return a.createElement("div",{className:"coverLogo"},a.createElement("img",{src:e.img_src,alt:"Nervos Logo"}))},n=function(e){return a.createElement("h2",{className:"projectTitle"},e.title)},c=function(e){return a.createElement("div",{id:e.id,className:"card"},a.createElement("div",{className:"cardHeader"},a.createElement("h2",null,e.title)),a.createElement("div",{className:"cardBody"},e.body),a.createElement("div",{className:"cardFooter"},e.footer))};return a.createElement("div",null,a.createElement("div",{className:"homeContainer"},a.createElement("div",{className:"homeSplashFade"},a.createElement("div",{className:"wrapper homeWrapper"},a.createElement(r,{img_src:t+"img/cover_logo.png"}),a.createElement("div",{className:"projectDescription"},a.createElement(n,{title:e.title}),a.createElement("p",null,"Nervos CKB is a public permissionless blockchain and the layer 1 of Nervos."),a.createElement("p",null,"CKB generates trust and extends this trust to upper layers, making Nervos a trust network. It's also the value store of the Nervos network, providing public, secure and censorship-resistant custody services for assets, identities and other common knowledge created in the network. We will also vigorously develop the developer community and aim to offer blockchain developers exciting new capabilities."),a.createElement("p",null,"If you run into an issue on our documentation website you can contact us on ",a.createElement("a",{href:"https://talk.nervos.org/"},"Nervos talk")," or ",a.createElement("a",{href:"https://discord.gg/AqGTUE9"},"Discord"),"."))))),a.createElement("div",{className:"mainContainer cards"},a.createElement("div",{className:"cardRow"},a.createElement(c,{id:"getting-started",title:"Getting Started",body:a.createElement("p",null,"If you are a beginner who just started experimenting with CKB for the first time, ",a.createElement("a",{href:"docs/basics/introduction"},"Basics")," will help you get to know CKB, and get the chain running. ",a.createElement("a",{href:"docs/reference/introduction"},"Reference")," contains advanced concepts that might also be of interest."),footer:a.createElement("p",null,a.createElement("a",{href:"docs/basics/introduction"},a.createElement("img",{src:"img/doc_basic.png",alt:"basics"})," Basics"),a.createElement("a",{href:"docs/reference/introduction"},a.createElement("img",{src:"img/doc_reference.png",alt:"reference"})," Reference"))}),a.createElement(c,{id:"wallet-integration",title:"Exchange & Wallet Integration",body:a.createElement("p",null,a.createElement("a",{href:"docs/integrate/introduction"},"Integrate")," section provides first hand experience gained in integrating CKB into existing exchanges and wallets. ",a.createElement("a",{href:"docs/reference/introduction"},"Reference")," might also help you learn more about CKB specific behavior."),footer:a.createElement("p",null,a.createElement("a",{href:"docs/integrate/introduction"},a.createElement("img",{src:"img/doc_integrate.png",alt:"integrate"})," Integrate"),a.createElement("a",{href:"docs/reference/introduction"},a.createElement("img",{src:"img/doc_reference.png",alt:"reference"})," Reference"))})),a.createElement("div",{className:"cardRow"},a.createElement(c,{id:"building-dapps",title:"Building Dapps",body:a.createElement("p",null,"If you are developers who want to build dapps on CKB, ",a.createElement("a",{href:"docs/labs/introduction"},"Labs")," provides hands-on tutorials which you can follow. ",a.createElement("a",{href:"docs/reference/introduction"},"Reference")," also contains explanations for CKB concepts and specific blockchain behaviors."),footer:a.createElement("p",null,a.createElement("a",{href:"docs/labs/introduction"},a.createElement("img",{src:"img/doc_basic.png",alt:"basics"})," Labs"),a.createElement("a",{href:"docs/reference/introduction"},a.createElement("img",{src:"img/doc_reference.png",alt:"reference"})," Reference"))}),a.createElement(c,{id:"clarification",title:"Clarification",body:a.createElement("p",null,"As dapp developers, you might need clarifications on specific part from time to time, ",a.createElement("a",{href:"docs/reference/introduction"},"Reference")," will be your best friend on this topc."),footer:a.createElement("p",null,a.createElement("a",{href:"docs/reference/introduction"},a.createElement("img",{src:"img/doc_reference.png",alt:"reference"})," Reference"))}),a.createElement(c,{id:"random-browsing",title:"Random Browsing",body:a.createElement("p",null,"For users who are just browsing to get a glimpse of CKB's design, or developers who want to learn one or two tips, ",a.createElement("a",{href:"docs/essays/introduction"},"Essays")," will provide all sorts of articles explaining CKB related topics. ",a.createElement("a",{href:"docs/reference/introduction"},"Reference")," might also be of interest since it aims to describe specific constructs in CKB."),footer:a.createElement("p",null,a.createElement("a",{href:"docs/essays/introduction"},a.createElement("img",{src:"img/doc_essay.png",alt:"essays"}),"Essays"),a.createElement("a",{href:"docs/reference/introduction"},a.createElement("img",{src:"img/doc_reference.png",alt:"reference"}),"Reference"))}))))},t}(a.Component);const i=function(e){return a.createElement(c.Z,null,a.createElement(o,e))}}}]); \ No newline at end of file diff --git a/assets/js/e9813fd7.b7353df6.js b/assets/js/e9813fd7.3a0b3c40.js similarity index 68% rename from assets/js/e9813fd7.b7353df6.js rename to assets/js/e9813fd7.3a0b3c40.js index 6e085f422..8caa1a1be 100644 --- a/assets/js/e9813fd7.b7353df6.js +++ b/assets/js/e9813fd7.3a0b3c40.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[9591],{3905:(e,t,a)=>{a.d(t,{Zo:()=>d,kt:()=>h});var n=a(7294);function l(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function r(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function i(e){for(var t=1;t=0||(l[a]=e[a]);return l}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(l[a]=e[a])}return l}var s=n.createContext({}),c=function(e){var t=n.useContext(s),a=t;return e&&(a="function"==typeof e?e(t):i(i({},t),e)),a},d=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var a=e.components,l=e.mdxType,r=e.originalType,s=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),u=c(a),h=l,m=u["".concat(s,".").concat(h)]||u[h]||p[h]||r;return a?n.createElement(m,i(i({ref:t},d),{},{components:a})):n.createElement(m,i({ref:t},d))}));function h(e,t){var a=arguments,l=t&&t.mdxType;if("string"==typeof e||l){var r=a.length,i=new Array(r);i[0]=u;var o={};for(var s in t)hasOwnProperty.call(t,s)&&(o[s]=t[s]);o.originalType=e,o.mdxType="string"==typeof e?e:l,i[1]=o;for(var c=2;c{a.r(t),a.d(t,{assets:()=>d,contentTitle:()=>s,default:()=>h,frontMatter:()=>o,metadata:()=>c,toc:()=>p});var n=a(7462),l=a(3366),r=(a(7294),a(3905)),i=["components"],o={id:"cell",title:"Cell"},s=void 0,c={unversionedId:"reference/cell",id:"reference/cell",title:"Cell",description:"Nervos CKB (Common Knowledge Base) is a layer 1 blockchain, a decentralized and secure layer that provides common knowledge custody for the network. Common knowledge refers to states that are agreed via global consensus.",source:"@site/docs/reference/cell.md",sourceDirName:"reference",slug:"/reference/cell",permalink:"/docs/reference/cell",draft:!1,editUrl:"https://github.com/nervosnetwork/docs-new/tree/develop/website/docs/reference/cell.md",tags:[],version:"current",frontMatter:{id:"cell",title:"Cell"},sidebar:"Reference",previous:{title:"Introduction",permalink:"/docs/reference/introduction"},next:{title:"Script",permalink:"/docs/reference/script"}},d={},p=[{value:"Data Structure",id:"data-structure",level:2},{value:"Cell data",id:"cell-data",level:3},{value:"Cell information size calculation",id:"cell-information-size-calculation",level:3},{value:"Live Cell",id:"live-cell",level:2},{value:"Index-Query-Assemble Pattern",id:"index-query-assemble-pattern",level:2},{value:"Tools",id:"tools",level:3},{value:"lumos",id:"lumos",level:4},{value:"ckb-indexer",id:"ckb-indexer",level:4},{value:"perkins-tent",id:"perkins-tent",level:4}],u={toc:p};function h(e){var t=e.components,a=(0,l.Z)(e,i);return(0,r.kt)("wrapper",(0,n.Z)({},u,a,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("p",null,"Nervos CKB (Common Knowledge Base) is a layer 1 blockchain, a decentralized and secure layer that provides common knowledge custody for the network. Common knowledge refers to ",(0,r.kt)("strong",{parentName:"p"},"states")," that are agreed via global consensus."),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Cells are the primary state units")," in CKB and assets owned by users. They must follow associated validation rules specified by scripts. In Bitcoin, money is the typical common knowledge stored in the Bitcoin ledger. Nervos CKB, however, takes one step further to store arbitrary common knowledge. We starts from Bitcoin's general architecture, and creates the ",(0,r.kt)("a",{parentName:"p",href:"https://medium.com/nervosnetwork/https-medium-com-nervosnetwork-cell-model-7323fca57571"},"Cell Model")," by generalizing from the UTXO model, while at the same time retaining the consistency and simplicity of Bitcoin."),(0,r.kt)("h2",{id:"data-structure"},"Data Structure"),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Example:")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'{\n "capacity": "0x19995d0ccf",\n "lock": {\n "code_hash": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8",\n "args": "0x0a486fb8f6fe60f76f001d6372da41be91172259",\n "hash_type": "type"\n },\n "type": null\n}\n')),(0,r.kt)("p",null,"A Cell has three fields\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"capacity"),": Capacity serves 2 purposes: on one hand, it represents the amount of CKB tokens stored in the cell, on the other hand, it also sets the limit on how much information the cell can store. The basic unit for capacity is ",(0,r.kt)("inlineCode",{parentName:"li"},"shannon"),", a bigger unit ",(0,r.kt)("inlineCode",{parentName:"li"},"CKByte"),", or just ",(0,r.kt)("inlineCode",{parentName:"li"},"CKB")," is also used. 1 CKB equals ",(0,r.kt)("inlineCode",{parentName:"li"},"10**8")," shannons, 1 CKB also means the cell can store 1 byte of information. See below for how to calculate the total information size of a cell."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"lock script"),": A script used to guard the cell: when the specified cell is used as an input cell in a transaction, the lock script included in a cell will be executed. The transaction will be rejected when the lock script fails in execution. One typical use case for lock script, is to represent the ownership of a cell, meaning a signature verification phase is usually included in the cell."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"type script"),": A script used to validate cell structure. The type script of a cell will be executed both when the cell is included as an input cell, as well as when the cell is created as an output cell. Due to this nature, type script is typically used to validate dapp logic, such as creating UDTs.")),(0,r.kt)("p",null,"Each cell must have a lock script, while type script is optional, and can be omitted. Please refer to ",(0,r.kt)("a",{parentName:"p",href:"/docs/reference/script"},"Script")," for the actual format of lock and type script."),(0,r.kt)("h3",{id:"cell-data"},"Cell data"),(0,r.kt)("p",null,"In addition to the above fields, each cell also contains a cell data field. Cell data is just a series of unformatted binary data. Depending on each dapp, anything could be stored in the cell data part:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Script code as explained in ",(0,r.kt)("a",{parentName:"li",href:"/docs/reference/script"},"Script"),"."),(0,r.kt)("li",{parentName:"ul"},"Token amount for User Defined Token cells."),(0,r.kt)("li",{parentName:"ul"},"Latest game stats for an on-chain fantasy game.")),(0,r.kt)("p",null,"For future potential, cell data is not stored directly in a cell. It is kept directly in the ",(0,r.kt)("a",{parentName:"p",href:"/docs/reference/transaction#data-structure"},"Transaction"),". You might find a field named ",(0,r.kt)("inlineCode",{parentName:"p"},"outputs_data")," in each transaction. This array should have the same length with ",(0,r.kt)("inlineCode",{parentName:"p"},"outputs"),". At each index location, the corresponding cell data could be located for each created output cell in the transaction. Conceptually, we still consider cell data as part of each output cell."),(0,r.kt)("h3",{id:"cell-information-size-calculation"},"Cell information size calculation"),(0,r.kt)("p",null,"Each cell on Nervos CKB, must not have a lower capacity than the total size of information stored in the cell. The size of information for a cell is calculated as the sum of the following fields:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"8 bytes for cell capacity field."),(0,r.kt)("li",{parentName:"ol"},"32 bytes for code hash in lock script."),(0,r.kt)("li",{parentName:"ol"},"1 byte for hash type in lock script."),(0,r.kt)("li",{parentName:"ol"},"Actual bytes of args field in lock script."),(0,r.kt)("li",{parentName:"ol"},"If type script is present, 32 bytes for code hash in type script."),(0,r.kt)("li",{parentName:"ol"},"If type script is present, 1 byte for hash type in type script."),(0,r.kt)("li",{parentName:"ol"},"If type script is present, actual bytes of args field in type script."),(0,r.kt)("li",{parentName:"ol"},"Actual bytes of cell data.")),(0,r.kt)("p",null,"By summing up all the above fields, we get the total size of information a cell needs. Cell capacity, when measured in ",(0,r.kt)("inlineCode",{parentName:"p"},"CKBytes"),", respresents the maximum size of information that can be held, meaning a valid cell must ensure the CKBytes stored in capacity equal or is larger than the total size of information."),(0,r.kt)("h2",{id:"live-cell"},"Live Cell"),(0,r.kt)("p",null,"Live cell refers to an unspent cell in CKB. It is similar to the concept of ",(0,r.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Unspent_transaction_output"},"UTXO")," in Bitcoin's terminology. The full set of live cells in CKB, is consider the full state of CKB at that particular point. Any transaction on CKB would consume some cells that were live cells just at the point before it is committed, and created new cells that are considered live cells after it is committed."),(0,r.kt)("h2",{id:"index-query-assemble-pattern"},"Index-Query-Assemble Pattern"),(0,r.kt)("p",null,"Nervos CKB is designed based on the concept of cells. A transaction, at its core, really just consumes some cells, and create another set of cells. As a result, the ability to locate and transform cells, plays a critical role in building any CKB dapps, which leads to the ",(0,r.kt)("inlineCode",{parentName:"p"},"index-query-assemble")," pattern:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Index: when a new block is committed to CKB, a dapp should be able to index relevant cells to its own storage for latter usage."),(0,r.kt)("li",{parentName:"ul"},"Query: when a user action is requested, cells satisfying certain criteria will be queried from the dapp storage."),(0,r.kt)("li",{parentName:"ul"},"Assemble: based on queried cells, a new transaction would be assembled to fulfill user requests.")),(0,r.kt)("p",null,"We believe all CKB dapps can be decomposed into individual actions following this pattern. Here are some examples:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"In a normal CKB wallet, cells should be indexed based on lock scripts. A transfer action would first query cells from the sender, and assemble a transaction which transfer CKBytes to the receiver."),(0,r.kt)("li",{parentName:"ul"},"A NervosDAO manager might index only cells related to NervosDAO. A user might then pick a NervosDAO cell and perform withdraw action, even though there is only one cell related, we can still view it as cells queried from the NervosDAO manager, and a transaction will also be assembled which performs the actual withdraw action."),(0,r.kt)("li",{parentName:"ul"},"A state based dapp might choose to store the latest state in a CKB cell. The dapp will still need to track the latest live cell, which can also be viewed as an indexing operation, any action on the state will result in the latest live cell being queried, assembled into a transaction, then accepted by CKB with a new output cell containing the updated state.")),(0,r.kt)("h3",{id:"tools"},"Tools"),(0,r.kt)("p",null,"Indexing & querying plays a central role in any CKB dapps. In most cases, you don't have to build an indexer from scratch. There are several existing tools one can leverage to fulfill the job:"),(0,r.kt)("h4",{id:"lumos"},"lumos"),(0,r.kt)("p",null,"Our dapp framework, ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/lumos"},"lumos")," already contains a ready-to-use indexer. When you are using lumos, it is very likely the indexer is already setup for you to use. Please refer to our labs for how to setup lumos."),(0,r.kt)("h4",{id:"ckb-indexer"},"ckb-indexer"),(0,r.kt)("p",null,"A ",(0,r.kt)("a",{parentName:"p",href:"https://docs.nervos.org/docs/integrate/introduction/#ckb-built-in-indexer"},"ckb-indexer")," is built into ckb, also handles the job of indexing cells. It provides an RPC mechanism you can use to query for relevant cells. Please refer to the documentation of ckb-indexer for more details."),(0,r.kt)("h4",{id:"perkins-tent"},"perkins-tent"),(0,r.kt)("p",null,"If you are looking at a one-stop solution, ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/xxuejie/perkins-tent"},"Perkins' Tent")," provides a single docker image that starts both CKB and ckb-indexer in one dockerisntance. With a single command, you should be able to start a CKB instance and be ready to use the enclosed ckb-indexer for querying tasks."))}h.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[9591],{3905:(e,t,a)=>{a.d(t,{Zo:()=>d,kt:()=>h});var n=a(7294);function l(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function r(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function i(e){for(var t=1;t=0||(l[a]=e[a]);return l}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(l[a]=e[a])}return l}var s=n.createContext({}),c=function(e){var t=n.useContext(s),a=t;return e&&(a="function"==typeof e?e(t):i(i({},t),e)),a},d=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var a=e.components,l=e.mdxType,r=e.originalType,s=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),u=c(a),h=l,m=u["".concat(s,".").concat(h)]||u[h]||p[h]||r;return a?n.createElement(m,i(i({ref:t},d),{},{components:a})):n.createElement(m,i({ref:t},d))}));function h(e,t){var a=arguments,l=t&&t.mdxType;if("string"==typeof e||l){var r=a.length,i=new Array(r);i[0]=u;var o={};for(var s in t)hasOwnProperty.call(t,s)&&(o[s]=t[s]);o.originalType=e,o.mdxType="string"==typeof e?e:l,i[1]=o;for(var c=2;c{a.r(t),a.d(t,{assets:()=>d,contentTitle:()=>s,default:()=>h,frontMatter:()=>o,metadata:()=>c,toc:()=>p});var n=a(7462),l=a(3366),r=(a(7294),a(3905)),i=["components"],o={id:"cell",title:"Cell"},s=void 0,c={unversionedId:"reference/cell",id:"reference/cell",title:"Cell",description:"Nervos CKB (Common Knowledge Base) is a layer 1 blockchain, a decentralized and secure layer that provides common knowledge custody for the network. Common knowledge refers to states that are agreed via global consensus.",source:"@site/docs/reference/cell.md",sourceDirName:"reference",slug:"/reference/cell",permalink:"/docs/reference/cell",draft:!1,editUrl:"https://github.com/nervosnetwork/docs-new/tree/develop/website/docs/reference/cell.md",tags:[],version:"current",frontMatter:{id:"cell",title:"Cell"},sidebar:"Reference",previous:{title:"Introduction",permalink:"/docs/reference/introduction"},next:{title:"Script",permalink:"/docs/reference/script"}},d={},p=[{value:"Data Structure",id:"data-structure",level:2},{value:"Cell data",id:"cell-data",level:3},{value:"Cell information size calculation",id:"cell-information-size-calculation",level:3},{value:"Live Cell",id:"live-cell",level:2},{value:"Index-Query-Assemble Pattern",id:"index-query-assemble-pattern",level:2},{value:"Tools",id:"tools",level:3},{value:"lumos",id:"lumos",level:4},{value:"ckb-indexer",id:"ckb-indexer",level:4},{value:"perkins-tent",id:"perkins-tent",level:4}],u={toc:p};function h(e){var t=e.components,a=(0,l.Z)(e,i);return(0,r.kt)("wrapper",(0,n.Z)({},u,a,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("p",null,"Nervos CKB (Common Knowledge Base) is a layer 1 blockchain, a decentralized and secure layer that provides common knowledge custody for the network. Common knowledge refers to ",(0,r.kt)("strong",{parentName:"p"},"states")," that are agreed via global consensus."),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Cells are the primary state units")," in CKB and assets owned by users. They must follow associated validation rules specified by scripts. In Bitcoin, money is the typical common knowledge stored in the Bitcoin ledger. Nervos CKB, however, takes one step further to store arbitrary common knowledge. We starts from Bitcoin's general architecture, and creates the ",(0,r.kt)("a",{parentName:"p",href:"https://medium.com/nervosnetwork/https-medium-com-nervosnetwork-cell-model-7323fca57571"},"Cell Model")," by generalizing from the UTXO model, while at the same time retaining the consistency and simplicity of Bitcoin."),(0,r.kt)("h2",{id:"data-structure"},"Data Structure"),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Example:")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'{\n "capacity": "0x19995d0ccf",\n "lock": {\n "code_hash": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8",\n "args": "0x0a486fb8f6fe60f76f001d6372da41be91172259",\n "hash_type": "type"\n },\n "type": null\n}\n')),(0,r.kt)("p",null,"A Cell has three fields\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"capacity"),": Capacity serves 2 purposes: on one hand, it represents the amount of CKB tokens stored in the cell, on the other hand, it also sets the limit on how much information the cell can store. The basic unit for capacity is ",(0,r.kt)("inlineCode",{parentName:"li"},"shannon"),", a bigger unit ",(0,r.kt)("inlineCode",{parentName:"li"},"CKByte"),", or just ",(0,r.kt)("inlineCode",{parentName:"li"},"CKB")," is also used. 1 CKB equals ",(0,r.kt)("inlineCode",{parentName:"li"},"10**8")," shannons, 1 CKB also means the cell can store 1 byte of information. See below for how to calculate the total information size of a cell."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"lock script"),": A script used to guard the cell: when the specified cell is used as an input cell in a transaction, the lock script included in a cell will be executed. The transaction will be rejected when the lock script fails in execution. One typical use case for lock script, is to represent the ownership of a cell, meaning a signature verification phase is usually included in the cell."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"type script"),": A script used to validate cell structure. The type script of a cell will be executed both when the cell is included as an input cell, as well as when the cell is created as an output cell. Due to this nature, type script is typically used to validate dapp logic, such as creating UDTs.")),(0,r.kt)("p",null,"Each cell must have a lock script, while type script is optional, and can be omitted. Please refer to ",(0,r.kt)("a",{parentName:"p",href:"/docs/reference/script"},"Script")," for the actual format of lock and type script."),(0,r.kt)("h3",{id:"cell-data"},"Cell data"),(0,r.kt)("p",null,"In addition to the above fields, each cell also contains a cell data field. Cell data is just a series of unformatted binary data. Depending on each dapp, anything could be stored in the cell data part:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Script code as explained in ",(0,r.kt)("a",{parentName:"li",href:"/docs/reference/script"},"Script"),"."),(0,r.kt)("li",{parentName:"ul"},"Token amount for User Defined Token cells."),(0,r.kt)("li",{parentName:"ul"},"Latest game stats for an on-chain fantasy game.")),(0,r.kt)("p",null,"For future potential, cell data is not stored directly in a cell. It is kept directly in the ",(0,r.kt)("a",{parentName:"p",href:"/docs/reference/transaction#data-structure"},"Transaction"),". You might find a field named ",(0,r.kt)("inlineCode",{parentName:"p"},"outputs_data")," in each transaction. This array should have the same length with ",(0,r.kt)("inlineCode",{parentName:"p"},"outputs"),". At each index location, the corresponding cell data could be located for each created output cell in the transaction. Conceptually, we still consider cell data as part of each output cell."),(0,r.kt)("h3",{id:"cell-information-size-calculation"},"Cell information size calculation"),(0,r.kt)("p",null,"Each cell on Nervos CKB, must not have a lower capacity than the total size of information stored in the cell. The size of information for a cell is calculated as the sum of the following fields:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"8 bytes for cell capacity field."),(0,r.kt)("li",{parentName:"ol"},"32 bytes for code hash in lock script."),(0,r.kt)("li",{parentName:"ol"},"1 byte for hash type in lock script."),(0,r.kt)("li",{parentName:"ol"},"Actual bytes of args field in lock script."),(0,r.kt)("li",{parentName:"ol"},"If type script is present, 32 bytes for code hash in type script."),(0,r.kt)("li",{parentName:"ol"},"If type script is present, 1 byte for hash type in type script."),(0,r.kt)("li",{parentName:"ol"},"If type script is present, actual bytes of args field in type script."),(0,r.kt)("li",{parentName:"ol"},"Actual bytes of cell data.")),(0,r.kt)("p",null,"By summing up all the above fields, we get the total size of information a cell needs. Cell capacity, when measured in ",(0,r.kt)("inlineCode",{parentName:"p"},"CKBytes"),", represents the maximum size of information that can be held, meaning a valid cell must ensure the CKBytes stored in capacity equal or is larger than the total size of information."),(0,r.kt)("h2",{id:"live-cell"},"Live Cell"),(0,r.kt)("p",null,"Live cell refers to an unspent cell in CKB. It is similar to the concept of ",(0,r.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Unspent_transaction_output"},"UTXO")," in Bitcoin's terminology. The full set of live cells in CKB, is consider the full state of CKB at that particular point. Any transaction on CKB would consume some cells that were live cells just at the point before it is committed, and created new cells that are considered live cells after it is committed."),(0,r.kt)("h2",{id:"index-query-assemble-pattern"},"Index-Query-Assemble Pattern"),(0,r.kt)("p",null,"Nervos CKB is designed based on the concept of cells. A transaction, at its core, really just consumes some cells, and create another set of cells. As a result, the ability to locate and transform cells, plays a critical role in building any CKB dapps, which leads to the ",(0,r.kt)("inlineCode",{parentName:"p"},"index-query-assemble")," pattern:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Index: when a new block is committed to CKB, a dapp should be able to index relevant cells to its own storage for latter usage."),(0,r.kt)("li",{parentName:"ul"},"Query: when a user action is requested, cells satisfying certain criteria will be queried from the dapp storage."),(0,r.kt)("li",{parentName:"ul"},"Assemble: based on queried cells, a new transaction would be assembled to fulfill user requests.")),(0,r.kt)("p",null,"We believe all CKB dapps can be decomposed into individual actions following this pattern. Here are some examples:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"In a normal CKB wallet, cells should be indexed based on lock scripts. A transfer action would first query cells from the sender, and assemble a transaction which transfer CKBytes to the receiver."),(0,r.kt)("li",{parentName:"ul"},"A NervosDAO manager might index only cells related to NervosDAO. A user might then pick a NervosDAO cell and perform withdraw action, even though there is only one cell related, we can still view it as cells queried from the NervosDAO manager, and a transaction will also be assembled which performs the actual withdraw action."),(0,r.kt)("li",{parentName:"ul"},"A state based dapp might choose to store the latest state in a CKB cell. The dapp will still need to track the latest live cell, which can also be viewed as an indexing operation, any action on the state will result in the latest live cell being queried, assembled into a transaction, then accepted by CKB with a new output cell containing the updated state.")),(0,r.kt)("h3",{id:"tools"},"Tools"),(0,r.kt)("p",null,"Indexing & querying plays a central role in any CKB dapps. In most cases, you don't have to build an indexer from scratch. There are several existing tools one can leverage to fulfill the job:"),(0,r.kt)("h4",{id:"lumos"},"lumos"),(0,r.kt)("p",null,"Our dapp framework, ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/lumos"},"lumos")," already contains a ready-to-use indexer. When you are using lumos, it is very likely the indexer is already setup for you to use. Please refer to our labs for how to setup lumos."),(0,r.kt)("h4",{id:"ckb-indexer"},"ckb-indexer"),(0,r.kt)("p",null,"A ",(0,r.kt)("a",{parentName:"p",href:"https://docs.nervos.org/docs/integrate/introduction/#ckb-built-in-indexer"},"ckb-indexer")," is built into ckb, also handles the job of indexing cells. It provides an RPC mechanism you can use to query for relevant cells. Please refer to the documentation of ckb-indexer for more details."),(0,r.kt)("h4",{id:"perkins-tent"},"perkins-tent"),(0,r.kt)("p",null,"If you are looking at a one-stop solution, ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/xxuejie/perkins-tent"},"Perkins' Tent")," provides a single docker image that starts both CKB and ckb-indexer in one dockerisntance. With a single command, you should be able to start a CKB instance and be ready to use the enclosed ckb-indexer for querying tasks."))}h.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/ffbe244f.7b20f12d.js b/assets/js/ffbe244f.afde17d8.js similarity index 99% rename from assets/js/ffbe244f.7b20f12d.js rename to assets/js/ffbe244f.afde17d8.js index d0c214ff3..558c8036a 100644 --- a/assets/js/ffbe244f.7b20f12d.js +++ b/assets/js/ffbe244f.afde17d8.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[8158],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>h});var a=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function s(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=a.createContext({}),c=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},d=function(e){var t=c(e.components);return a.createElement(l.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},u=a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,l=e.parentName,d=r(e,["components","mdxType","originalType","parentName"]),u=c(n),h=o,f=u["".concat(l,".").concat(h)]||u[h]||p[h]||i;return n?a.createElement(f,s(s({ref:t},d),{},{components:n})):a.createElement(f,s({ref:t},d))}));function h(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,s=new Array(i);s[0]=u;var r={};for(var l in t)hasOwnProperty.call(t,l)&&(r[l]=t[l]);r.originalType=e,r.mdxType="string"==typeof e?e:o,s[1]=r;for(var c=2;c{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>l,default:()=>h,frontMatter:()=>r,metadata:()=>c,toc:()=>p});var a=n(7462),o=n(3366),i=(n(7294),n(3905)),s=["components"],r={id:"lumos-nervosdao",title:"Introduction to Lumos via NervosDAO"},l=void 0,c={unversionedId:"labs/lumos-nervosdao",id:"labs/lumos-nervosdao",title:"Introduction to Lumos via NervosDAO",description:"In the real world, one hardly sees a blockchain exposed and used directly by the ordinary users. Apps, websites or other services are built on top of blockchains to provide a seamless service. Based on this belief, we built lumos, a JavaScript/TypeScript framework, that aids dapp development on CKB. Lumos should be able to free you from most, if not all of the hassles for dealing with CKB, and let you focus on the specific logic in your dapp.",source:"@site/docs/labs/lumos-nervosdao.md",sourceDirName:"labs",slug:"/labs/lumos-nervosdao",permalink:"/docs/labs/lumos-nervosdao",draft:!1,editUrl:"https://github.com/nervosnetwork/docs-new/tree/develop/website/docs/labs/lumos-nervosdao.md",tags:[],version:"current",frontMatter:{id:"lumos-nervosdao",title:"Introduction to Lumos via NervosDAO"},sidebar:"Labs",previous:{title:"Write an SUDT Script by Capsule",permalink:"/docs/labs/sudtbycapsule"},next:{title:"Exec syscall in Capsule",permalink:"/docs/labs/capsule-exec"}},d={},p=[{value:"Components",id:"components",level:2},{value:"Initial CKB Setup",id:"initial-ckb-setup",level:2},{value:"Node Skeleton",id:"node-skeleton",level:2},{value:"Config Manager Setup",id:"config-manager-setup",level:2},{value:"Booting Indexer",id:"booting-indexer",level:2},{value:"Deposit",id:"deposit",level:2},{value:"Transaction Skeleton",id:"transaction-skeleton",level:3},{value:"Withdraw",id:"withdraw",level:2},{value:"Locktime Pool",id:"locktime-pool",level:3},{value:"Common Script",id:"common-script",level:2},{value:"Recap",id:"recap",level:2}],u={toc:p};function h(e){var t=e.components,n=(0,o.Z)(e,s);return(0,i.kt)("wrapper",(0,a.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("p",null,"In the real world, one hardly sees a blockchain exposed and used directly by the ordinary users. Apps, websites or other services are built on top of blockchains to provide a seamless service. Based on this belief, we built ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/lumos"},"lumos"),", a JavaScript/TypeScript framework, that aids dapp development on CKB. Lumos should be able to free you from most, if not all of the hassles for dealing with CKB, and let you focus on the specific logic in your dapp."),(0,i.kt)("p",null,"In this tutorial, we will provide an introduction on lumos via a real example: ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0023-dao-deposit-withdraw/0023-dao-deposit-withdraw.md"},"Nervos DAO"),", while quite valuable on CKB, can be a real pain to integrate for many dapps. Here we will demonstrate that how lumos can be used to streamline Nervos DAO integration."),(0,i.kt)("h2",{id:"components"},"Components"),(0,i.kt)("p",null,"Lumos is designed as a framework, meaning it is expected to be used in a intrinsic way: certain setup code will be needed when you first boot your application. Global states might also be kept in your application memory space for bookkeeping purposes. That being said, lumos is also organized into several components, some of which might be used in a non-intrinsic stateless fashion. In general, lumos consists of the following components:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/lumos/tree/v0.4.0/packages/indexer"},"indexer"),": a CKB cell indexer that fulfills ",(0,i.kt)("a",{parentName:"li",href:"../reference/cell#index-query-assemble-pattern"},"Index-Query-Assemble")," pattern. For now, this package only contains RocksDB backed indexer. A ",(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/lumos/tree/v0.4.0/packages/sql-indexer"},"separate pacakge")," contains SQL backed indexer using the same interface. Later, we might merge the 2 packages into one for consistency."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/lumos/tree/v0.4.0/packages/base"},"base"),": a base package containing common types and utilities that are used by most packages. If there is a CKB specific task you need to perform, you might want to look here first. Chances are they are already provided."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/lumos/tree/v0.4.0/packages/helpers"},"helpers"),": a helper package containing more utilities. The difference between ",(0,i.kt)("inlineCode",{parentName:"li"},"helpers")," and ",(0,i.kt)("inlineCode",{parentName:"li"},"base"),", is that ",(0,i.kt)("inlineCode",{parentName:"li"},"base")," contains pure stateless functions, while ",(0,i.kt)("inlineCode",{parentName:"li"},"helpers")," works in a more intrinsic way: it requires ",(0,i.kt)("inlineCode",{parentName:"li"},"config-manager")," mentioned below to be setup."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/lumos/tree/v0.4.0/packages/common-scripts"},"common-scripts"),": integrations for known scripts on CKB. While we try our best to provide integrations for popular CKB scripts, people might be working on innovations everyday. As a result, we are also designing a set of APIs, so developers can freely integrate their own scripts into lumos for everyone to use. One integrated, ",(0,i.kt)("inlineCode",{parentName:"li"},"common-scripts")," should be able to leverage those new scripts as well."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/lumos/tree/v0.4.0/packages/config-manager"},"config-manager"),": a manager for dealing with differences between different chains, such as mainnet, testnet, or numerous dev chains. We abstract each chain into individual config file. Once loaded, config manager will be able to handle the chain specific logic, so you don't have to deal with this in your own code."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/lumos/tree/v0.4.0/packages/transaction-manager"},"transaction-manager"),": a transaction manager for CKB. One problem with UTXO based blockchains, is that a certain amount of gap period exists between a transaction is accepted by a blockchain, and when it is actually committed on chain. During this gap, new cells created by the pending transaction will not be available. Transaction manager package takes care of this. It wraps an indexer instance, and makes sure cells created in pending transactions, are also exposed and available for assembling new transactions. This means you are no longer bounded to one transaction at a time, you can freely send series of transactions as you wish.")),(0,i.kt)("h2",{id:"initial-ckb-setup"},"Initial CKB Setup"),(0,i.kt)("p",null,"To ease the whole process so we don't have to wait too long to see the results, let's setup our own dev chain with ",(0,i.kt)("a",{parentName:"p",href:"../basics/guides/devchain#4-adjust-the-parameters-to-shorten-the-block-interval-optional"},"tweaks"),":"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},'$ export TOP=$(pwd)\n# I\'m testing this on a Linux machine, if you use other platforms, please adjust\n# this accordingly.\n$ curl -LO https://github.com/nervosnetwork/ckb/releases/download/v0.33.0/ckb_v0.33.0_x86_64-unknown-linux-gnu.tar.gz\n$ tar xzf ckb_v0.33.0_x86_64-unknown-linux-gnu.tar.gz\n$ export PATH=$PATH:$TOP/ckb_v0.33.0_x86_64-unknown-linux-gnu\n$ ckb -V\nckb 0.33.0\n$ ckb init -C devnet -c dev\n$ ed devnet/specs/dev.toml <\n')),(0,i.kt)("p",null,"But this is only for demonstration purposes. There's nothing stopping you from copying the same code into a file that is then executed by node."),(0,i.kt)("h2",{id:"config-manager-setup"},"Config Manager Setup"),(0,i.kt)("p",null,"The first step in using lumos, is setting up config manager. Even though CKB has a unified programming model, different configurations would still be required for different chain instances, such as mainnet, testnet or dev chains. Config manager allows the node app to boot with a specific chain configuration, so other parts in lumos can consult config manager directly for information."),(0,i.kt)("p",null,"If you are using a well known chain configuration, you can use ",(0,i.kt)("inlineCode",{parentName:"p"},"LUMOS_CONFIG_NAME")," environment variable to setup config manager:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"$ LUMOS_CONFIG_NAME=LINA node --experimental-repl-await\nWelcome to Node.js v12.16.2.\nType \".help\" for more information.\n> const { initializeConfig, getConfig } = require(\"@ckb-lumos/config-manager\");\n> initializeConfig();\n> getConfig();\n{\n PREFIX: 'ckb',\n SCRIPTS: {\n SECP256K1_BLAKE160: {\n CODE_HASH: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8',\n HASH_TYPE: 'type',\n TX_HASH: '0x71a7ba8fc96349fea0ed3a5c47992e3b4084b031a42264a018e0072e8172e46c',\n INDEX: '0x0',\n DEP_TYPE: 'dep_group',\n SHORT_ID: 0\n },\n SECP256K1_BLAKE160_MULTISIG: {\n CODE_HASH: '0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8',\n HASH_TYPE: 'type',\n TX_HASH: '0x71a7ba8fc96349fea0ed3a5c47992e3b4084b031a42264a018e0072e8172e46c',\n INDEX: '0x1',\n DEP_TYPE: 'dep_group',\n SHORT_ID: 1\n },\n DAO: {\n CODE_HASH: '0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e',\n HASH_TYPE: 'type',\n TX_HASH: '0xe2fb199810d49a4d8beec56718ba2593b665db9d52299a0f9e6e75416d73ff5c',\n INDEX: '0x2',\n DEP_TYPE: 'code'\n }\n }\n}\n")),(0,i.kt)("p",null,"Supported well known configurations include:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"LINA"),": mainnet config;"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"AGGRON4"),": current testnet config. Note at certain time, we might reset testnet, in that case, lumos might be upgraded with new testnet configurations.")),(0,i.kt)("p",null,"However there might be cases, where you don't use a pre-defined configuration. For example, the dev chain we use here, does not have a pre-defined configuration. Lumos also supports setting up config manager via a local config file. You can use ",(0,i.kt)("inlineCode",{parentName:"p"},"LUMOS_CONFIG_FILE")," environment variable to point to the config file. If neither config variable is set, lumos will try to read config file from ",(0,i.kt)("inlineCode",{parentName:"p"},"config.json")," file in current directory."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},'$ cat < config.json\n{\n "PREFIX": "ckt",\n "SCRIPTS": {\n "SECP256K1_BLAKE160": {\n "CODE_HASH": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8",\n "HASH_TYPE": "type",\n "TX_HASH": "0xace5ea83c478bb866edf122ff862085789158f5cbff155b7bb5f13058555b708",\n "INDEX": "0x0",\n "DEP_TYPE": "dep_group",\n "SHORT_ID": 0\n },\n "SECP256K1_BLAKE160_MULTISIG": {\n "CODE_HASH": "0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8",\n "HASH_TYPE": "type",\n "TX_HASH": "0xace5ea83c478bb866edf122ff862085789158f5cbff155b7bb5f13058555b708",\n "INDEX": "0x1",\n "DEP_TYPE": "dep_group",\n "SHORT_ID": 1\n },\n "DAO": {\n "CODE_HASH": "0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e",\n "HASH_TYPE": "type",\n "TX_HASH": "0xa563884b3686078ec7e7677a5f86449b15cf2693f3c1241766c6996f206cc541",\n "INDEX": "0x2",\n "DEP_TYPE": "code"\n }\n }\n}\nEOF\n$ LUMOS_CONFIG_FILE="config.json" node --experimental-repl-await\nWelcome to Node.js v12.16.2.\nType ".help" for more information.\n> const { initializeConfig, getConfig } = require("@ckb-lumos/config-manager");\n> initializeConfig();\n')),(0,i.kt)("p",null,"Now config manager is successfully setup, we can proceed to the next step."),(0,i.kt)("h2",{id:"booting-indexer"},"Booting Indexer"),(0,i.kt)("p",null,"Lumos is designed based on the ",(0,i.kt)("a",{parentName:"p",href:"../reference/cell#index-query-assemble-pattern"},"Index-Query-Assemble")," pattern, meaning a dapp shall hava an indexer that keeps indexing new blocks in a format that is easier to query. This means any dapp built with lumos, should also have an indexer configured and running at all time:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},'> const { Indexer } = require("@ckb-lumos/indexer");\n> const indexer = new Indexer("http://127.0.0.1:8114", "./indexed-data");\n> indexer.startForever();\n')),(0,i.kt)("p",null,"Here we are using the RocksDB backed indexer for simplicity. Lumos provides 2 indexer types:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"RocksDB backed indexer"),(0,i.kt)("li",{parentName:"ul"},"SQL backed indexer, supported SQL databases now include MySQL and PostgreSQL.")),(0,i.kt)("p",null,"If you want to test against the SQL indexer, some modifications to the above setup code might be required."),(0,i.kt)("p",null,"You can check current indexed tip with the following code snippet:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},'> await indexer.tip()\n{\n block_number: "0x29c",\n block_hash: "0x3e44b571c82a09117231baee1939d38440d71f56de8bc600ac32b1dead9be46d"\n}\n')),(0,i.kt)("p",null,"Please wait a while till lumos has caught up with the current chain tip. This should not take much time for a dev chain."),(0,i.kt)("h2",{id:"deposit"},"Deposit"),(0,i.kt)("p",null,"To deposit to Nervos DAO, we need to first create a deposit transaction. You could of course go the hard way and create a transaction manually, but lumos has already provide a solution for simplifying transaction creation. Let's look at ",(0,i.kt)("inlineCode",{parentName:"p"},"TransactionSkeleton")," and how it works in lumos first."),(0,i.kt)("h3",{id:"transaction-skeleton"},"Transaction Skeleton"),(0,i.kt)("p",null,"CKB provides great flexibility for dapp developers to build anything they want. But we all know that ",(0,i.kt)("strong",{parentName:"p"},"with great power comes great responsibility"),", a flexible programming model also significantly complicates transaction assembling. This includes but might not be limited to the following hurdles:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Different scripts used in transaction inputs will require separate message generation, and also separate signing steps."),(0,i.kt)("li",{parentName:"ul"},"Some cells might require special argument setup in witness, due to type script validation rules."),(0,i.kt)("li",{parentName:"ul"},"Coordination might be required, since both lock script and type script in a cell might require arguments in the same witness construct.")),(0,i.kt)("p",null,"Those problems will haunt you even when you are dealing with a single NervosDAO transaction. It is only gonna get more complicated, when we consider multiple cells containing different CKB scripts composed together. Looking into the future, we will definitely need a solution to this issue."),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"TransactionSkeleton")," is the answer we propose in lumos. Each transaction skeleton corresponds to an action, and will be built into a single transaction that is ready to be submitted to CKB. Surrounding the idea of TransactionSkeleton, a series of conveniences are provided to aid transaction assembling:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"A well designed component should automatically query and include cells to provide capacities required by the transaction."),(0,i.kt)("li",{parentName:"ul"},"Individual script logic should be managed and respected by the general transaction skeleton."),(0,i.kt)("li",{parentName:"ul"},"Scripts sharing the same behavior should be managed together in a unified interface. Developers can rely on abstractions instead of catering for every single detail.")),(0,i.kt)("p",null,"This still sounds quite complicated, let's walkthrough an example to see how we can leverage TransactionSkeleton."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},'> // In practice, you might already have the address at your hand, here we just\n> // want to demonstrate how this works.\n> const script = {\n code_hash: "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8",\n hash_type: "type",\n args: "0xcbfbb9edb5838e2d61061c3fc69eaaa5fdbd3273"\n};\n> const {generateAddress, parseAddress, createTransactionFromSkeleton,\n sealTransaction, TransactionSkeleton } = require("@ckb-lumos/helpers");\n> const address = generateAddress(script);\n\n> // Now let\'s create the actual skeleton, and deposit CKBytes into the skeleton\n> let skeleton = TransactionSkeleton({ cellProvider: indexer });\n> const { secp256k1Blake160, dao } = require("@ckb-lumos/common-scripts");\n\n> // Using utility provided in common-scripts, let\'s deposit 1000 CKBytes into\n> // the skeleton. We will introduce common-scripts separately below. Here we are\n> // using the same address as from and to, but this does not have to be the case\n> // everywhere.\n> skeleton = await dao.deposit(skeleton, address, address, 100000000000n);\n\n> // createTransactionFromSkeleton is designed to build a final transaction, but\n> // there is nothing stopping you from using it to peek into the current skeleton.\n> console.log(JSON.stringify(createTransactionFromSkeleton(skeleton), null, 2));\n\n> // But this transaction is not yet complete, we still need 2 parts:\n> // * Transaction fee is not taken into consideration\n> // * The transaction is not signed yet\n> // Let\'s take a look at them separately.\n\n> // First, since we are using the default secp256k1-blake160 lock script, an\n> // existing module in common-scripts can be leveraged to incur transaction\n> // fee. Here we are using the same address to provide 1 CKByte as transaction\n> // fee.\n> skeleton = await secp256k1Blake160.payFee(skeleton, address, 100000000n);\n\n> // If you checked the transaction skeleton after incurring fees. You will\n> // notice that it only has one input. This might raise a question: if NervoDAO\n> // deposit consumes one input cell, transaction fee requires a different input\n> // cell, shouldn\'t there be 2 input cells with 3 output cells(a deposited cell,\n> // and 2 change cell)? The trick here, is that common-scripts is smart enough\n> // to figure out that the 2 actions here use the same address. Hence it just\n> // rewrite the change cell generated in the NervosDAO deposit action to pay\n> // enough transaction fee.\n> createTransactionFromSkeleton(skeleton).inputs.length;\n1\n\n> // Now the transaction is more or less complete, we can start generate messages\n> // used for signing.\n> skeleton = secp256k1Blake160.prepareSigningEntries(skeleton);\n> // This method actually loops through the skeleton, and create `signingEntries`\n> // that are using the default secp256k1-blake160 lock script:\n> skeleton.get("signingEntries").toArray();\n[\n {\n type: \'witness_args_lock\',\n index: 0,\n message: \'0x40811fd6ed74b9042f603dc7f2f577da7ebe0e05175d349dbb5c539b1111b83f\'\n }\n]\n')),(0,i.kt)("p",null,"Lumos, for now, does not handle message signing for the following reasons:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"This is a serious matter that relates to the overall security of the dapp, we want to make sure we are doing this properly if/when we decide to do it."),(0,i.kt)("li",{parentName:"ul"},"Different dapps might have different requirements, some don't do signing at all, having signing built-in might render certain dapps hard to build.")),(0,i.kt)("p",null,"Using a secp256k1 tool, it's not hard to generate a signature here based on the private key listed above, and the message. And we can continue with this process:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},'> const signatures = ["0x1cb952fd224d1d14d07af621587e91a65ccb051d55ed1371b3b66d4fe169cf7758173882e4c02587cb54054d2de287cbb1fdc2fc21d848d7b320ee8c5826479901"];\n> const tx = sealTransaction(skeleton, signatures);\n')),(0,i.kt)("p",null,"Now we have a complete transaction assembled, and we can send it to CKB:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},'> const { RPC } = require("ckb-js-toolkit");\n> const rpc = new RPC("http://127.0.0.1:8114");\n> await rpc.send_transaction(tx);\n\'0x88536e8c25f5f8c89866dec6a5a1a6a72cccbe282963e4a7bfb5542b4c15d376\'\n')),(0,i.kt)("p",null,"Now we have successfully deposited CKBytes into CKB using lumos!"),(0,i.kt)("h2",{id:"withdraw"},"Withdraw"),(0,i.kt)("p",null,"The following code can help us list all deposited Nervos DAO cells for an address:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"> for await (const cell of dao.listDaoCells(indexer, address, \"deposit\")) { console.log(cell); }\n{\n cell_output: {\n capacity: '0x174876e800',\n lock: {\n code_hash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8',\n hash_type: 'type',\n args: '0xcbfbb9edb5838e2d61061c3fc69eaaa5fdbd3273'\n },\n type: {\n code_hash: '0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e',\n hash_type: 'type',\n args: '0x'\n }\n },\n out_point: {\n tx_hash: '0x88536e8c25f5f8c89866dec6a5a1a6a72cccbe282963e4a7bfb5542b4c15d376',\n index: '0x0'\n },\n block_hash: '0xa1ec7dc291774bc0fc229efba4a162c099a8d88ffa7ae2fa410cc574e0701ced',\n block_number: '0x196',\n data: '0x0000000000000000'\n}\n")),(0,i.kt)("p",null,"Here we can find the cell we just deposited to Nervos DAO. Let's now try to withdraw it from Nervos DAO:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"> // First, we will need to locate the cell. In a real dapp this is most likely\n> // coming from user selection.\n> const cell = (await dao.listDaoCells(indexer, address, \"deposit\").next()).value;\n> // For a new action, let's create a new transaction skeleton\n> skeleton = TransactionSkeleton({ cellProvider: indexer });\n> // This time, we invoke withdraw method to prepare a withdraw skeleton\n> skeleton = await dao.withdraw(skeleton, cell, address);\n> // Fees are also necessary\n> skeleton = await secp256k1Blake160.payFee(skeleton, address, 100000000n);\n> // And let's generate signing entries again.\n> skeleton = secp256k1Blake160.prepareSigningEntries(skeleton);\n> skeleton.get(\"signingEntries\").toArray();\n[\n {\n type: 'witness_args_lock',\n index: 0,\n message: '0x24370c5cedc03c34ae0a00a10d9e62324bce07e8d155c839ff10991d73684c34'\n }\n]\n> // After we signed the message, we can get the signature:\n> const signatures2 = [\"0x5aed4480c82844506fefc1d92dd18422a123b8e880018ea4cfa7f95891c4781e6578facedd765676831cf3cca04492ec3ec3885ac8d0b6d90cb6c1d6f99e6ffb01\"];\n> // Now we can seal and send the transaction\n> const tx2 = sealTransaction(skeleton, signatures2);\n> await rpc.send_transaction(tx2);\n'0xe411eb6a3cf4f659461cc7a9df9ff95a72b9624bf850b9ccad0c4d7f2ab444f6'\n")),(0,i.kt)("p",null,"See that withdrawing transaction is not so hard!"),(0,i.kt)("h3",{id:"locktime-pool"},"Locktime Pool"),(0,i.kt)("p",null,"We could've just showed the ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/lumos/blob/ac96a3220ab2a148425120eaac216abe246ee1da/packages/common-scripts/index.d.ts#L262"},"unlock")," method in ",(0,i.kt)("inlineCode",{parentName:"p"},"dao")," module, which let you complete the withdrawing from Nervos DAO. But here I want to talk about a different construct in lumos: locktime pool."),(0,i.kt)("p",null,"If you look closer, you would notice that the cell consumed in ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0023-dao-deposit-withdraw/0023-dao-deposit-withdraw.md#withdraw-phase-2"},"withdraw phase 2"),", is really nothing but a cell with a certain lock period. Likewise, there might be other scripts on CKB, when combined with certain cell, just provide lock periods. The multisig script included in genesis cell, is one such example. So the idea arises: what if we build a unified pool, that handles all cells that have lock periods? When designed properly, we can ignore the fact that they might come from different dapps, using different scripts. What we do care, is that each of those cells comes with a capacity and lock period, when the lock period is reached, they are nothing but ordinary cells in one's wallet."),(0,i.kt)("p",null,"Given this thought, we designed ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime pool")," in lumos. Right now it only processes Nervos DAO cells in withdraw phase 2 and multisig cells, but in the future there is nothing stopping us from integrating more scripts that provide lock periods. From a developer point of view, locktime pool, can be used to manage all of them, provide a unified view in dapps."),(0,i.kt)("p",null,"As usual, we can query for all cells currently in the locktime pool:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"> const { locktimePool } = require(\"@ckb-lumos/common-scripts\");\n> for await (const cell of locktimePool.collectCells(indexer, address)) { console.log(cell); }\n{\n cell_output: {\n capacity: '0x174876e800',\n lock: {\n code_hash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8',\n hash_type: 'type',\n args: '0xcbfbb9edb5838e2d61061c3fc69eaaa5fdbd3273'\n },\n type: {\n code_hash: '0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e',\n hash_type: 'type',\n args: '0x'\n }\n },\n out_point: {\n tx_hash: '0xe411eb6a3cf4f659461cc7a9df9ff95a72b9624bf850b9ccad0c4d7f2ab444f6',\n index: '0x0'\n },\n block_hash: '0xb468ec0a1aed1f7070fc00952453ac882dbe36b1afbfb520c822fe46b3b81dfe',\n block_number: '0x543',\n data: '0x9601000000000000',\n maximumCapacity: 100153459536n,\n since: '0x20000a00060000dc',\n depositBlockHash: '0xa1ec7dc291774bc0fc229efba4a162c099a8d88ffa7ae2fa410cc574e0701ced',\n withdrawBlockHash: '0xb468ec0a1aed1f7070fc00952453ac882dbe36b1afbfb520c822fe46b3b81dfe',\n sinceBaseValue: undefined\n}\n")),(0,i.kt)("p",null,"Here we can found the cell just created from NervosDAO withdrawing step. Let's try to consume it using locktimePool:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},'> // Notice you will wait till the lock period of the cell has passed, otherwise this function would throw an error:\n> skeleton = await locktimePool.transfer(skeleton, [address], address, 100153459536n, (await rpc.get_tip_header()));\n> console.log(JSON.stringify(createTransactionFromSkeleton(skeleton), null, 2));\n{\n "version": "0x0",\n "cell_deps": [],\n "header_deps": [],\n "inputs": [],\n "outputs": [],\n "outputs_data": [],\n "witnesses": []\n}\n')),(0,i.kt)("p",null,"This might actually be a surprise: we invoked transfer method, but it does nothing! Turns out the reason here, is that we are using the same address as both transfer input, and transfer output. Lumos is smart enough to figure out that when you are using the same input and output, we don't need to perform the action so as to save certain transaction fee."),(0,i.kt)("p",null,"One different question you might ask, is that we use the same address in deposit and withdraw steps, why those previous attempts work? The reason for this, is that deposited cell, or created cell in withdraw step 1 has special purposes, they represent unique ",(0,i.kt)("strong",{parentName:"p"},"actions")," that we want to perform, hence they are ",(0,i.kt)("strong",{parentName:"p"},"freezed")," in the transaction skeleton, so later when we optimize the transaction to combine inputs/outputs, we won't touch those specially created cells. On the other hand, in locktime pool design, we treat a cell with expired lock period the same as a normal cell, they really have nothing different, hence here, lumos will try to optimize the transaction, by removing the action transferring amount from an address to itself. In lumos' eye, this is a no-op."),(0,i.kt)("p",null,"Now let's try the same step using a different target address:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"> skeleton = await locktimePool.transfer(skeleton, [address], \"ckt1qyqx57xrsztnq7g5mlw6r998uyc2f5hm3vnsvgsaet\", 100153459536n, (await rpc.get_tip_header()));\n> skeleton = await secp256k1Blake160.payFee(skeleton, address, 100000000n);\n> skeleton = secp256k1Blake160.prepareSigningEntries(skeleton);\n> skeleton.get(\"signingEntries\").toArray();\n[\n {\n type: 'witness_args_lock',\n index: 0,\n message: '0xf01fb9988ba0265597760f50df92a56162d650b119cc95e8508079af584bdbc7'\n }\n]\n")),(0,i.kt)("p",null,"We can generate the signature as always:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"> const signatures3 = [\"0x6edde41592b41d445fabfd1b1d6854cf643bba724a338b5751827d991affa5a979d12339250bf5ade45f7f2742cba1e3de0791e37ef03914459bcdd099908ec601\"];\n> const tx3 = sealTransaction(skeleton, signatures3);\n> await rpc.send_transaction(tx3);\n'0xbaa7bdd71b7ec975f5a75c49d300857981f333c4346d6d6de1297d8d9d9ce0e0'\n")),(0,i.kt)("p",null,"This is really the core part of this post, if you are not understanding this part, we recommend you to read it again, and try it in CKB by yourself. What we are showing here, is that by designing a set of common APIs, we can build a general facility, that manages many different script instances, given the fact that they share the same behavior. And it is really not only the secp256k1-blake160 single signing script that shall be managed by a wallet. Any scripts that follow certain behavior, can be treated as a cell managed in a wallet."),(0,i.kt)("h2",{id:"common-script"},"Common Script"),(0,i.kt)("p",null,"As we show above, locktime pool is one step ahead of the journey at managing different cells/scripts with similar behaviors. But we are not stopping here, we can continue further down the path: it is mentioned above, that those cells with lock period already passed, can be thought as normal cells. Can we treat them as usual, without needing to deal with locktime pool?"),(0,i.kt)("p",null,"We have build ",(0,i.kt)("inlineCode",{parentName:"p"},"common")," module for this. Given a set of address/configurations(since for some P2SH script, address alone won't be enough), it can manage all cells using those scripts, including cells with expired lock period. Right now this includes the following:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"secp256k1-blake160 single signing script"),(0,i.kt)("li",{parentName:"ul"},"secp256k1-blake160 multiple signing script"),(0,i.kt)("li",{parentName:"ul"},"NervosDAO script(only cells in withdraw phase 2 are managed)")),(0,i.kt)("p",null,"And the list doesn't stop here, we are working to provide a common API specification, that once implemented, can enable ",(0,i.kt)("inlineCode",{parentName:"p"},"common")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime pool")," to support those additional scripts as well. We do hope those 2 modules can help enable a unified cell manager in lumos, in which ",(0,i.kt)("inlineCode",{parentName:"p"},"common")," handles all consumable cells, while ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime pool")," gives insights into cells that are locked now but will be usable in the future."),(0,i.kt)("h2",{id:"recap"},"Recap"),(0,i.kt)("p",null,"Lumos aims to take care of the full lifecycle of your CKB dapp. In this post, we are just taking a sneak peek at all the powers. We will continue to work on documents as well as sample projects to showcase all the powers enabled by lumos. We welcome all of you to try out lumos, and tell us what you think of it. So we can continue enhancing it, to make it the beloved framework for building CKB dapps."))}h.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[8158],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>h});var a=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function s(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=a.createContext({}),c=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},d=function(e){var t=c(e.components);return a.createElement(l.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},u=a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,l=e.parentName,d=r(e,["components","mdxType","originalType","parentName"]),u=c(n),h=o,f=u["".concat(l,".").concat(h)]||u[h]||p[h]||i;return n?a.createElement(f,s(s({ref:t},d),{},{components:n})):a.createElement(f,s({ref:t},d))}));function h(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,s=new Array(i);s[0]=u;var r={};for(var l in t)hasOwnProperty.call(t,l)&&(r[l]=t[l]);r.originalType=e,r.mdxType="string"==typeof e?e:o,s[1]=r;for(var c=2;c{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>l,default:()=>h,frontMatter:()=>r,metadata:()=>c,toc:()=>p});var a=n(7462),o=n(3366),i=(n(7294),n(3905)),s=["components"],r={id:"lumos-nervosdao",title:"Introduction to Lumos via NervosDAO"},l=void 0,c={unversionedId:"labs/lumos-nervosdao",id:"labs/lumos-nervosdao",title:"Introduction to Lumos via NervosDAO",description:"In the real world, one hardly sees a blockchain exposed and used directly by the ordinary users. Apps, websites or other services are built on top of blockchains to provide a seamless service. Based on this belief, we built lumos, a JavaScript/TypeScript framework, that aids dapp development on CKB. Lumos should be able to free you from most, if not all of the hassles for dealing with CKB, and let you focus on the specific logic in your dapp.",source:"@site/docs/labs/lumos-nervosdao.md",sourceDirName:"labs",slug:"/labs/lumos-nervosdao",permalink:"/docs/labs/lumos-nervosdao",draft:!1,editUrl:"https://github.com/nervosnetwork/docs-new/tree/develop/website/docs/labs/lumos-nervosdao.md",tags:[],version:"current",frontMatter:{id:"lumos-nervosdao",title:"Introduction to Lumos via NervosDAO"},sidebar:"Labs",previous:{title:"Write an SUDT Script by Capsule",permalink:"/docs/labs/sudtbycapsule"},next:{title:"Exec syscall in Capsule",permalink:"/docs/labs/capsule-exec"}},d={},p=[{value:"Components",id:"components",level:2},{value:"Initial CKB Setup",id:"initial-ckb-setup",level:2},{value:"Node Skeleton",id:"node-skeleton",level:2},{value:"Config Manager Setup",id:"config-manager-setup",level:2},{value:"Booting Indexer",id:"booting-indexer",level:2},{value:"Deposit",id:"deposit",level:2},{value:"Transaction Skeleton",id:"transaction-skeleton",level:3},{value:"Withdraw",id:"withdraw",level:2},{value:"Locktime Pool",id:"locktime-pool",level:3},{value:"Common Script",id:"common-script",level:2},{value:"Recap",id:"recap",level:2}],u={toc:p};function h(e){var t=e.components,n=(0,o.Z)(e,s);return(0,i.kt)("wrapper",(0,a.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("p",null,"In the real world, one hardly sees a blockchain exposed and used directly by the ordinary users. Apps, websites or other services are built on top of blockchains to provide a seamless service. Based on this belief, we built ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/lumos"},"lumos"),", a JavaScript/TypeScript framework, that aids dapp development on CKB. Lumos should be able to free you from most, if not all of the hassles for dealing with CKB, and let you focus on the specific logic in your dapp."),(0,i.kt)("p",null,"In this tutorial, we will provide an introduction on lumos via a real example: ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0023-dao-deposit-withdraw/0023-dao-deposit-withdraw.md"},"Nervos DAO"),", while quite valuable on CKB, can be a real pain to integrate for many dapps. Here we will demonstrate that how lumos can be used to streamline Nervos DAO integration."),(0,i.kt)("h2",{id:"components"},"Components"),(0,i.kt)("p",null,"Lumos is designed as a framework, meaning it is expected to be used in a intrinsic way: certain setup code will be needed when you first boot your application. Global states might also be kept in your application memory space for bookkeeping purposes. That being said, lumos is also organized into several components, some of which might be used in a non-intrinsic stateless fashion. In general, lumos consists of the following components:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/lumos/tree/v0.4.0/packages/indexer"},"indexer"),": a CKB cell indexer that fulfills ",(0,i.kt)("a",{parentName:"li",href:"../reference/cell#index-query-assemble-pattern"},"Index-Query-Assemble")," pattern. For now, this package only contains RocksDB backed indexer. A ",(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/lumos/tree/v0.4.0/packages/sql-indexer"},"separate package")," contains SQL backed indexer using the same interface. Later, we might merge the 2 packages into one for consistency."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/lumos/tree/v0.4.0/packages/base"},"base"),": a base package containing common types and utilities that are used by most packages. If there is a CKB specific task you need to perform, you might want to look here first. Chances are they are already provided."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/lumos/tree/v0.4.0/packages/helpers"},"helpers"),": a helper package containing more utilities. The difference between ",(0,i.kt)("inlineCode",{parentName:"li"},"helpers")," and ",(0,i.kt)("inlineCode",{parentName:"li"},"base"),", is that ",(0,i.kt)("inlineCode",{parentName:"li"},"base")," contains pure stateless functions, while ",(0,i.kt)("inlineCode",{parentName:"li"},"helpers")," works in a more intrinsic way: it requires ",(0,i.kt)("inlineCode",{parentName:"li"},"config-manager")," mentioned below to be setup."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/lumos/tree/v0.4.0/packages/common-scripts"},"common-scripts"),": integrations for known scripts on CKB. While we try our best to provide integrations for popular CKB scripts, people might be working on innovations everyday. As a result, we are also designing a set of APIs, so developers can freely integrate their own scripts into lumos for everyone to use. One integrated, ",(0,i.kt)("inlineCode",{parentName:"li"},"common-scripts")," should be able to leverage those new scripts as well."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/lumos/tree/v0.4.0/packages/config-manager"},"config-manager"),": a manager for dealing with differences between different chains, such as mainnet, testnet, or numerous dev chains. We abstract each chain into individual config file. Once loaded, config manager will be able to handle the chain specific logic, so you don't have to deal with this in your own code."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/nervosnetwork/lumos/tree/v0.4.0/packages/transaction-manager"},"transaction-manager"),": a transaction manager for CKB. One problem with UTXO based blockchains, is that a certain amount of gap period exists between a transaction is accepted by a blockchain, and when it is actually committed on chain. During this gap, new cells created by the pending transaction will not be available. Transaction manager package takes care of this. It wraps an indexer instance, and makes sure cells created in pending transactions, are also exposed and available for assembling new transactions. This means you are no longer bounded to one transaction at a time, you can freely send series of transactions as you wish.")),(0,i.kt)("h2",{id:"initial-ckb-setup"},"Initial CKB Setup"),(0,i.kt)("p",null,"To ease the whole process so we don't have to wait too long to see the results, let's setup our own dev chain with ",(0,i.kt)("a",{parentName:"p",href:"../basics/guides/devchain#4-adjust-the-parameters-to-shorten-the-block-interval-optional"},"tweaks"),":"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},'$ export TOP=$(pwd)\n# I\'m testing this on a Linux machine, if you use other platforms, please adjust\n# this accordingly.\n$ curl -LO https://github.com/nervosnetwork/ckb/releases/download/v0.33.0/ckb_v0.33.0_x86_64-unknown-linux-gnu.tar.gz\n$ tar xzf ckb_v0.33.0_x86_64-unknown-linux-gnu.tar.gz\n$ export PATH=$PATH:$TOP/ckb_v0.33.0_x86_64-unknown-linux-gnu\n$ ckb -V\nckb 0.33.0\n$ ckb init -C devnet -c dev\n$ ed devnet/specs/dev.toml <\n')),(0,i.kt)("p",null,"But this is only for demonstration purposes. There's nothing stopping you from copying the same code into a file that is then executed by node."),(0,i.kt)("h2",{id:"config-manager-setup"},"Config Manager Setup"),(0,i.kt)("p",null,"The first step in using lumos, is setting up config manager. Even though CKB has a unified programming model, different configurations would still be required for different chain instances, such as mainnet, testnet or dev chains. Config manager allows the node app to boot with a specific chain configuration, so other parts in lumos can consult config manager directly for information."),(0,i.kt)("p",null,"If you are using a well known chain configuration, you can use ",(0,i.kt)("inlineCode",{parentName:"p"},"LUMOS_CONFIG_NAME")," environment variable to setup config manager:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"$ LUMOS_CONFIG_NAME=LINA node --experimental-repl-await\nWelcome to Node.js v12.16.2.\nType \".help\" for more information.\n> const { initializeConfig, getConfig } = require(\"@ckb-lumos/config-manager\");\n> initializeConfig();\n> getConfig();\n{\n PREFIX: 'ckb',\n SCRIPTS: {\n SECP256K1_BLAKE160: {\n CODE_HASH: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8',\n HASH_TYPE: 'type',\n TX_HASH: '0x71a7ba8fc96349fea0ed3a5c47992e3b4084b031a42264a018e0072e8172e46c',\n INDEX: '0x0',\n DEP_TYPE: 'dep_group',\n SHORT_ID: 0\n },\n SECP256K1_BLAKE160_MULTISIG: {\n CODE_HASH: '0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8',\n HASH_TYPE: 'type',\n TX_HASH: '0x71a7ba8fc96349fea0ed3a5c47992e3b4084b031a42264a018e0072e8172e46c',\n INDEX: '0x1',\n DEP_TYPE: 'dep_group',\n SHORT_ID: 1\n },\n DAO: {\n CODE_HASH: '0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e',\n HASH_TYPE: 'type',\n TX_HASH: '0xe2fb199810d49a4d8beec56718ba2593b665db9d52299a0f9e6e75416d73ff5c',\n INDEX: '0x2',\n DEP_TYPE: 'code'\n }\n }\n}\n")),(0,i.kt)("p",null,"Supported well known configurations include:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"LINA"),": mainnet config;"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"AGGRON4"),": current testnet config. Note at certain time, we might reset testnet, in that case, lumos might be upgraded with new testnet configurations.")),(0,i.kt)("p",null,"However there might be cases, where you don't use a pre-defined configuration. For example, the dev chain we use here, does not have a pre-defined configuration. Lumos also supports setting up config manager via a local config file. You can use ",(0,i.kt)("inlineCode",{parentName:"p"},"LUMOS_CONFIG_FILE")," environment variable to point to the config file. If neither config variable is set, lumos will try to read config file from ",(0,i.kt)("inlineCode",{parentName:"p"},"config.json")," file in current directory."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},'$ cat < config.json\n{\n "PREFIX": "ckt",\n "SCRIPTS": {\n "SECP256K1_BLAKE160": {\n "CODE_HASH": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8",\n "HASH_TYPE": "type",\n "TX_HASH": "0xace5ea83c478bb866edf122ff862085789158f5cbff155b7bb5f13058555b708",\n "INDEX": "0x0",\n "DEP_TYPE": "dep_group",\n "SHORT_ID": 0\n },\n "SECP256K1_BLAKE160_MULTISIG": {\n "CODE_HASH": "0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8",\n "HASH_TYPE": "type",\n "TX_HASH": "0xace5ea83c478bb866edf122ff862085789158f5cbff155b7bb5f13058555b708",\n "INDEX": "0x1",\n "DEP_TYPE": "dep_group",\n "SHORT_ID": 1\n },\n "DAO": {\n "CODE_HASH": "0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e",\n "HASH_TYPE": "type",\n "TX_HASH": "0xa563884b3686078ec7e7677a5f86449b15cf2693f3c1241766c6996f206cc541",\n "INDEX": "0x2",\n "DEP_TYPE": "code"\n }\n }\n}\nEOF\n$ LUMOS_CONFIG_FILE="config.json" node --experimental-repl-await\nWelcome to Node.js v12.16.2.\nType ".help" for more information.\n> const { initializeConfig, getConfig } = require("@ckb-lumos/config-manager");\n> initializeConfig();\n')),(0,i.kt)("p",null,"Now config manager is successfully setup, we can proceed to the next step."),(0,i.kt)("h2",{id:"booting-indexer"},"Booting Indexer"),(0,i.kt)("p",null,"Lumos is designed based on the ",(0,i.kt)("a",{parentName:"p",href:"../reference/cell#index-query-assemble-pattern"},"Index-Query-Assemble")," pattern, meaning a dapp shall have an indexer that keeps indexing new blocks in a format that is easier to query. This means any dapp built with lumos, should also have an indexer configured and running at all time:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},'> const { Indexer } = require("@ckb-lumos/indexer");\n> const indexer = new Indexer("http://127.0.0.1:8114", "./indexed-data");\n> indexer.startForever();\n')),(0,i.kt)("p",null,"Here we are using the RocksDB backed indexer for simplicity. Lumos provides 2 indexer types:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"RocksDB backed indexer"),(0,i.kt)("li",{parentName:"ul"},"SQL backed indexer, supported SQL databases now include MySQL and PostgreSQL.")),(0,i.kt)("p",null,"If you want to test against the SQL indexer, some modifications to the above setup code might be required."),(0,i.kt)("p",null,"You can check current indexed tip with the following code snippet:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},'> await indexer.tip()\n{\n block_number: "0x29c",\n block_hash: "0x3e44b571c82a09117231baee1939d38440d71f56de8bc600ac32b1dead9be46d"\n}\n')),(0,i.kt)("p",null,"Please wait a while till lumos has caught up with the current chain tip. This should not take much time for a dev chain."),(0,i.kt)("h2",{id:"deposit"},"Deposit"),(0,i.kt)("p",null,"To deposit to Nervos DAO, we need to first create a deposit transaction. You could of course go the hard way and create a transaction manually, but lumos has already provide a solution for simplifying transaction creation. Let's look at ",(0,i.kt)("inlineCode",{parentName:"p"},"TransactionSkeleton")," and how it works in lumos first."),(0,i.kt)("h3",{id:"transaction-skeleton"},"Transaction Skeleton"),(0,i.kt)("p",null,"CKB provides great flexibility for dapp developers to build anything they want. But we all know that ",(0,i.kt)("strong",{parentName:"p"},"with great power comes great responsibility"),", a flexible programming model also significantly complicates transaction assembling. This includes but might not be limited to the following hurdles:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Different scripts used in transaction inputs will require separate message generation, and also separate signing steps."),(0,i.kt)("li",{parentName:"ul"},"Some cells might require special argument setup in witness, due to type script validation rules."),(0,i.kt)("li",{parentName:"ul"},"Coordination might be required, since both lock script and type script in a cell might require arguments in the same witness construct.")),(0,i.kt)("p",null,"Those problems will haunt you even when you are dealing with a single NervosDAO transaction. It is only gonna get more complicated, when we consider multiple cells containing different CKB scripts composed together. Looking into the future, we will definitely need a solution to this issue."),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"TransactionSkeleton")," is the answer we propose in lumos. Each transaction skeleton corresponds to an action, and will be built into a single transaction that is ready to be submitted to CKB. Surrounding the idea of TransactionSkeleton, a series of conveniences are provided to aid transaction assembling:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"A well designed component should automatically query and include cells to provide capacities required by the transaction."),(0,i.kt)("li",{parentName:"ul"},"Individual script logic should be managed and respected by the general transaction skeleton."),(0,i.kt)("li",{parentName:"ul"},"Scripts sharing the same behavior should be managed together in a unified interface. Developers can rely on abstractions instead of catering for every single detail.")),(0,i.kt)("p",null,"This still sounds quite complicated, let's walkthrough an example to see how we can leverage TransactionSkeleton."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},'> // In practice, you might already have the address at your hand, here we just\n> // want to demonstrate how this works.\n> const script = {\n code_hash: "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8",\n hash_type: "type",\n args: "0xcbfbb9edb5838e2d61061c3fc69eaaa5fdbd3273"\n};\n> const {generateAddress, parseAddress, createTransactionFromSkeleton,\n sealTransaction, TransactionSkeleton } = require("@ckb-lumos/helpers");\n> const address = generateAddress(script);\n\n> // Now let\'s create the actual skeleton, and deposit CKBytes into the skeleton\n> let skeleton = TransactionSkeleton({ cellProvider: indexer });\n> const { secp256k1Blake160, dao } = require("@ckb-lumos/common-scripts");\n\n> // Using utility provided in common-scripts, let\'s deposit 1000 CKBytes into\n> // the skeleton. We will introduce common-scripts separately below. Here we are\n> // using the same address as from and to, but this does not have to be the case\n> // everywhere.\n> skeleton = await dao.deposit(skeleton, address, address, 100000000000n);\n\n> // createTransactionFromSkeleton is designed to build a final transaction, but\n> // there is nothing stopping you from using it to peek into the current skeleton.\n> console.log(JSON.stringify(createTransactionFromSkeleton(skeleton), null, 2));\n\n> // But this transaction is not yet complete, we still need 2 parts:\n> // * Transaction fee is not taken into consideration\n> // * The transaction is not signed yet\n> // Let\'s take a look at them separately.\n\n> // First, since we are using the default secp256k1-blake160 lock script, an\n> // existing module in common-scripts can be leveraged to incur transaction\n> // fee. Here we are using the same address to provide 1 CKByte as transaction\n> // fee.\n> skeleton = await secp256k1Blake160.payFee(skeleton, address, 100000000n);\n\n> // If you checked the transaction skeleton after incurring fees. You will\n> // notice that it only has one input. This might raise a question: if NervoDAO\n> // deposit consumes one input cell, transaction fee requires a different input\n> // cell, shouldn\'t there be 2 input cells with 3 output cells(a deposited cell,\n> // and 2 change cell)? The trick here, is that common-scripts is smart enough\n> // to figure out that the 2 actions here use the same address. Hence it just\n> // rewrite the change cell generated in the NervosDAO deposit action to pay\n> // enough transaction fee.\n> createTransactionFromSkeleton(skeleton).inputs.length;\n1\n\n> // Now the transaction is more or less complete, we can start generate messages\n> // used for signing.\n> skeleton = secp256k1Blake160.prepareSigningEntries(skeleton);\n> // This method actually loops through the skeleton, and create `signingEntries`\n> // that are using the default secp256k1-blake160 lock script:\n> skeleton.get("signingEntries").toArray();\n[\n {\n type: \'witness_args_lock\',\n index: 0,\n message: \'0x40811fd6ed74b9042f603dc7f2f577da7ebe0e05175d349dbb5c539b1111b83f\'\n }\n]\n')),(0,i.kt)("p",null,"Lumos, for now, does not handle message signing for the following reasons:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"This is a serious matter that relates to the overall security of the dapp, we want to make sure we are doing this properly if/when we decide to do it."),(0,i.kt)("li",{parentName:"ul"},"Different dapps might have different requirements, some don't do signing at all, having signing built-in might render certain dapps hard to build.")),(0,i.kt)("p",null,"Using a secp256k1 tool, it's not hard to generate a signature here based on the private key listed above, and the message. And we can continue with this process:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},'> const signatures = ["0x1cb952fd224d1d14d07af621587e91a65ccb051d55ed1371b3b66d4fe169cf7758173882e4c02587cb54054d2de287cbb1fdc2fc21d848d7b320ee8c5826479901"];\n> const tx = sealTransaction(skeleton, signatures);\n')),(0,i.kt)("p",null,"Now we have a complete transaction assembled, and we can send it to CKB:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},'> const { RPC } = require("ckb-js-toolkit");\n> const rpc = new RPC("http://127.0.0.1:8114");\n> await rpc.send_transaction(tx);\n\'0x88536e8c25f5f8c89866dec6a5a1a6a72cccbe282963e4a7bfb5542b4c15d376\'\n')),(0,i.kt)("p",null,"Now we have successfully deposited CKBytes into CKB using lumos!"),(0,i.kt)("h2",{id:"withdraw"},"Withdraw"),(0,i.kt)("p",null,"The following code can help us list all deposited Nervos DAO cells for an address:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"> for await (const cell of dao.listDaoCells(indexer, address, \"deposit\")) { console.log(cell); }\n{\n cell_output: {\n capacity: '0x174876e800',\n lock: {\n code_hash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8',\n hash_type: 'type',\n args: '0xcbfbb9edb5838e2d61061c3fc69eaaa5fdbd3273'\n },\n type: {\n code_hash: '0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e',\n hash_type: 'type',\n args: '0x'\n }\n },\n out_point: {\n tx_hash: '0x88536e8c25f5f8c89866dec6a5a1a6a72cccbe282963e4a7bfb5542b4c15d376',\n index: '0x0'\n },\n block_hash: '0xa1ec7dc291774bc0fc229efba4a162c099a8d88ffa7ae2fa410cc574e0701ced',\n block_number: '0x196',\n data: '0x0000000000000000'\n}\n")),(0,i.kt)("p",null,"Here we can find the cell we just deposited to Nervos DAO. Let's now try to withdraw it from Nervos DAO:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"> // First, we will need to locate the cell. In a real dapp this is most likely\n> // coming from user selection.\n> const cell = (await dao.listDaoCells(indexer, address, \"deposit\").next()).value;\n> // For a new action, let's create a new transaction skeleton\n> skeleton = TransactionSkeleton({ cellProvider: indexer });\n> // This time, we invoke withdraw method to prepare a withdraw skeleton\n> skeleton = await dao.withdraw(skeleton, cell, address);\n> // Fees are also necessary\n> skeleton = await secp256k1Blake160.payFee(skeleton, address, 100000000n);\n> // And let's generate signing entries again.\n> skeleton = secp256k1Blake160.prepareSigningEntries(skeleton);\n> skeleton.get(\"signingEntries\").toArray();\n[\n {\n type: 'witness_args_lock',\n index: 0,\n message: '0x24370c5cedc03c34ae0a00a10d9e62324bce07e8d155c839ff10991d73684c34'\n }\n]\n> // After we signed the message, we can get the signature:\n> const signatures2 = [\"0x5aed4480c82844506fefc1d92dd18422a123b8e880018ea4cfa7f95891c4781e6578facedd765676831cf3cca04492ec3ec3885ac8d0b6d90cb6c1d6f99e6ffb01\"];\n> // Now we can seal and send the transaction\n> const tx2 = sealTransaction(skeleton, signatures2);\n> await rpc.send_transaction(tx2);\n'0xe411eb6a3cf4f659461cc7a9df9ff95a72b9624bf850b9ccad0c4d7f2ab444f6'\n")),(0,i.kt)("p",null,"See that withdrawing transaction is not so hard!"),(0,i.kt)("h3",{id:"locktime-pool"},"Locktime Pool"),(0,i.kt)("p",null,"We could've just showed the ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/lumos/blob/ac96a3220ab2a148425120eaac216abe246ee1da/packages/common-scripts/index.d.ts#L262"},"unlock")," method in ",(0,i.kt)("inlineCode",{parentName:"p"},"dao")," module, which let you complete the withdrawing from Nervos DAO. But here I want to talk about a different construct in lumos: locktime pool."),(0,i.kt)("p",null,"If you look closer, you would notice that the cell consumed in ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0023-dao-deposit-withdraw/0023-dao-deposit-withdraw.md#withdraw-phase-2"},"withdraw phase 2"),", is really nothing but a cell with a certain lock period. Likewise, there might be other scripts on CKB, when combined with certain cell, just provide lock periods. The multisig script included in genesis cell, is one such example. So the idea arises: what if we build a unified pool, that handles all cells that have lock periods? When designed properly, we can ignore the fact that they might come from different dapps, using different scripts. What we do care, is that each of those cells comes with a capacity and lock period, when the lock period is reached, they are nothing but ordinary cells in one's wallet."),(0,i.kt)("p",null,"Given this thought, we designed ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime pool")," in lumos. Right now it only processes Nervos DAO cells in withdraw phase 2 and multisig cells, but in the future there is nothing stopping us from integrating more scripts that provide lock periods. From a developer point of view, locktime pool, can be used to manage all of them, provide a unified view in dapps."),(0,i.kt)("p",null,"As usual, we can query for all cells currently in the locktime pool:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"> const { locktimePool } = require(\"@ckb-lumos/common-scripts\");\n> for await (const cell of locktimePool.collectCells(indexer, address)) { console.log(cell); }\n{\n cell_output: {\n capacity: '0x174876e800',\n lock: {\n code_hash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8',\n hash_type: 'type',\n args: '0xcbfbb9edb5838e2d61061c3fc69eaaa5fdbd3273'\n },\n type: {\n code_hash: '0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e',\n hash_type: 'type',\n args: '0x'\n }\n },\n out_point: {\n tx_hash: '0xe411eb6a3cf4f659461cc7a9df9ff95a72b9624bf850b9ccad0c4d7f2ab444f6',\n index: '0x0'\n },\n block_hash: '0xb468ec0a1aed1f7070fc00952453ac882dbe36b1afbfb520c822fe46b3b81dfe',\n block_number: '0x543',\n data: '0x9601000000000000',\n maximumCapacity: 100153459536n,\n since: '0x20000a00060000dc',\n depositBlockHash: '0xa1ec7dc291774bc0fc229efba4a162c099a8d88ffa7ae2fa410cc574e0701ced',\n withdrawBlockHash: '0xb468ec0a1aed1f7070fc00952453ac882dbe36b1afbfb520c822fe46b3b81dfe',\n sinceBaseValue: undefined\n}\n")),(0,i.kt)("p",null,"Here we can found the cell just created from NervosDAO withdrawing step. Let's try to consume it using locktimePool:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},'> // Notice you will wait till the lock period of the cell has passed, otherwise this function would throw an error:\n> skeleton = await locktimePool.transfer(skeleton, [address], address, 100153459536n, (await rpc.get_tip_header()));\n> console.log(JSON.stringify(createTransactionFromSkeleton(skeleton), null, 2));\n{\n "version": "0x0",\n "cell_deps": [],\n "header_deps": [],\n "inputs": [],\n "outputs": [],\n "outputs_data": [],\n "witnesses": []\n}\n')),(0,i.kt)("p",null,"This might actually be a surprise: we invoked transfer method, but it does nothing! Turns out the reason here, is that we are using the same address as both transfer input, and transfer output. Lumos is smart enough to figure out that when you are using the same input and output, we don't need to perform the action so as to save certain transaction fee."),(0,i.kt)("p",null,"One different question you might ask, is that we use the same address in deposit and withdraw steps, why those previous attempts work? The reason for this, is that deposited cell, or created cell in withdraw step 1 has special purposes, they represent unique ",(0,i.kt)("strong",{parentName:"p"},"actions")," that we want to perform, hence they are ",(0,i.kt)("strong",{parentName:"p"},"freezed")," in the transaction skeleton, so later when we optimize the transaction to combine inputs/outputs, we won't touch those specially created cells. On the other hand, in locktime pool design, we treat a cell with expired lock period the same as a normal cell, they really have nothing different, hence here, lumos will try to optimize the transaction, by removing the action transferring amount from an address to itself. In lumos' eye, this is a no-op."),(0,i.kt)("p",null,"Now let's try the same step using a different target address:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"> skeleton = await locktimePool.transfer(skeleton, [address], \"ckt1qyqx57xrsztnq7g5mlw6r998uyc2f5hm3vnsvgsaet\", 100153459536n, (await rpc.get_tip_header()));\n> skeleton = await secp256k1Blake160.payFee(skeleton, address, 100000000n);\n> skeleton = secp256k1Blake160.prepareSigningEntries(skeleton);\n> skeleton.get(\"signingEntries\").toArray();\n[\n {\n type: 'witness_args_lock',\n index: 0,\n message: '0xf01fb9988ba0265597760f50df92a56162d650b119cc95e8508079af584bdbc7'\n }\n]\n")),(0,i.kt)("p",null,"We can generate the signature as always:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"> const signatures3 = [\"0x6edde41592b41d445fabfd1b1d6854cf643bba724a338b5751827d991affa5a979d12339250bf5ade45f7f2742cba1e3de0791e37ef03914459bcdd099908ec601\"];\n> const tx3 = sealTransaction(skeleton, signatures3);\n> await rpc.send_transaction(tx3);\n'0xbaa7bdd71b7ec975f5a75c49d300857981f333c4346d6d6de1297d8d9d9ce0e0'\n")),(0,i.kt)("p",null,"This is really the core part of this post, if you are not understanding this part, we recommend you to read it again, and try it in CKB by yourself. What we are showing here, is that by designing a set of common APIs, we can build a general facility, that manages many different script instances, given the fact that they share the same behavior. And it is really not only the secp256k1-blake160 single signing script that shall be managed by a wallet. Any scripts that follow certain behavior, can be treated as a cell managed in a wallet."),(0,i.kt)("h2",{id:"common-script"},"Common Script"),(0,i.kt)("p",null,"As we show above, locktime pool is one step ahead of the journey at managing different cells/scripts with similar behaviors. But we are not stopping here, we can continue further down the path: it is mentioned above, that those cells with lock period already passed, can be thought as normal cells. Can we treat them as usual, without needing to deal with locktime pool?"),(0,i.kt)("p",null,"We have build ",(0,i.kt)("inlineCode",{parentName:"p"},"common")," module for this. Given a set of address/configurations(since for some P2SH script, address alone won't be enough), it can manage all cells using those scripts, including cells with expired lock period. Right now this includes the following:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"secp256k1-blake160 single signing script"),(0,i.kt)("li",{parentName:"ul"},"secp256k1-blake160 multiple signing script"),(0,i.kt)("li",{parentName:"ul"},"NervosDAO script(only cells in withdraw phase 2 are managed)")),(0,i.kt)("p",null,"And the list doesn't stop here, we are working to provide a common API specification, that once implemented, can enable ",(0,i.kt)("inlineCode",{parentName:"p"},"common")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime pool")," to support those additional scripts as well. We do hope those 2 modules can help enable a unified cell manager in lumos, in which ",(0,i.kt)("inlineCode",{parentName:"p"},"common")," handles all consumable cells, while ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime pool")," gives insights into cells that are locked now but will be usable in the future."),(0,i.kt)("h2",{id:"recap"},"Recap"),(0,i.kt)("p",null,"Lumos aims to take care of the full lifecycle of your CKB dapp. In this post, we are just taking a sneak peek at all the powers. We will continue to work on documents as well as sample projects to showcase all the powers enabled by lumos. We welcome all of you to try out lumos, and tell us what you think of it. So we can continue enhancing it, to make it the beloved framework for building CKB dapps."))}h.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/runtime~main.6eb3c6f5.js b/assets/js/runtime~main.8ba77859.js similarity index 55% rename from assets/js/runtime~main.6eb3c6f5.js rename to assets/js/runtime~main.8ba77859.js index 118151ba7..77498b42b 100644 --- a/assets/js/runtime~main.6eb3c6f5.js +++ b/assets/js/runtime~main.8ba77859.js @@ -1 +1 @@ -(()=>{"use strict";var e,b,a,f,c={},r={};function d(e){var b=r[e];if(void 0!==b)return b.exports;var a=r[e]={exports:{}};return c[e].call(a.exports,a,a.exports,d),a.exports}d.m=c,e=[],d.O=(b,a,f,c)=>{if(!a){var r=1/0;for(i=0;i=c)&&Object.keys(d.O).every((e=>d.O[e](a[o])))?a.splice(o--,1):(t=!1,c0&&e[i-1][2]>c;i--)e[i]=e[i-1];e[i]=[a,f,c]},d.n=e=>{var b=e&&e.__esModule?()=>e.default:()=>e;return d.d(b,{a:b}),b},a=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,d.t=function(e,f){if(1&f&&(e=this(e)),8&f)return e;if("object"==typeof e&&e){if(4&f&&e.__esModule)return e;if(16&f&&"function"==typeof e.then)return e}var c=Object.create(null);d.r(c);var r={};b=b||[null,a({}),a([]),a(a)];for(var t=2&f&&e;"object"==typeof t&&!~b.indexOf(t);t=a(t))Object.getOwnPropertyNames(t).forEach((b=>r[b]=()=>e[b]));return r.default=()=>e,d.d(c,r),c},d.d=(e,b)=>{for(var a in b)d.o(b,a)&&!d.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:b[a]})},d.f={},d.e=e=>Promise.all(Object.keys(d.f).reduce(((b,a)=>(d.f[a](e,b),b)),[])),d.u=e=>"assets/js/"+({53:"935f2afb",409:"054a0a32",482:"5a37071a",610:"696ee830",669:"0feb03eb",703:"b541bfa9",728:"c0cedf52",953:"087210fe",1432:"4ef42647",1563:"ebf8ab85",1773:"d19a1628",2059:"4b2e3693",2085:"f03c4687",2205:"5e2b223b",2332:"62f186d4",2347:"01a1c591",2401:"b2dbc2be",2645:"588203d5",2903:"62c546c3",3124:"2d8051d4",3326:"0223c8b7",3771:"d43007af",3799:"6e38a461",3906:"d78fab64",4094:"5dc0a998",4195:"c4f5d8e4",4288:"51ce6456",4615:"1246b634",4673:"6d9f7284",4726:"11fdc039",4793:"b9403f6d",5143:"540b5dcd",5549:"f340be0f",5611:"0d25d5de",5741:"6ee80bbf",6049:"8af0162e",6146:"bfc39627",6167:"4d39e3ea",6174:"e3b31ca8",6592:"7acc5651",6917:"3ede27e6",7002:"23ce2864",7039:"6146ab48",7220:"eb8849dd",7274:"0bbc4f18",7277:"2c43fa15",7390:"b6e9640d",7702:"81e2e379",7818:"176b9270",7850:"987d1510",7918:"17896441",7920:"1a4e3797",8158:"ffbe244f",8225:"43c4bbc7",8277:"fa6c22b7",8336:"49efc93a",8491:"d4b35ab3",8793:"be9f0b28",9021:"b67aa53b",9190:"98916265",9351:"ea4491db",9514:"1be78505",9591:"e9813fd7",9620:"342f0ebc",9670:"6b0715fe"}[e]||e)+"."+{53:"d460d2d5",409:"17f280ba",482:"6a2aee74",610:"83bf38ca",669:"034b3dc5",703:"7c954c96",728:"df6668ee",953:"75450ff3",1432:"7fab5b41",1563:"2f4f4279",1773:"2b4144a5",2059:"91b3b02e",2085:"98254ba4",2205:"15433e20",2332:"481ef8b1",2347:"3be568dd",2401:"59b03a93",2645:"2858642c",2903:"ba2b704b",3124:"3900ff6b",3326:"6b37e9d2",3771:"1f5f1522",3799:"c5b7257e",3906:"6b1f98f5",4094:"ff8e05bc",4195:"1547c3df",4288:"d2084750",4615:"40c5715f",4673:"2f0c9ec9",4726:"8b887f35",4793:"38e775d0",4972:"a84f38bd",5143:"b7753841",5549:"b9adad38",5611:"cf5ece44",5741:"f0f3d2e5",6049:"755af75f",6146:"c7d77102",6167:"ae32c8c1",6174:"e78e4c4a",6592:"0c9fd5ad",6780:"0da41e21",6917:"5b92d2e7",6945:"29c43de0",7002:"d886231b",7039:"fe93ba7d",7220:"d15518dd",7274:"ba02cbba",7277:"31f9975a",7390:"fd856dc2",7702:"80b0f84e",7818:"44274b31",7850:"41bebe8f",7918:"ef281941",7920:"096f3e09",8158:"7b20f12d",8225:"02c38278",8277:"0c1412e8",8336:"e5719967",8491:"e25b8a9a",8793:"0e17e316",8894:"143a3960",9021:"3b2ba6ee",9190:"fb9290c4",9351:"c824d6cf",9514:"6481fdeb",9591:"b7353df6",9620:"f06d41c2",9670:"f31a6605"}[e]+".js",d.miniCssF=e=>{},d.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),d.o=(e,b)=>Object.prototype.hasOwnProperty.call(e,b),f={},d.l=(e,b,a,c)=>{if(f[e])f[e].push(b);else{var r,t;if(void 0!==a)for(var o=document.getElementsByTagName("script"),n=0;n{r.onerror=r.onload=null,clearTimeout(l);var c=f[e];if(delete f[e],r.parentNode&&r.parentNode.removeChild(r),c&&c.forEach((e=>e(a))),b)return b(a)},l=setTimeout(u.bind(null,void 0,{type:"timeout",target:r}),12e4);r.onerror=u.bind(null,r.onerror),r.onload=u.bind(null,r.onload),t&&document.head.appendChild(r)}},d.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},d.p="/",d.gca=function(e){return e={17896441:"7918",98916265:"9190","935f2afb":"53","054a0a32":"409","5a37071a":"482","696ee830":"610","0feb03eb":"669",b541bfa9:"703",c0cedf52:"728","087210fe":"953","4ef42647":"1432",ebf8ab85:"1563",d19a1628:"1773","4b2e3693":"2059",f03c4687:"2085","5e2b223b":"2205","62f186d4":"2332","01a1c591":"2347",b2dbc2be:"2401","588203d5":"2645","62c546c3":"2903","2d8051d4":"3124","0223c8b7":"3326",d43007af:"3771","6e38a461":"3799",d78fab64:"3906","5dc0a998":"4094",c4f5d8e4:"4195","51ce6456":"4288","1246b634":"4615","6d9f7284":"4673","11fdc039":"4726",b9403f6d:"4793","540b5dcd":"5143",f340be0f:"5549","0d25d5de":"5611","6ee80bbf":"5741","8af0162e":"6049",bfc39627:"6146","4d39e3ea":"6167",e3b31ca8:"6174","7acc5651":"6592","3ede27e6":"6917","23ce2864":"7002","6146ab48":"7039",eb8849dd:"7220","0bbc4f18":"7274","2c43fa15":"7277",b6e9640d:"7390","81e2e379":"7702","176b9270":"7818","987d1510":"7850","1a4e3797":"7920",ffbe244f:"8158","43c4bbc7":"8225",fa6c22b7:"8277","49efc93a":"8336",d4b35ab3:"8491",be9f0b28:"8793",b67aa53b:"9021",ea4491db:"9351","1be78505":"9514",e9813fd7:"9591","342f0ebc":"9620","6b0715fe":"9670"}[e]||e,d.p+d.u(e)},(()=>{var e={1303:0,532:0};d.f.j=(b,a)=>{var f=d.o(e,b)?e[b]:void 0;if(0!==f)if(f)a.push(f[2]);else if(/^(1303|532)$/.test(b))e[b]=0;else{var c=new Promise(((a,c)=>f=e[b]=[a,c]));a.push(f[2]=c);var r=d.p+d.u(b),t=new Error;d.l(r,(a=>{if(d.o(e,b)&&(0!==(f=e[b])&&(e[b]=void 0),f)){var c=a&&("load"===a.type?"missing":a.type),r=a&&a.target&&a.target.src;t.message="Loading chunk "+b+" failed.\n("+c+": "+r+")",t.name="ChunkLoadError",t.type=c,t.request=r,f[1](t)}}),"chunk-"+b,b)}},d.O.j=b=>0===e[b];var b=(b,a)=>{var f,c,[r,t,o]=a,n=0;if(r.some((b=>0!==e[b]))){for(f in t)d.o(t,f)&&(d.m[f]=t[f]);if(o)var i=o(d)}for(b&&b(a);n{"use strict";var e,f,b,a,c={},r={};function d(e){var f=r[e];if(void 0!==f)return f.exports;var b=r[e]={exports:{}};return c[e].call(b.exports,b,b.exports,d),b.exports}d.m=c,e=[],d.O=(f,b,a,c)=>{if(!b){var r=1/0;for(i=0;i=c)&&Object.keys(d.O).every((e=>d.O[e](b[o])))?b.splice(o--,1):(t=!1,c0&&e[i-1][2]>c;i--)e[i]=e[i-1];e[i]=[b,a,c]},d.n=e=>{var f=e&&e.__esModule?()=>e.default:()=>e;return d.d(f,{a:f}),f},b=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,d.t=function(e,a){if(1&a&&(e=this(e)),8&a)return e;if("object"==typeof e&&e){if(4&a&&e.__esModule)return e;if(16&a&&"function"==typeof e.then)return e}var c=Object.create(null);d.r(c);var r={};f=f||[null,b({}),b([]),b(b)];for(var t=2&a&&e;"object"==typeof t&&!~f.indexOf(t);t=b(t))Object.getOwnPropertyNames(t).forEach((f=>r[f]=()=>e[f]));return r.default=()=>e,d.d(c,r),c},d.d=(e,f)=>{for(var b in f)d.o(f,b)&&!d.o(e,b)&&Object.defineProperty(e,b,{enumerable:!0,get:f[b]})},d.f={},d.e=e=>Promise.all(Object.keys(d.f).reduce(((f,b)=>(d.f[b](e,f),f)),[])),d.u=e=>"assets/js/"+({53:"935f2afb",409:"054a0a32",482:"5a37071a",610:"696ee830",669:"0feb03eb",703:"b541bfa9",728:"c0cedf52",953:"087210fe",1432:"4ef42647",1563:"ebf8ab85",1773:"d19a1628",2059:"4b2e3693",2085:"f03c4687",2205:"5e2b223b",2332:"62f186d4",2347:"01a1c591",2401:"b2dbc2be",2645:"588203d5",2903:"62c546c3",3124:"2d8051d4",3326:"0223c8b7",3771:"d43007af",3799:"6e38a461",3906:"d78fab64",4094:"5dc0a998",4195:"c4f5d8e4",4288:"51ce6456",4615:"1246b634",4673:"6d9f7284",4726:"11fdc039",4793:"b9403f6d",5143:"540b5dcd",5549:"f340be0f",5611:"0d25d5de",5741:"6ee80bbf",6049:"8af0162e",6146:"bfc39627",6167:"4d39e3ea",6174:"e3b31ca8",6592:"7acc5651",6917:"3ede27e6",7002:"23ce2864",7039:"6146ab48",7220:"eb8849dd",7274:"0bbc4f18",7277:"2c43fa15",7390:"b6e9640d",7702:"81e2e379",7818:"176b9270",7850:"987d1510",7918:"17896441",7920:"1a4e3797",8158:"ffbe244f",8225:"43c4bbc7",8277:"fa6c22b7",8336:"49efc93a",8491:"d4b35ab3",8793:"be9f0b28",9021:"b67aa53b",9190:"98916265",9351:"ea4491db",9514:"1be78505",9591:"e9813fd7",9620:"342f0ebc",9670:"6b0715fe"}[e]||e)+"."+{53:"d460d2d5",409:"17f280ba",482:"6a2aee74",610:"83bf38ca",669:"034b3dc5",703:"7c954c96",728:"df6668ee",953:"75450ff3",1432:"7fab5b41",1563:"2f4f4279",1773:"2b4144a5",2059:"e95acd7d",2085:"98254ba4",2205:"a4c94edd",2332:"481ef8b1",2347:"3be568dd",2401:"59b03a93",2645:"2858642c",2903:"ba2b704b",3124:"3900ff6b",3326:"6b37e9d2",3771:"1f5f1522",3799:"c5b7257e",3906:"6b1f98f5",4094:"ff8e05bc",4195:"9f338d1a",4288:"d2084750",4615:"40c5715f",4673:"323f24f9",4726:"8b887f35",4793:"38e775d0",4972:"a84f38bd",5143:"b7753841",5549:"b9adad38",5611:"cf5ece44",5741:"f0f3d2e5",6049:"56b325a5",6146:"c7d77102",6167:"ae32c8c1",6174:"e78e4c4a",6592:"0c9fd5ad",6780:"0da41e21",6917:"5b92d2e7",6945:"29c43de0",7002:"d886231b",7039:"fe93ba7d",7220:"d15518dd",7274:"ba02cbba",7277:"207825b9",7390:"fd856dc2",7702:"80b0f84e",7818:"7e62e9ca",7850:"41bebe8f",7918:"ef281941",7920:"096f3e09",8158:"afde17d8",8225:"02c38278",8277:"0c1412e8",8336:"e5719967",8491:"e25b8a9a",8793:"0e17e316",8894:"143a3960",9021:"3b2ba6ee",9190:"77c49894",9351:"c824d6cf",9514:"6481fdeb",9591:"3a0b3c40",9620:"f06d41c2",9670:"f31a6605"}[e]+".js",d.miniCssF=e=>{},d.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),d.o=(e,f)=>Object.prototype.hasOwnProperty.call(e,f),a={},d.l=(e,f,b,c)=>{if(a[e])a[e].push(f);else{var r,t;if(void 0!==b)for(var o=document.getElementsByTagName("script"),n=0;n{r.onerror=r.onload=null,clearTimeout(l);var c=a[e];if(delete a[e],r.parentNode&&r.parentNode.removeChild(r),c&&c.forEach((e=>e(b))),f)return f(b)},l=setTimeout(u.bind(null,void 0,{type:"timeout",target:r}),12e4);r.onerror=u.bind(null,r.onerror),r.onload=u.bind(null,r.onload),t&&document.head.appendChild(r)}},d.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},d.p="/",d.gca=function(e){return e={17896441:"7918",98916265:"9190","935f2afb":"53","054a0a32":"409","5a37071a":"482","696ee830":"610","0feb03eb":"669",b541bfa9:"703",c0cedf52:"728","087210fe":"953","4ef42647":"1432",ebf8ab85:"1563",d19a1628:"1773","4b2e3693":"2059",f03c4687:"2085","5e2b223b":"2205","62f186d4":"2332","01a1c591":"2347",b2dbc2be:"2401","588203d5":"2645","62c546c3":"2903","2d8051d4":"3124","0223c8b7":"3326",d43007af:"3771","6e38a461":"3799",d78fab64:"3906","5dc0a998":"4094",c4f5d8e4:"4195","51ce6456":"4288","1246b634":"4615","6d9f7284":"4673","11fdc039":"4726",b9403f6d:"4793","540b5dcd":"5143",f340be0f:"5549","0d25d5de":"5611","6ee80bbf":"5741","8af0162e":"6049",bfc39627:"6146","4d39e3ea":"6167",e3b31ca8:"6174","7acc5651":"6592","3ede27e6":"6917","23ce2864":"7002","6146ab48":"7039",eb8849dd:"7220","0bbc4f18":"7274","2c43fa15":"7277",b6e9640d:"7390","81e2e379":"7702","176b9270":"7818","987d1510":"7850","1a4e3797":"7920",ffbe244f:"8158","43c4bbc7":"8225",fa6c22b7:"8277","49efc93a":"8336",d4b35ab3:"8491",be9f0b28:"8793",b67aa53b:"9021",ea4491db:"9351","1be78505":"9514",e9813fd7:"9591","342f0ebc":"9620","6b0715fe":"9670"}[e]||e,d.p+d.u(e)},(()=>{var e={1303:0,532:0};d.f.j=(f,b)=>{var a=d.o(e,f)?e[f]:void 0;if(0!==a)if(a)b.push(a[2]);else if(/^(1303|532)$/.test(f))e[f]=0;else{var c=new Promise(((b,c)=>a=e[f]=[b,c]));b.push(a[2]=c);var r=d.p+d.u(f),t=new Error;d.l(r,(b=>{if(d.o(e,f)&&(0!==(a=e[f])&&(e[f]=void 0),a)){var c=b&&("load"===b.type?"missing":b.type),r=b&&b.target&&b.target.src;t.message="Loading chunk "+f+" failed.\n("+c+": "+r+")",t.name="ChunkLoadError",t.type=c,t.request=r,a[1](t)}}),"chunk-"+f,f)}},d.O.j=f=>0===e[f];var f=(f,b)=>{var a,c,[r,t,o]=b,n=0;if(r.some((f=>0!==e[f]))){for(a in t)d.o(t,a)&&(d.m[a]=t[a]);if(o)var i=o(d)}for(f&&f(b);n Community Nodes | Nervos CKB - +

Community Nodes

Developers on the CKB can test and build their projects by accessing the service through the API nodes granted by Nervos.

note

If your RPC is remotely accessible, restrict access to the following interfaces when running CKB nodes:

clear_banned_addresses
set_ban
set_network_active
add_node
remove_node
remove_transaction
clear_tx_pool

Ankr

Ankr is a decentralized Web3 infrastructure provider offering a distributed node infrastructure that supports a multi-chain network to help developers interact with multiple blockchains. CKB developers can now access the Ankr API and RPC to test or build their own DApps.

- + \ No newline at end of file diff --git a/docs/basics/concepts/cell-model/index.html b/docs/basics/concepts/cell-model/index.html index 5ad0484e3..d002a0f8f 100644 --- a/docs/basics/concepts/cell-model/index.html +++ b/docs/basics/concepts/cell-model/index.html @@ -14,13 +14,13 @@ Cell Model | Nervos CKB - +
-

Cell Model

What is a Cell?

Cell is the most basic structure for representing a single piece of data in Nervos. The data contained in a Cell can take many forms, including CKBytes, tokens, code in Javascript, or even serialized data like JSON strings. As there is no restriction on the type of data included, developers have full flexibility in their choices.

Each Cell contains a small program called a Lock Script that defines who has permission to use it. In general, the Lock Script defines one user as the owner of a Cell, it can also do more complex operations such as having multiple owners (multi-sig) or conditional uses of time-locking within particular time-frames.

A Cell can opt to include a second program, called a Type Script, to execute a set of rules on the usage of cell. As a result, developers are empowered to create complex smart contracts across a wide range of use cases, from CryptoKitties to tokens, DeFi, and everything in between.

What is the Cell Model?

The cell model defines how each cell in Nervos acts and interacts with each other, and the process must be followed for updating the data contained within the cells. People familiar with Bitcoin’s UTXO model may notice the similarities, because the cell model was inspired by it.

Cells are immutable. This means no changes can be made once cells have been added to the blockchain. For any data update, the containing cell must undergo a process called consumption. When a Cell is consumed, data gets extracted and the cell gets destroyed. The data can be updated as needed while being extracted. A new cell with updated data will then be created and added to the blockchain.

Each Cell can be consumed only once. A non-consumed cell is known as a live cell. A consumed cell is known as a dead cell. Once dead, the cell can no longer be used.

Transactions serve to explain the changes in cell data. The transaction specifies a group of live cells to consume and a group of new cells to create by using the updated data. The network validates the transaction by executing all lock scripts and type scripts of each cell contained in the transaction. This ensures that all rules defined by the developers are being followed without any fraud.

First-Class Assets

Nervos’ cell model treats all digital assets, such as CKBytes, tokens, and digital collectibles, as the exclusive property and responsibility of their owner. Assets must adhere to smart contract rules when being included in transactions, but the asset inherently belongs to the user instead of the smart contract. The difference is subtle but critical.

When a user owns an asset, then only that user has permission to use the asset. Even the smart contract that defines the token has no permission to the asset. This means that even if an attacker found an exploit in the contract code, he or she would remain locked out of the asset because the asset is under user control. The impact of the attack is fully mitigated.

Having a defined ownership of the asset also clarifies who is responsible for its upkeep. As assets take up space on Nervos, there will be a small recurring upkeep fee, commonly known as state rent. User is the owner and is responsible as such, not the smart contract. More about state rent will be covered in the Economics section.

Transaction Fees Paid by Anyone

In most cases, people who send funds or execute smart contracts pay the transaction fees. However, to have a different party cover the associated fees can be beneficial in some cases.

A common scenario is the transfer of tokens from one party to another. The sender must own the tokens wanted to be transferred and sufficient CKBytes to cover the transaction cost. This creates an usability problem to users.

The flexibility of the cell model allows any party to pay the transaction fees. This can significantly improve the user experience since owning CKBytes is no longer an absolute requirement. The receiver or a third-party can pay the fee, easing the process for users.

Scalability

The cell model separates the concepts of computation and validation for smart contract execution. Computation is the process of generating new data, which is done off-chain before the transaction gets sent to the network. Validation ensures that the data conforms to the rules set by the developers, which is done on-chain by full nodes after being received by the network. Offloading computation reduces the burden on full nodes and improves the total processing capacity of the network.

Smart contract execution is parallel in the cell model. Each transaction runs independently in its own virtual machine. And, multiple virtual machines run simultaneously rather than sequentially. This gives the cell model dramatic scaling improvements on modern computers - computers that increase the number of CPU cores with each generation.

Transactions are very flexible in the cell model. Multiple smart contract operations can often be batched into a single transaction, eliminating the need to construct multiple distinct transactions. This decreases the overhead involved in transactions and simplifies the process by reducing the required processing and transaction fees.

The unique structure of the cell model grants an inherent scalability. The conbination of these methods enables Nervos to achieve a greater level of smart contract scalability. A level that would not be possible in other ways.

Further Reading

  • For more information, please see Nervos Network’s blog post on the Cell Model.
- +

Cell Model

What is a Cell?

Cell is the most basic structure for representing a single piece of data in Nervos. The data contained in a Cell can take many forms, including CKBytes, tokens, code in Javascript, or even serialized data like JSON strings. As there is no restriction on the type of data included, developers have full flexibility in their choices.

Each Cell contains a small program called a Lock Script that defines who has permission to use it. In general, the Lock Script defines one user as the owner of a Cell, it can also do more complex operations such as having multiple owners (multi-sig) or conditional uses of time-locking within particular time-frames.

A Cell can opt to include a second program, called a Type Script, to execute a set of rules on the usage of cell. As a result, developers are empowered to create complex smart contracts across a wide range of use cases, from CryptoKitties to tokens, DeFi, and everything in between.

What is the Cell Model?

The cell model defines how each cell in Nervos acts and interacts with each other, and the process must be followed for updating the data contained within the cells. People familiar with Bitcoin’s UTXO model may notice the similarities, because the cell model was inspired by it.

Cells are immutable. This means no changes can be made once cells have been added to the blockchain. For any data update, the containing cell must undergo a process called consumption. When a Cell is consumed, data gets extracted and the cell gets destroyed. The data can be updated as needed while being extracted. A new cell with updated data will then be created and added to the blockchain.

Each Cell can be consumed only once. A non-consumed cell is known as a live cell. A consumed cell is known as a dead cell. Once dead, the cell can no longer be used.

Transactions serve to explain the changes in cell data. The transaction specifies a group of live cells to consume and a group of new cells to create by using the updated data. The network validates the transaction by executing all lock scripts and type scripts of each cell contained in the transaction. This ensures that all rules defined by the developers are being followed without any fraud.

First-Class Assets

Nervos’ cell model treats all digital assets, such as CKBytes, tokens, and digital collectibles, as the exclusive property and responsibility of their owner. Assets must adhere to smart contract rules when being included in transactions, but the asset inherently belongs to the user instead of the smart contract. The difference is subtle but critical.

When a user owns an asset, then only that user has permission to use the asset. Even the smart contract that defines the token has no permission to the asset. This means that even if an attacker found an exploit in the contract code, he or she would remain locked out of the asset because the asset is under user control. The impact of the attack is fully mitigated.

Having a defined ownership of the asset also clarifies who is responsible for its upkeep. As assets take up space on Nervos, there will be a small recurring upkeep fee, commonly known as state rent. User is the owner and is responsible as such, not the smart contract. More about state rent will be covered in the Economics section.

Transaction Fees Paid by Anyone

In most cases, people who send funds or execute smart contracts pay the transaction fees. However, to have a different party cover the associated fees can be beneficial in some cases.

A common scenario is the transfer of tokens from one party to another. The sender must own the tokens wanted to be transferred and sufficient CKBytes to cover the transaction cost. This creates an usability problem to users.

The flexibility of the cell model allows any party to pay the transaction fees. This can significantly improve the user experience since owning CKBytes is no longer an absolute requirement. The receiver or a third-party can pay the fee, easing the process for users.

Scalability

The cell model separates the concepts of computation and validation for smart contract execution. Computation is the process of generating new data, which is done off-chain before the transaction gets sent to the network. Validation ensures that the data conforms to the rules set by the developers, which is done on-chain by full nodes after being received by the network. Offloading computation reduces the burden on full nodes and improves the total processing capacity of the network.

Smart contract execution is parallel in the cell model. Each transaction runs independently in its own virtual machine. And, multiple virtual machines run simultaneously rather than sequentially. This gives the cell model dramatic scaling improvements on modern computers - computers that increase the number of CPU cores with each generation.

Transactions are very flexible in the cell model. Multiple smart contract operations can often be batched into a single transaction, eliminating the need to construct multiple distinct transactions. This decreases the overhead involved in transactions and simplifies the process by reducing the required processing and transaction fees.

The unique structure of the cell model grants an inherent scalability. The combination of these methods enables Nervos to achieve a greater level of smart contract scalability. A level that would not be possible in other ways.

Further Reading

  • For more information, please see Nervos Network’s blog post on the Cell Model.
+ \ No newline at end of file diff --git a/docs/basics/concepts/ckb-vm/index.html b/docs/basics/concepts/ckb-vm/index.html index cbc780710..e1a5cd692 100644 --- a/docs/basics/concepts/ckb-vm/index.html +++ b/docs/basics/concepts/ckb-vm/index.html @@ -14,13 +14,13 @@ CKB-VM | Nervos CKB - +

CKB-VM

What is the CKB-VM?

Ethereum’s virtual machine-based programmability opened the door for Turing complete development on the blockchain. Nervos takes this one step further by utilizing the RISC-V instruction set to create the CKB-VM.

The CKB-VM is a virtual machine that executes smart contracts on Nervos. It is a full computer being emulated through software. It provides developers with the maximum amount of power and flexibility while maintaining a secure high-performance environment.

RISC-V

RISC-V is a computer instruction set similar to the one that powers your computer and the smartphone in your pocket. It is the lowest level of the software stack that provides raw instructions directly to the CPU.

RISC-V is an award-winning open standard developed and backed by some of the largest and most recognized tech industry leaders. Support and adoption are already prevalent and several large hardware manufacturers have announced plans to implement RISC-V in their mainstream consumer products.

The standard is mature, established, and built for modern hardware development. This guarantees a simple, modular design that will always be backward-compatible. It is an ideal fit for blockchain development.

Flexibility

With CKB-VM, operations that have traditionally been problematic in blockchains, like rolling out new cryptographic primitives such as Schnorr, BLS, zk-SNARKs, and zk-STARKs, no longer require a hard fork. The process is as simple as adding a new library to your codebase.

Developers have complete flexibility to rely on existing open-source libraries rather than being forced to retool everything from scratch. This allows for a less restrictive developer experience and quicker adoption of next-generation technological advancements, such as cross-blockchain interaction, scaling innovations, and direct integration with secure hardware enclaves.

Any programming language that can target RISC-V can be used natively for Nervos development. Use your existing tooling, favorite IDEs, and debug tools. There is no need to rely on immature and untested tools; use whatever is best for the job.

Nervos CKB offers native SDKs in a growing number of well-known general-purpose programming languages, such as JavaScript, Rust, and C. Direct support for emerging smart contract languages, such as Solidity, Vyper, and Plutus is also planned.

Further Reading

  • For more technical information on CKB-VM, please see the CKB-VM RFC.
- + \ No newline at end of file diff --git a/docs/basics/concepts/consensus/index.html b/docs/basics/concepts/consensus/index.html index 021e369c3..d5679ed9b 100644 --- a/docs/basics/concepts/consensus/index.html +++ b/docs/basics/concepts/consensus/index.html @@ -14,13 +14,13 @@ Consensus | Nervos CKB - +

Consensus

What is Consensus?

Consensus is a state of agreement between the participants of a decentralized network. This means that the nodes on the network agree on the history and current state of the blockchain. State represents data such as the amount of CKBytes every user owns and which digital assets they have.

The Nervos Network consists of thousands of computers and millions of transactions that are constantly flowing through the network. A consensus must be reached between the computers on the network about which transactions are valid and in what order they occurred. This is a challenge because nodes are positioned all over the world, and internet transmission isn’t instant or completely reliable.

Nodes pass messages to each other, sharing information about transactions and blocks that have been created. The messages might arrive out of order, or very late, or not at all. It also cannot be guaranteed that all of the nodes are functioning correctly or are being honest.

Billions of dollars of value are at stake. The challenge is great, and robust solutions are of absolute importance.

NC-Max

A project as ambitious as Nervos requires a zero-compromise solution for consensus. Many options were considered and it was determined that Proof of Work (PoW) is still the best solution.

Proof of Stake (PoS) is one of the strongest contenders to PoW. The major advantage of PoS is that it requires substantially less electricity to operate. However, PoW still offers several advantages over PoS:

  • PoW mining is subject to external changes in technology, energy production, and regulation. This means that continued reinvestment is necessary to stay ahead of the competition, making long term monopolization difficult.
  • PoW does not give strong advantages to the early participants of the system. There is no way for a late participant to compete with an early participant in PoS, because rewards are awarded deterministically.
  • PoW is more simplistic and requires far fewer assumptions to be made. This means the potential for security holes is substantially lower.

Bitcoin’s Nakamoto Consensus is the PoW algorithm that has successfully defended Bitcoin from countless attacks for over a decade. The technology is well understood and proven through the test of time. Nervos’ NC-MAX builds on Nakamoto Consensus by improving block propagation, block throughput, and resistance to selfish mining.

Improved Block Propagation

When a transaction is broadcast to all the nodes on the network, it remains in queue until it is included in a future block. A bottleneck can occur if the transaction broadcast is not fully successful. For instance, some nodes might be aware of the transaction and others may not. The nodes will need to sync their missing transactions before a block can be properly verified. There will be network delays as the missing transactions are found and distributed to all nodes that need them.

This bottleneck limits the performance of a blockchain because its impact becomes greater as the time between blocks is lowered. It can also lead to selfish mining attacks where miners intentionally create network delays so that they will have an advantage over others to gain more mining rewards.

NC-MAX solves this problem by splitting the confirmation process into two steps: propose and commit. A transaction is first proposed to the network. After several blocks have been verified, the transaction can then be confirmed. This gives more time for transaction propagation without slowing down block propagation. Once a transaction has been proposed and fully propagated, then it can be committed. This eliminates transaction propagation as a delay factor to block propagation, eliminating the bottleneck and selfish mining attack.

Improved Block Throughput

With a shorter block interval, blocks are created more frequently, enabling faster transaction confirmations and a higher throughput for the network. The downside of a shorter block interval is that internet congestion has a greater effect on the ability of the network to properly synchronize. There are times when blocks are created while the network is not fully in sync, creating so-called orphan blocks. This means that the efforts towards network security are temporarily divided. Orphan blocks are inevitable; however, if too many occur within a short period of time, shorter block intervals become counterproductive.

NC-MAX improves this by automatically adjusting block intervals based on network performance. In the consensus protocol, the number of orphan blocks created within a time frame is tracked and taken into account. The network is then able to adjust the block interval to maximize throughput while maintaining an expected Orphan Rate. This results in dramatically shorter block times without compromising security.

Improved Resistance to Selfish Mining

Selfish mining is a practice where certain miners are able to secretly gain a larger share of mining rewards while contributing less hash power to the network. This practice is discouraged, since it weakens overall network security and leads to irregular block times that can cause congestion problems.

NC-MAX offers the most accurate measurement of the network’s computing power by taking into account both external and internal factors. The new model takes into account the actions miners would take to exploit the computing power calculation. Therefore, all known selfish mining attacks become unprofitable.

Eaglesong

Bitcoin’s Nakamoto Consensus internally utilizes a well-known hashing function known as SHA256. The majority of mining infrastructure that exists in the world is based on this algorithm.

Any new cryptocurrency that is also based on SHA256 immediately benefits from hardware availability. However, there is a downside in that the substantial amount of infrastructure available for a large cryptocurrency, like Bitcoin, can be used maliciously towards a small cryptocurrency during their early days. Having dedicated mining hardware available for your ecosystem is overall beneficial since it significantly increases the challenges of attacking the network. For these reasons, a new cryptographic hashing function called Eaglesong was created specifically for Nervos.

Eaglesong successfully blends novelty, simplicity, and security in a way that is easily implemented in both software and hardware. This advancement gives Nervos an edge in blockchain security while allowing for complete hardware sovereignty.

Further Reading

- + \ No newline at end of file diff --git a/docs/basics/concepts/cryptowallet/index.html b/docs/basics/concepts/cryptowallet/index.html index 88d8a04fa..d6cda1361 100644 --- a/docs/basics/concepts/cryptowallet/index.html +++ b/docs/basics/concepts/cryptowallet/index.html @@ -14,14 +14,14 @@ Crypto Wallet | Nervos CKB - +

Crypto Wallet

What is a Crypto Wallet?

A crypto wallet is a software program or physical device that keeps your private keys and gives you access to your cryptocurrencies. Simply put, a crypto wallet is a digital wallet that allows users to store and manage their cryptocurrencies.

A crypto wallet consists of a collection of key pairs. Each key pair consists of a private key and a public key corresponding to an address. The public key is similar to a bank account number and the private key is similar to the secret PIN that provides control over the account. The public key is generated from the private key by a one-way cryptographic function. The wallet address is generated from the public key by a one-way cryptographic hash function. The wallet address is human-readable and is used for sending and receiving cryptocurrencies. The keys and addresses establish the ownership of cryptocurrencies.

Types of Crypto Wallets

There are two main categories of crypto wallets, hot and cold wallets, which are defined by the internet connectivity. Hot wallets are internet-connected, less secure, and pose more risk, but are user-friendly. Cold wallets, on the other hand, are stored offline, do not require an internet connection, with higher security and lower risk.

Hot Wallets

Hot wallets are basically internet-connected wallets that offer a higher level of user-friendliness. Hot wallets are easy to set up and have fast access to assets.

The three main types of hot wallets are:

  • Web-based Wallets

    Web-based wallets are the prominent crypto wallets in the hot wallet category. One can access a web wallet through a web browser without downloading any specific software or application. Web wallets, such as MetaMask, work as browser extensions allowing users to access cryptocurrency assets from anywhere by simply having a password, a device, and a web browser, enabling users to easily interact with dApps (decentralized applications) and DeFi (decentralized finance) protocols.

  • Desktop Wallets

    Desktop Wallet requires the user to download an application onto the desktop or laptop. The application generates a data file that holds the user's privkeys. The user also needs to create a PIN to access these keys. Desktop wallets, such as the Electrum wallet, can be used on a desktop or laptop computer.

  • Mobile Wallets

    Mobile wallets are also one of the crucial cryptocurrency wallet categories in hot wallets. Functioning similarly to desktop wallets, users must install a mobile application on their phone to serve as a wallet. Mobile wallets bring better flexibility for exchanging funds, but there are also some security risks. Mobile wallets, such as the Blockchain.com wallet, allow users to store cryptocurrencies, send/receive transactions, and "scan" the privkey of an existing wallet into the app by scanning a QR code.

Cold Wallets

Cold wallets are types of crypto wallets used for cold storage. These wallets store the cryptos in an offline mode and offer better security. Cold wallets are always a secure option compared to other wallets, as these act as a vault for daily transactions.

There are two main types of cold wallets, paper wallets and hardware wallets:

  • Paper Wallets

    Paper wallet is nothing but a physical piece of paper. This paper must contain all the data a user needs to access the cryptocurrency.

  • Hardware Wallets

    Hardware wallets store private keys on a physical device in an offline environment. It can be connected to a computer or other device effortlessly by using a USB drive. When the device is connected to the internet, the private key remains on the device. The device will request transaction details and provide verification for the data to complete the transaction. The transaction details are sent to the network where the transaction is logged. Trezor and Ledger are among the popular hardware wallets available today.

Benefits of Using Crypto Wallets

  • Simplicity and ease of use. It’s just like any other software or wallet that you use for your day-to-day transactions.

  • Highly secure. A highly secure sign-in procedure is usually implemented, requiring an encrypted login details ID to be entered. This can assist to guarantee that no one else can access the account unless an explicit permission is given.

  • Allows instant transactions across geographies. And these are barrierless, without intermediaries.

  • Low transaction fees. The cost of transferring funds is much lower than with traditional banks.

  • Access to multiple cryptocurrencies. One of the benefits of utilizing a well-known cryptocurrency wallet is having many cryptocurrency alternatives to choose from. It facilitates the ease of the crypto conversion whilst reducing risk and increasing the total profit potential.

CKB Wallets

There are many options for storing and securing CKB assets, either in hot or cold wallets. Given that CKB is available on several exchanges, users can choose to store assets on any exchange. But some alternatives may deserve attention as well for additional security.

Wallets that provide custody and security services to CKB include:

For more information, see the guides of Neuron Wallet, imToken & imKey, SafePal, Portal Wallet, Bitpie.

CKB Addresses

Nervos CKB follows Bitcoin bech32 address format (BIP-173) or Bitcoin bech32m address format (BIP-350) rules to generate addresses.

The following two address formats have been deprecated:

  • Short address

    Example: ckb1qyq5lv479ewscx3ms620sv34pgeuz6zagaaqklhtgg

  • Full address

    Example: ckb1q3w9q60tppt7l3j7r09qcp7lxnp3vcanvgha8pmvsa3jplykxn32snajhch96rq68wrff7pjx59r8stgt4rh5g96ahs

A new full address format is supported now. Both the community and partners in the Nervos ecosystem are encouraged to migrate to the new full address format.

Example: ckb1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqdnnw7qkdnnclfkg59uzn8umtfd2kwxceqxwquc4

For more information, see RFC: CKB Address Format.

Here are three solutions for CKB address generation and transformation:

  • CKB.tools: allow the parsing or generating of deprecated addresses for applications that do not yet support the new full address format, such as the faucet.
  • Lumos Page (CKB Lumos): can be used to generate new full addresses.
  • ckb-address-transformer: can be used to convert a deprecated address into a new full address and vice versa.

Minimum Requirements of a CKB Transfer

The minimum unit of a transfer is one CKB cell, and the basic data structure of a cell consists of capacity, lock, args and hash_type.

  • capacity requires 8 bytes of storage space.
  • lock requires 32 bytes of storage space.
  • args requires 20 bytes of storage space.
  • hash_type requires 1 byte of storage space.

The total minimum storage space of a cell is 61 bytes. 1 byte equals 1 CKByte (CKB), so one cell requires at least 61 CKBs. That is, each transfer requires at least 61 CKBs.

References

- + \ No newline at end of file diff --git a/docs/basics/concepts/economics/index.html b/docs/basics/concepts/economics/index.html index 75fd838a2..eb7e0fde0 100644 --- a/docs/basics/concepts/economics/index.html +++ b/docs/basics/concepts/economics/index.html @@ -14,13 +14,13 @@ Economics | Nervos CKB - +

Economics

The Economics of the CKByte

The CKByte is the native token of Nervos, and it is used to pay for the three types of fees that exist: Cycles (computation), Transaction Fees (security), and State Rent (storage).

  • Cycles are fees paid to miners based on the amount of computer resources that are used to verify a transaction. These are measured by CKB-VM during the execution of any smart contracts in a transaction.
  • Transaction Fees are paid to miners for providing the computing power that provides security to the network.
  • State Rent compensates miners for providing storage space to persist the data in a transaction.

Cycles and Transaction Fees are paid once to process and insert the transaction into the blockchain. State Rent is paid continuously to persist the data until it is removed.

Owning one CKByte entitles the holder to one byte of data storage on Nervos. To create a new cell, the user must own an amount of CKBytes equal to the space the cell will occupy. These CKBytes will remain locked the entire time the cell exists. When the cell is consumed, the lock is released, and the CKBytes can be used again. State Rent is automatically paid while the CKBytes are locked.

All assets on Nervos require data storage, which means they are subject to State Rent. This creates direct value alignment because CKBytes are required to maintain an asset on Nervos. The following sections provide more information about Value Alignment and State Rent.

Value Alignment

The security of a platform must grow along with the value that the platform stores. Otherwise, the value stored will have too little security. It would be like adding more and more gold to a bank vault without adding any additional guards. This makes it vulnerable to attack.

The native tokens, CKBytes, are used to pay miners for their contributions. As the value of the CKBytes increases, so do the rewards for protecting the network. This prevents a scenario where the value of the CKBytes being stored on the network is very high, but the reward for securing the network is very low.

However, a problem can develop on multi-asset platforms if the total value of the assets gains value but the native token providing security does not. This is known as the “heavy asset problem”, and it is common among multi-asset platforms.

The heavy asset problem exists when there isn’t a strong enough value correlation between the assets and the native token used to secure the underlying platform. Usage of CKBytes for the payment of Cycle and Transaction fees creates some demand similar to Bitcoin and Ethereum. However, history has demonstrated that this model does not rectify the problem.

Nervos addresses this by aligning the CKByte with data storage and mandating State Rent. This directly creates long-term demand because assets require data storage. Every asset requires CKBytes and is subject to State Rent for the entire duration of its existence.

State Rent

Miners are responsible for ensuring that the data on the network is valid and preserved. Cycles and transaction fees are paid to ensure proper validation. However, once the fees have been paid, there is no further incentive for the miner to preserve the data. As a solution, State Rent continuously pays miners to participate in preserving the data on the network.

When a user puts data on Nervos they must pay a small amount of State Rent for the space their data occupies. An upfront recurring fee is inconvenient for users since it requires constant attention and time. Nervos solves this issue by using targeted inflation on users who are occupying space on the Nervos network.

A certain amount of CKBytes must be locked when data is stored on Nervos. These CKBytes are ineligible for interest payments. Even though the number of CKBytes does not change while locked, the value is slowly decreasing because of inflation that only affects users who are storing data on Nervos. This small decrease in value is how State Rent is paid.

The inflation that pays the State Rent is created through a process called Secondary Issuance. Nervos users who do not occupy space on the network may gain interest from Secondary Issuance by locking their CKBytes in Nervos DAO. The following sections will cover these topics in more detail.

Base Issuance

During the initial launch of the network, CKBytes had a low value, which indicates the network had a low level of security. To make Nervos a safe and attractive place to store assets, the security must be temporarily subsidized through a process called Base Issuance.

Base Issuance is very similar to Bitcoin's mining process. Miners are paid a fixed amount of CKBytes for providing the computer resources to process transactions and secure the network. The assets stored on the network will gain value over time, and fewer subsidies will be required.

Base Issuance is paid for with a fixed inflationary schedule. Approximately every four years, the subsidy amount is halved, and it eventually stops, when the cap of 33.6 billion CKBytes is issued. This provides a monetary policy that is transparent and predictable.

Secondary Issuance

It has been suggested that after the Base Issuance ends, the incentive to miners will not provide sufficient security if it is only paid with fees from cycles and transactions. Additionally, miners require long-term incentives to ensure that Nervos data persists. Both of these concerns are addressed through a process called Secondary Issuance.

Secondary Issuance follows a fixed inflation schedule of 1.344 billion CKBytes per year. This amount does not change. Unlike Base Issuance, Secondary Issuance does not affect everyone on the network. The inflation is small and targeted at users who occupy space on Nervos or hold their CKBytes outside of Nervos DAO.

The CKBytes from Secondary Issuance are distributed to:

  • Miners who maintain the network (State Rent).
  • Nervos DAO users.
  • The Nervos Treasury for continued development.

Nervos DAO

CKBytes holders can lock their tokens in Nervos DAO to gain interest in a similar manner to staking on other platforms. When this is done, the holder will accrue CKByte interest at a rate directly proportional to that of Secondary Issuance. This offsets the long-term inflationary effects of Secondary Issuance exactly, resulting in no loss of value over time.

Users who occupy space on Nervos have their CKBytes locked, which makes them ineligible to be placed in Nervos DAO. Once the cells occupying the space are consumed, the CKBytes are released, and they can then be placed in Nervos DAO. This provides an incentive to remove unnecessary data from Nervos, in order to keep the blockchain manageable in the long term.

Further Reading

- + \ No newline at end of file diff --git a/docs/basics/concepts/nervos-blockchain/index.html b/docs/basics/concepts/nervos-blockchain/index.html index 4083e8241..cde65fc95 100644 --- a/docs/basics/concepts/nervos-blockchain/index.html +++ b/docs/basics/concepts/nervos-blockchain/index.html @@ -14,13 +14,13 @@ Nervos Blockchain | Nervos CKB - +

Nervos Blockchain

What is the Nervos Blockchain?

Nervos blockchain, also known as Common Knowledge Base, is the rock-bottom layer of the Nervos ecosystem. As the foundation, Nervos blockchain provides trust for all the layers built on top of it. It is designed to maximize decentralization while remaining minimal, flexible, and secure. Its primary objective is to reliably preserve any data and assets stored therein.

Multi-Layer Architecture

Trade-offs are inevitable in designing any decentralized system. A common example of the trade-off concerns scalability, security, and decentralization. It is tough to achieve all three at the same high level on a single layer, but having different layers can solve different problems separately.

An example on how layering helps improve this:

  • Layer 1 focuses on security and decentralization, providing trust to higher layers.
  • Layer 2 focuses on scalability, providing nearly instantaneous transactions for millions of users.

These two layers function together to achieve higher levels of decentralization, security, and scalability.

The Nervos blockchain represents the layer 1 of a multi-layer architecture that prioritizes security and decentralization as core design principles.

What is a CKByte?

The native token of Nervos is known as the CKByte, or CKB for short. One CKByte token entitles the holder to one byte of data storage on Nervos. The CKByte is also used to pay fees associated with any transactions and computations.

To store 100 bytes of data in Nervos, it is mandatory to have 100 CKBytes. If your data occupies space on Nervos, your CKBytes will remain locked. If your data is no longer needed and is removed from Nervos, the 100 CKBytes will be available for other purposes.

CKBytes can also be deposited in the Nervos DAO,where they gain interests in a staking-like process.

Further information about CKByte will be presented in the Cell Model and Economics sections.

Programming on Nervos

Nervos offers smart contract programmability using a growing number of well-known general-purpose programming languages, such as Javascript, Rust, and C.

All programs on Nervos can store data and state on-chain,which makes creating complex applications and customized tokens a simple and straightforward process.

All code runs in CKB-VM. CKB-VM is a high-performance RISC-V virtual machine that provides a secure, consistent and flexible environment for developers. Multiple instances of CKB-VM can execute different smart contracts concurrently, which enables substantial scaling improvements through massive parallelization.

More details about programming on Nervos will be covered in the Cell Model and CKB-VM sections.

Consensus

Nervos uses a Proof of Work (PoW) based consensus algorithm,known as NC-MAX. PoW has been repeatedly proven to be the best in class solution for incentivize security.

Building on Bitcoin’s Nakamoto Consensus, NC-MAX dramatically increases transactions per second and decreases confirmation time without compromising security or decentralization.

Nervos currently provides a 10x throughput boost compared to Ethereum, and is expected to grow exponentially as layer 2 solutions come to the table.

More details on the design of Nervos’ consensus implementation will be discussed in the Consensus section.

- + \ No newline at end of file diff --git a/docs/basics/faq/address/index.html b/docs/basics/faq/address/index.html index 35e276017..8db9e79bd 100644 --- a/docs/basics/faq/address/index.html +++ b/docs/basics/faq/address/index.html @@ -14,7 +14,7 @@ CKB Address | Nervos CKB - + @@ -25,7 +25,7 @@ For details about GO SDK, you may refer to: https://github.com/nervosnetwork/ckb-sdk-go.

In the latest version of Java SDK, you can use AddressTools.ConvertToBech32mFullAddress to convert any address formats into our recommended address format -- the new full address format. You can also use AddressTools.ConvertToShortAddress to convert secp, ACP and multi-sig script address of any format into short address, and ConvertToBech32FullAddress to convert any address format to the old full address. For details about Java SDK, you may refer to: https://github.com/nervosnetwork/ckb-sdk-java.

In the latest version (0.18.0-rc3) of Lumos, we provide a brand new encodeToAddress API to generate the new full address format, while retaining the old generateAddress API to generate an address. However, the generateAddress is going to be marked as deprecated, and we recommend that you can migrate to the new encodeToAddress API. If users find out some platforms (e.g. Nervos Aggron Faucet) do not yet support the new address format, the old API can still be used. You can use yarn add @ckb-lumos/lumos@next to install if using the latest version of Lumos.


- + \ No newline at end of file diff --git a/docs/basics/faq/general/index.html b/docs/basics/faq/general/index.html index f450153c5..1658a809a 100644 --- a/docs/basics/faq/general/index.html +++ b/docs/basics/faq/general/index.html @@ -14,13 +14,13 @@ General FAQ | Nervos CKB - +

General FAQ

Q: Which consensus does Nervos use?

A: Consensus refers to the consistent state of distributed network participants, in other words, the historical data and current ledger state of the blockchain that the nodes on the network agree on unanimously. The ledger state consists of records of user accounts and asset balances, such as the number of CKBytes and tokens they own. The consensus algorithm Nervos is using is called NC-MAX. NC-MAX is based on Proof of Work (PoW) and Nakamoto consensus (used by Bitcoin) and is an ambitious project as much as Nervos. It is a consensus solution with zero compromise in terms of security and decentralization, while maximizing the use of network bandwidth. After thoughtful considerations, Nervos believed Proof of Work (PoW) is the best solution.

Proof of Stake (PoS) is one of PoW's competitors. One advantage that PoS has is that it requires less power to operate. Compared with PoS, PoW has the following incomparable advantages: 1) PoW mining is affected by external changes in technology, energy production and regulation. This means that PoW is energy efficiency. Moreover, the continuous reinvestment is necessary to maintain a leading position in the competition, which makes long-term monopoly difficult. 2) PoW will not bring monopolistic advantages to early participants in the system. In PoS, rewards are obtained with complete in-protocol resource and determinism, which means that early participants have advantages over latecomers. 3) PoW is simpler and requires far fewer assumptions, therefore, the probability of a security breach is much lower. To achieve the same level of security, PoW is more efficient than PoS except it exhibits security budget in a more explicit way. 4)

Based on the Satoshi Nakamoto consensus of Bitcoin, NC-MAX significantly increases the transaction volume per second and reduces the confirmation time without affecting security or decentralization. Compared with Ethereum, Nervos currently provides 10 times the throughput growth, which is expected to increase exponentially with the development of Layer 2 solutions.

For more information, see Consensus.

More discussions on POS and POW: https://talk.nervos.org/t/pow-pos-discussion-in-history/5457.


Q: What is CKByte?

A: CKByte is the token required for the use of the basic functions of the Nervos network. CKByte is the native token of the Nervos CKB blockchain, which can be redeemed for transaction fees, and is also a unit of CKB on-chain space. Possessing 1 CKByte means having 1 byte of storage capacity on CKB, i.e. ownership of 1 byte of a common knowledge base. Instead of cloud servers or general distributed storage, data stored in Common Knowledge Base has a higher value density as the data will be verified by permissionless global consensus and smart contracts throughout the network before being stored on countless nodes in the distributed network. Either the fungible token or non-fungible token, for example, is typical of data held in the common knowledge base.

The initial amount of CKByte in design is 33.6 billion, of which 25%, or 8.4 billion CKBytes were reserved for Satoshi Nakamoto (using his/her/their address found in Bitcoin genesis block). However, the “tribute to Satoshi“ was later cancelled due to security concerns, and the 8.4 billion CKBytes are sent to an all-zero address in the genesis block, making them effectively “burnt” and will never enter circulation. The real initial amount of CKByte in genesis is thus 25.2 billion.

Burning is not the same as not-issued, as these 8.4 billion CKBytes will impact the second issuance. 15% of the 8.4 billion CKBytes will be filled with data (make them occupied capacity), while the remaining 10% of the 8.4 billion CKbytes will be left empty (free capacity). By this setting, miners are guaranteed 15% of secondary issuance, which is effectively the minimal security budget of Nervos, solves perhaps the only unsolved problem in Bitcoin. The 10% empty capacity means at minimum 10% of secondary issuance is “burnt” until Nervos Treasury is enabled. (note: the description of “burnt” 8.4 billion’s impact on secondary issuance in this article is correct, but the 8.4 billion is sent to all-zero address, not Satoshi’s address).

In addition to the CKBytes generated in the Genesis block, a primary issuance of 33.6 billion CKBytes and a secondary issue of 1.344 billion CKBytes per year are set in the protocol. Similar to the Bitcoin mining process, miners are compensated in CKBytes as they provide computing resources to process transactions and secure the network. The primary issuance halves every four years, while the secondary issuance is constant every year. In the beginning, miners will be rewarded by both primary and secondary issuance. After all the 33.6 billion primary issuance has been released, there will only be a secondary issue of 1.344B CKBytes per year. The secondary issue can be seen as payment-by-inflation from CKB users to use the common knowledge base.

The secondary issuance is shared by miners, the Nervos DAO and the future Nervos treasury based on common knowledge base usage. CKB can be utilised as a secure store of value, just like BTC. It’s also the fuel of smart contracts and decentralised applications, like ETH, for transaction processing and on-chain storage. The unique crypto-economic of CKByte ensures secure storage of value, value capture of the layered Nervos network, and incentive compatibility of users, miners, developers and node operators.

More information is available at:


Q: What is SUDT?

A: SUDT is the abbreviation of Simple User Defined Token, which is equivalent to the ERC20 standard on Ethereum. It defines an easy-to-understand token standard, which contains the content that DApp developers need while minting their own tokens on Nervos CKB. You can check SUDT RFC for more details. For the method of writing and mining SUDT, please refer to the following documents:


- + \ No newline at end of file diff --git a/docs/basics/glossary/index.html b/docs/basics/glossary/index.html index b124c3ea1..e0899971e 100644 --- a/docs/basics/glossary/index.html +++ b/docs/basics/glossary/index.html @@ -14,13 +14,13 @@ Glossary | Nervos CKB - +
-

Glossary

Glossary Sections


General Glossary

Account

A kind of basic object in distributed ledger used to keep the balance and other information of users.


Address

A label consists of string of letters and numbers that anonymously represents user's identity on chain. Crypto assets can be sent to and/or from addresses.

Synonyms


Asset

A piece of data that has value or that represents an entity having value.

Synonyms


Block

A grouping of transactions, marked with a timestamp, and a fingerprint of the previous block. The block header is hashed to produce a proof of work, thereby validating the transactions. Valid blocks are added to the main blockchain by network consensus.

See Also


Block Height

Block height is the total number of blocks that have been confirmed on the blockchain, also used to identify a unique block when specifying a particular block height, as there is always an exact block at any block height.

Synonyms

See Also


Block Interval

Also known as Block Time. Block interval is the length of time it takes to create a new block in a cryptocurrency blockchain. Block interval is the measure of the time it takes the miners or validators within a network to verify transactions within one block and produce a new block in that blockchain. The block interval is variable on Nervos blockchain.

The block interval on the Bitcoin blockchain is approximately every 10 minutes. The block interval on Nervos is variable, but is usually under 10 seconds.

Synonyms

See Also


Block Propagation

The process of synchronizing a new block to the majority of full nodes in the network. Block propagation is a well-known bottleneck that prevents Bitcoin from scaling.

Block propagation time is an average time that is needed for the new block to reach the majority of nodes in the network. Long block propagation delay reduces the node's resistance against 51% attacks.

Synonyms

See Also


Block Reward

The amount of cryptocurrency credited to a miner's account after the miner successfully adds a block of transactions to the blockchain.

In Nervos CKB, block rewards are the CKBytes credited to a miner's account after a block is successfully added to CKB by the miner.

See Also


Block Time

Alternatively referred to as Block Interval.

Synonyms


Blockchain

A data structure maintaining a growing list of records, organized as a chain of blocks. Each block, apart from the first one, is cryptographically linked to the previous block, thus creating a chain-like structure.

The cryptographic link ensures any party with the last block can verify that none of the historical data is modified after the creation of this block.

See Also


BLS Signature

A cryptographic signature scheme for signing and verification. BLS is short for Boneh–Lynn–Shacham.

See Also


Broadcast

Blocks are sent to all nodes in a blockchain network.

See Also


Capacity

The maximum space (in bytes) that a cell can occupy on the Nervos CKB.

Synonyms

See Also


Cell

All data on Nervos CKB is stored in cells. Cells are the primary state units in CKB, within them users can include arbitrary states.

A cell has 4 fields: capacity, data, type and lock.

Synonyms

See Also


Cell Model

A representation of how state is managed on Nervos CKB. The cell model is a more generic state model than either Bitcoin's UTXO or Ethereum's account model.

The cell model is a new construction that combines many of the advantages of Ethereum's account model with the asset ownership and proof-based verification properties of Bitcoin's UTXO model.

See Also


Censorship Resistance

Censorship resistance in blockchain generally means that it is difficult for a malicious party to prevent the blockchain from confirming a set of transactions generated by honest users.


Chain

A shorthand name for blockchain.

Synonyms


CKB

An abbreviation which can have different meanings depending on the context:

  • Common Knowledge Base - The layer 1 blockchain of the Nervos Network.
  • Common Knowledge Byte - The native token of the Nervos Common Knowledge Base.

Synonyms


CKByte

A shorthand name for Common Knowledge Byte.

CKByte is also sometimes shortened to CKB. Exchanges often use CKB as the ticker symbol.

Synonyms

Not To Be Confused With


CKB-VM

CKB VM is a crypto-agnostic virtual machine, a RISC-V instruction set based VM for executing both on-chain and off-chain code.

See Also


Code Hash

A field in a cell which contains a hash value that can refer to a specific piece of data, or a specific cell referenced by Type ID.

See Also


Cold Storage

A method of securing funds by placing them in a cold wallet; a type of wallet that is never connected to the internet.

See Also


Cold Wallet

A wallet that is used to secure assets offline. This wallet is permanently disconnected from the internet, and not vulnerable to attacks which rely on an active internet connection.

See Also


Commit

Nervos CKB's consensus algorithm, NC-Max consensus, has two phases: propose and commit. Commit is the process of including a valid proposed transaction into a new block.


Commit-Chain

A scheme that enables the off-chain processing of transactions by one or more operators with on-chain state update commitments that do not contain per-transaction data.


Commit Reward

A reward paid to miners in CKBytes on inclusion of previously proposed transactions.


Common Knowledge Base

A layer 1 proof of work blockchain that provides a foundation of decentralized trust for the Nervos Network.

Synonyms

Not To Be Confused With

See Also


Common Knowledge Byte

The native token of the Nervos layer 1 blockchain, the Common Knowledge Base.

Common Knowledge Byte is often abbreviated as CKByte or CKB.

Owning a CKByte entitles the holder to store one byte of data on the Nervos CKB blockchain.

Synonyms

Not To Be Confused With

See Also


Confirmation

A process where a transaction has been accepted and verified by the network and included in a block.

See Also


Consensus

An algorithm executed among a number of distributed participants, ensuring that all participants faithfully executing this algorithm can reach agreement on some data value even if the other participants are faulty or malicious.

See Also


Consume

The process of using a live cell as an input to a transaction. The consumption processes indicate that live cell turns into a dead cell.


Contract Account

An account containing code that executes automatically whenever it receives an event from another account.

See Also


Cryptocurrency

A cryptocurrency is a digital or virtual currency that is secured by blockchain and cryptography, which makes it nearly impossible to counterfeit or double-spend.

See Also


Cryptographic Signature

A concise piece of proof data. Cryptographic signature schemes are a fundamental component of cryptocurrency networks that verify the integrity and non-repudiation of transaction messages across the network.

Synonyms


Cryptography

Cryptography is the practice and study of techniques for secure communication in the presence of adversarial behavior.

See Also


Cycles

The number of RISC-V computational cycles required by a script to execute. It's a metric used to prevent malicious behavior such as infinite loops, that's why it is called cycles.

This is a similar concept to Ethereum's Gas, we set cycles to ensure optimal performance and security. Scripts must stay within cycle limits, otherwise the block will be rejected by CKB nodes.

See Also


DAO

A decentralized autonomous organization (DAO) is an organization represented by rules encoded as a computer program that is transparent, controlled by the organization members and not influenced by a centralized entity, in other words they are member-owned communities without centralized leadership. A DAO's financial transaction record and program rules are maintained on a blockchain.

See Also


DApp

Decentralized application. At a minimum, it is a smart contract and a web user interface. In a broader sense, DApps are web applications that are built on top of open, decentralized, peer-to-peer infrastructure services. Additionally, many DApps include decentralized storage and/or a message protocol and platform.


Data

In cell model, data is a field in a cell which can store arbitrary bytes.

See Also


Decentralization

In blockchain, decentralization refers to the transfer of control and decision-making from a centralized entity (individual, organization, or group thereof) to a distributed network.

See Also


DeFi

Short for "decentralized finance", a broad category of DApps aiming to provide financial services backed by the blockchain, without any intermediaries, so anyone with an internet connection can participate.


Digital Asset

A digital asset is an individual piece of data that has value, or represents another entity that has value.

Digital assets are most commonly represented as tokens, which may be used as digital currency or represent physical items such as real estate.

Synonyms


Digital Currency

A type of currency that primarily exists digitally over the internet. Physical representations of the currency, in the form of cards, bills, or coins, may exist, but are secondary mediums.

See Also


Distributed

A system where components are spread across multiple nodes to parallelize workloads, add redundancy, or eliminate single points of failure.

See Also


Double-Spending

Double-spending is the risk that a digital token is spent twice or more. In the context of blockchain, it happens when the transaction spending a digital token is cancelled after confirmation, and the same token is spent in another transaction.

See Also


Epoch

An epoch is a period of time for a set of blocks.

In Nervos, the PoW difficulty changes on a new epoch. All the blocks in the same epoch share the same difficulty target. The difficulty adjustment algorithm aims to stabilize the orphan block rate at 2.5% and the epoch duration at 4 hours.

See Also


Fee

The sender of a transaction often includes a fee to the network for processing the requested transaction. There's no minimum fee rate set in consensus, but there's a minimum fee rate 1,000 Shannons/KB in CKB's P2P network. (1 Shannon = 10-8 CKB)

See Also


Fee Rate

A tip per byte that a user offers to the miners for including his transaction in a block on the blockchain.

This is a same concept to Bitcoin's Fee Rate(often spelled feerate).

See Also

First-Class Assets

Assets that 1. the asset itself (rather than a reference to the asset) can be passed directly in smart contract interactions, and 2. directly controlled by owners without any intermediaries.

See Also


Fork

A change in protocol causing the creation of an alternative chain, or a temporal divergence in two potential block paths during mining.


Full Node

A full node is an essential component of the CKB network. It stores and syncs the entire blockchain, verifies the validity of blocks and transactions, and enforces the network's consensus rules.

ckb init --chain mainnet && ckb run

See Also


Full Payload Format

The deprecated full payload format directly encodes all data field of lock script. The encode rule of deprecated full payload format is Bech32.

See Also


Fungible Token

A fungible token can be fiat currencies like the dollar or a cryptocurrency like Bitcoin.

Fungible tokens or assets are divisible and non-unique.

See Also


Gas Limit

The maximum amount of gas a transaction or block may consume.

See Also


Hard-Fork

A permanent divergence in the blockchain; also known as a hard-forking change. One commonly occurs when nonupgraded nodes can’t validate blocks created by upgraded nodes that follow newer consensus rules. Not to be confused with a fork, soft fork, software fork, or Git fork.


Hardware Wallet

A hardware wallet is a form of cold wallet. A hardware wallet is a cryptocurrency wallet that stores the user's private keys (a critical piece of information used to authorize outgoing transactions on the blockchain network) in a secure hardware device.

See Also


Hash

A fixed-length fingerprint of variable-size input, produced by a hash function.


Hash Rate

Hash rate is a measure of the computational power per second used when mining. These operations are known as "hashing".

See Also


Height

A shorthand name for block height.

Synonyms


Light Client

As a low-resource node, a light client allows users to sync with a blockchain in a cryptographically secure manner without having to store the whole blockchain.


Light Node

A light node downloads only the headers of the blockchain, conserving resources. It relies on other nodes for full transaction data and is a lightweight option for network participation.

ckb-light-client run --config-file ./testnet.toml

See Also


Mempool

Short for "memory pool". A waiting area on full nodes for transactions that have been broadcasted to the network but have not yet been confirmed on the blockchain.

See Also


Metadata

Metadata is data that provides information about other data. capacity, type and lock in cells are metadata, they occupy cell capacity and incur a state cost as well.

See Also


Micro-State

A small piece of state that is isolated and often able to be acted upon independently without knowing the total state of the network.

On Nervos, micro-state is represented by a Cell.

Synonyms

See Also


Miner

A network node that finds valid proof of work for new blocks, by repeated hashing.

See Also


Miner Fee

Another term for transaction fee.

Synonyms


Mining

Mining is the process by which a blockchain node get new token reward by verifying new transactions, finding valid proof of work and creating new blocks.

See Also


Mining Node

Mining nodes create new blocks by solving computational puzzles. They contribute to the network's security and consensus by actively validating and adding blocks to the blockchain.

ckb init --chain mainnet && ckb miner

See Also


Mining Reward

Native tokens paid to miners as a reward for providing the necessary computing resources for mining.

See Also


Multisig

The term multisig stands for multi-signature, which is a specific type of digital signatures that can be created through the combination of multiple unique signatures.


Native Token

The token issued as reward to a blockchain's consensus nodes. Nervos CKB's native token is CKByte.

See Also


NC-MAX

Nervos CKB's consensus algorithm, which follows NC's backbone protocol. The main innovation here is a two-step transaction confirmation mechanism

See Also


Neighbor

A node that is directly connected to another node in the blockchain peer to peer network.

See Also


Nervos Blockchain

The layer 1 blockchain of the Nervos Network known as the Common Knowledge Base.

Synonyms


Nervos DAO

Nervos DAO enable users to lock CKBytes to get compensation from Nervos CKB secondary issuance. This process is similar to staking on other platforms. Nervos DAO provides a "virtual hardcap" for CKByte holders to insulate them from inflation.

See Also


Network Hash Rate

A measurement of the total computational processing power which is dedicated to providing security to the network.

See Also


Node

A software client that participates in the network.

See Also


Nonce

In cryptography, a value that can only be used once. Nonce can refer to two things in blockchain context: 1. a proof-of-work nonce is the random value in a block satisfying the proof of work requirement; 2. an account nonce is a transaction counter in each account, which is used to prevent replay attacks.

See Also


Non-Fungible Token

Non-fungible tokens or NFTs are cryptographic assets on a blockchain with unique identification codes and metadata that distinguish them from each other.

See Also


Open Source

A piece of software where source code is freely available for examination or alteration by any third-party.

See Also


P2P

A shortname name for peer to peer.

Synonyms


Paper Wallet

A form of storing a recovery phrase or private keys offline by printing them on a piece of paper. This document would then be stored by traditional means in a secured location of the user's choosing, such as a safe.

See Also


Payment Address

A string of letters and numbers that cryptocurrency and assets can be sent to and from.

Nervos CKB mainnet addresses always begin with the prefix "ckb".

Synonyms


Payment Channel

A micropayment channel or payment channel is class of techniques designed to allow users to make multiple payment transactions without committing all of the transactions to the layer 1 blockchain. In a typical payment channel, only two transactions are added to the block chain but an unlimited or nearly unlimited number of payments can be made between the participants.

See Also


Peer to Peer

A peer-to-peer (P2P) service is a decentralized platform whereby two individuals interact directly with each other, without intermediation by a third party.

Synonyms

See Also


Private Key

A private key, also known as a secret key, is a variable in cryptography, known only to the owner(s) of the key, that is used with an algorithm to encrypt and decrypt data.

See Also


Proof of Work

PoW asks users to solve a cryptographic puzzle to prove ownershipo of a certain amount of computational resource to participate in the consensus. In general PoW is a more permissionless consensus mechanism than PoS.

In contrast to wildly spread misconception, PoW is not a "waste" of energy and does not induce more carbon emission. PoW is used in the Nervos layer 1 blockchain CKB.

See Also


Proof of Stake

PoS asks users to prove ownership of a certain amount of cryptocurrency (their “stake” in the network) in order to be able to participate in the consensus. PoS relies on weak-subjectivity due to unsolvable issues like long-range attack. In PoS system the future consensus quorum is decided by existing participants completely. PoS is used in layer 2 protocols on Nervos Network.

See Also


Propagation

A shorthand name for Block Propagation.

Synonyms


Public Key

A notion used only in public-key cryptography, a.k.a. asymmetric cryptography. A public key is a piece of information that can be known to others without compromising security. Unique for each user, a public key is associated with a private key known only to the user. The public key can be used to encrypt a message so that it can only be decrypted with the corresponding private key, or to verify that a message is authorized by the user with the corresponding private key.

See Also


Reward

An amount of CKBytes included in each new block as a reward by the network to the miner who found the proof-of-work solution.

See Also


Signature

A shorthand name for cryptographic signature.

Synonyms


Smart Contract

A smart contract is a self-executing contract with the terms of the agreement between contract creators and contract users being directly written into lines of code. The code and the agreements contained therein exist across a distributed, decentralized blockchain network. Also known as script on Nervos CKB.


State

Data stored on the blockchain. In most contexts this this means current data and excludes historical data.

See Also


State Bloat

The unlimited increase of state data in Ethereum. State bloat slows down node synchronization, raises the barrier of full node, thus hurts network decentralization.


State Channel

A layer 2 solution where a channel is set up between participants, where they can transact freely and cheaply. Only a transaction to set up the channel and close the channel is sent to mainnet. This allows for very high transaction throughput, but does rely on knowing number of participants up front and locking up of funds.


Tip

A shorthand name for tip block.

Synonyms


Tip Block

The most recent block to be confirmed in a blockchain. The tip block has the highest block height in the blockchain.

Synonyms

See Also


Transaction

Transaction is the basic object created and signed by users to interact with distributed ledger. Transactions update ledger state at users requests. A CKB transaction destroys some outputs created in previous transactions and creates some new outputs. We call the transaction output a cell in CKB.

See Also


Transaction Fee

A fee which is paid in the native token to miners in exchange for processing a transaction.

Synonyms

See Also


Token

A “token” often refers to non-native token on smart contract platform, such as UDT on Nervos Network or ERC20 on Ethereum.

See Also


Turing Complete

Turing Complete refers to a machine that, given enough time and memory along with the necessary instructions, can solve any computational problem, no matter how complex. The term is normally used to describe modern programming languages as most of them are Turing Complete (C++, Python, JavaScript, etc.).


UDT

Short for User-Defined Token, a customised token created with properties defined by the user. In normal usage, this most commonly refers to fungible tokens.

Synonyms


Unconfirmed

The state of a transaction that has not yet been confirmed. An unconfirmed transaction is not finalized and cannot be guaranteed.

Synonyms

See Also


Unconfirmed Transaction

A transaction that has not yet been confirmed. An unconfirmed transaction is not finalized and cannot be guaranteed.

Synonyms

See Also


User-Defined Token

A custom token created with properties defined by the user. In normal usage, this most commonly refers to fungible tokens.

A User-Defined Token is usually referred to by its abbreviation, UDT.

Synonyms

See Also


Wallet

User-facing software used to interact with on-chain entities such as assets, smart contracts and dapps. A wallet can include key management itself or delegate key management to external hardware for improved security.

See Also


Economics Glossary

Base Issuance

Base issuance is the basic CKByte issuance with a fixed and decreasing schedule. Base issuance is awarded to miners as incentives to protect the network and also as an indirect token distribution method.

Base issuance is limited to a finite total supply 33.6G (33.6 billion) CKBytes.

See Also


Base Reward

Base reward is the block reward (in CKBytes) to miners generated from the base issuance. Base reward halves approximately every 4 years until eventually reaching 0, like Bitcoin.

See Also


Commit Reward

A reward paid to miners in CKBytes for committing a previously proposed transaction. After the transaction has been committed it is confirmed.

See Also


Economic Abstraction

With proper tool support, users can use tokens other than CKByte (for example, stable coins) to pay transactions fees, a concept known as "Economic Abstraction".


Fiat Currency

Fiat currencies are a medium of exchange established as money, often by government regulation. Fiat money does not have intrinsic value and does not have use value. It has value only because a government maintains its value, or because parties engaging in exchange agree on its value.

See Also


Heavy Asset Problem

A common problem found in multi-asset blockchain platforms where the value of the assets stored on the chain gains significant value but the native token of the chain does not. This raises the incentive to attack the the network, but does not increase the security because the value of the native token is what is used to secure the network.

See Also


Liquidity

The ability for an asset to be bought or sold easily without causing a significant change in the current market price.

See Also


Proposal Reward

A reward paid to miners in CKBytes for proposing an unconfirmed transaction.

See Also


Secondary Issuance

The creation of new CKBytes that is paid to miners through secondary rewards. Secondary issuance follows a fixed inflation schedule of 1.344 billion CKBytes per year. Nervos DAO stakers are not affected by secondary issuance.

See Also


Secondary Reward

A subsidy paid to miners in CKBytes for providing the compute and storage requirements required for processing transactions and persisting data on Nervos.

Secondary rewards are created from secondary issuance, and continuously pay miners for the verification of transactions and preservation of blockchain state.

See Also


Selfish Mining Attack

Selfish mining is a concept that was addressed by Cornell University researchers in detail in a 2013 report. In this attack, malicious miners gain unfair block rewards by deliberately orphaning blocks mined by others.

See Also


Starving Layer 1 Problem

A scenario that can arise in multi-layer blockchain platforms where the vast majority of the transaction traffic moves from layer 1 to layer 2, taking the vast majority of transaction fees with it. If layer 1 relies exclusively on transaction fees to support the security of the platform, it may end up not having enough incentives available to properly secure it.

See Also


State Rent

A recurring fee that is paid to persist and secure state data.

On Nervos, secondary issuance is used to boost the payment of state rent by users who occupy space on the Nervos blockchain.

See Also


Store of Assets

Similar to the concept of "Store of Value" in the context of Bitcoin, we call the utility "Store of Assets" when a blockchain keeps any crypto-assets securely and censorship-resistantly. Nervos CKB is such a Store of Assets or SoA.

See Also


Store of Value

Assets which can maintain their worth over time without depreciating

A good store of value either match or outpace the inflation rate of fiat currency, and has a reasonable amount of liquidity, allowing the asset to be easily sold.

See Also


Tail Emission

A type of reward that is paid to miners through a fixed amount of inflation.

See Also


Targeted Inflation

A form of inflation that only affects a specific subset of users.

Nervos uses Secondary Issuance to create targeted inflation on users who occupy space on the Nervos blockchain to pay State Rent. Long-term holders of CKBytes have the option of locking them in the Nervos DAO, which acts and an inflation shelter.

See Also


Tragedy of the Commons

A situation in a system where the participants act in accordance with their own self interest and deplete or destroy a shared resource through their collective action.

See Also


Tragedy of the Security Commons

A situation that can emerge on multi-asset blockchain platforms where asset tokens rely on the storage and security of the blockchain platform, but do not contribute back to the platform. As the number of assets that "ride for free" increases, so does the burden placed on the underlying blockchain platform. If the assets do not contribute to the underlying platform, the available security may not properly support the network.

See Also


Tragedy of the Storage Commons

A situation that can emerge on incentivized blockchain platforms where mining rewards are paid for inclusion of data to the blockchain, but no rewards exist for the long-term persistance of the blockchain data. As the size of the chain grows, so do the costs associated with persisting the data. If there is no direct incentive for persisting data, fewer and fewer nodes will do so. Eventually, too few nodes will be available to properly support the network.

See Also


Technical Glossary

Active Cell

Or live cell, a cell exists in the current CKB state. Only active cells can be used as inputs to new transactions.

Synonyms

See Also


Aggron

The first Nervos CKB testnet corresponding to mainnet Lina.

  • CKB version: >= v0.101.0 (latest stable is recommended)
  • Genesis hash: 0x10639e0895502b5688a6be8cf69460d76541bfa4821629d86d62ba0aae3f9606
  • Init command: ckb init --chain testnet
  • Launched at: 2020-05-22 04:00:00 UTC
  • ckb2021 activated at: 2021-10-24 03:00:00 UTC

Synonyms

Not To Be Confused With


Animagus

A framework layer that runs on top of Nervos CKB which provides an easy way to query for account balances without having to go through the cell collection process.

See Also


Args

Args is short for arguments. Arguments are data provided to the lock script or type script of a cell, similar to args provided to a function or method call.

Arguments are stored as part of the Cell when it is created.

See Also


Axon

Axon is a chain-based layer 2 protocol and framework with a practical security and economic model. Axon chains allow anyone to stake tokens on CKB to become a validator and participate in consensus.

See Also


Blake2b

A cryptographic hash function. BLAKE2b (or BLAKE2) is optimized for 64-bit platforms including NEON-enabled ARMs and produces digests of any size between 1 and 64 bytes. BLAKE2b is optimized for 8- to 32-bit platforms, and produces digests of any size between 1 and 32 bytes. CKB uses BLAKE2b as the default hash algorithm.

See Also


Block Subsidy

A payment that is made in the native currency of the blockchain that is paid to to miners for providing the computational resources create a block and secure the blockchain.

The subsidy consists is the portion of the total block reward that is issued out of inflation for creating the block, but does not include any additional transaction fees that may be paid on top.

Synonyms


Boxer

A lightweight Rust library for verifying the Nervos layer 1 blockchain, the Common Knowledge Base.

See Also


block_version

Version of a block. This field is reserved for the system, set to 0 by default.

pub const BLOCK_VERSION: Version = 0;

See Also


Cell Collection

The process of gathering cells that meet certain criteria.

For example: To find the balance of a particular account, all active cells for the address would need to be collected.

See Also


Cellbase

The transaction in each block that is responsible for the minting of new CKBytes.

This is the equivalent of a coinbase transaction in Bitcoin.

See Also


cellbase_maturity

Any referenced cellbase output must meet this requirement in a transaction; otherwise, the transaction is rejected. Cellbase outputs are "locked" and have to wait for 4 epochs (approximately 16 hours) to be confirmed before they become ready to be spent. This restriction is to avoid the risk of later transactions with cellbase root being rollbacked when a soft fork occurs.

pub(crate) const CELLBASE_MATURITY: EpochNumberWithFraction =
EpochNumberWithFraction::new_unchecked(4, 0, 1);

See Also


cell_deps

Pointers to live cells on the chain that allow scripts in the transaction to access (read-only) referenced live cells.

Find more in the essay Script dependencies.

See Also


Ckbhash

CKB uses blake2b as the default hash algorithm with the following configurations:

  • output digest size in bytes: 32
  • personalization: ckb-default-hash

ckbhash is used to denote the blake2b hash with the configurations above, there are example and test vectors in python 3:

import hashlib
import unittest

def ckbhash():
return hashlib.blake2b(digest_size=32, person=b'ckb-default-hash')

class TestCKBBlake2b(unittest.TestCase):

def test_empty_message(self):
hasher = ckbhash()
hasher.update(b'')
self.assertEqual('44f4c69744d5f8c55d642062949dcae49bc4e7ef43d388c5a12f42b5633d163e', hasher.hexdigest())

if __name__ == '__main__':
unittest.main()

See Also


CKB Merkle Tree

CKB Merkle Tree is a CBMT( Complete Binary Merkle Tree ) using following merge function:

ckbhash(left || right)

ckbhash is the hash function, || denotes binary concatenation.

See Also


Code Hash

A field in a Cell that contains a hash value which could refer to a specific piece of data, or a specific cell referenced by Type ID.

See Also


Commit

The process of taking a proposed transaction and adding it to the blockchain. After the transaction has been committed it is confirmed.

Miners are incentivized to commit transactions by being paid a commit reward.

See Also


Commitment Zone

Section of the block that contains transaction commitments. The commitment zone can only contain valid transactions which have appeared in the proposal zone of one of the previous 2 to 10 blocks.

See Also


Consume

The process of using a Live Cell as an input to a transaction.

The process of consumption marks the Live Cell as a Dead Cell. This is the equivalent of marking a UTXO as spent in Bitcoin.

See Also


Crypto Primitives

Well-established, low-level cryptographic algorithm commonly used to build out a cryptographic protocol.

See Also


dao_type_hash

NervosDAO’s type_hash.

Find more in CKB Genesis Script List.

See Also


Data

In Nervos specific contexts, data may refer to the data structure within a Cell. This structure is used to hold any form of information that needs to be stored on the Nervos blockchain.

In more general contexts, data may refer to any form of information.

See Also


Dead Cell

A cell that has been used as an input to a previous transaction and is consumed.

A dead cell cannot be used as an input to a new transaction, nor can it be used as a dependency. It is effectively destroyed and removed from the active state of the network.

A dead cell is the equivalent of a "spent UTXO" in Bitcoin.

Synonyms

See Also


Dep Group

A method for referencing multiple dependencies which are commonly used together using a single dependency field.

See Also


Dep Type

A field that specifies the type of the dependency.

See Also


Deps

A shorthand name for dependencies.

Synonyms


Dependencies

Dependencies are commonly referred to as deps. Dependencies are cells that are referenced in a transaction. Cells that are referenced as dependencies are read-only and made available to any scripts executing within the transaction. Dependencies, or deps, are not consumed.

Synonyms

See Also


Duktape

Duktape is an embeddable Javascript engine, with a focus on portability and compact footprint.

Duktape is used to run JavaScript based smart contracts on Nervos.

See Also


Difficulty

A measurement of how difficult it is to solve the Proof of Work cryptographic puzzle required to create a block.

Networks automatically adjust the difficulty to control the speed at which blocks are generated as mining participants enter and exit the network.

See Also


Diviner

A deterministic testing framework for Rust.

See Also


Eaglesong

Eaglesong is a new hash function developed specifically for Nervos CKB proof-of-work, which is also suitable in other use cases in which a secure hash function is needed.

See Also


epoch_duration_target

The estimated epoch duration specified by NC-Max. Set as 4 hours in CKB.

pub(crate) const DEFAULT_EPOCH_DURATION_TARGET: u64 = 4 * 60 * 60; // 4 hours, unit: second

See Also


ERC20

An Ethereum token standard for basic fungible tokens.

An SUDT on Nervos is the equivalent of Ethereum tokens standards ERC20 or ERC777.

See Also


ERC721

An Ethereum token standard for non-fungible tokens.

See Also


ERC777

An updated Ethereum token standard for basic fungible tokens that is backwards compatible with ERC20.

An SUDT on Nervos is the equivalent of Ethereum tokens standards ERC20 or ERC777.

See Also


ERC1155

An Ethereum token standard that supports the creation any number of fungible or non-fungible tokens on a single contract.

See Also


Full Address

An address format used on Nervos that includes the full code hash of the lock script associated.

See Also


Generator

A program used to create transactions that can be broadcast to the Nervos CKB network.

Generators run locally on the client side (off-chain). They utilize user input and existing cells as program inputs, to create new cells with new states as output.


Genesis Block

The first block in the blockchain, used to initialize the global state. The genesis block is unique because it does not contain a reference to the previous block because it is the first.

See Also


genesis_hash

Hash of CKB genesis block. CKB Genesis Block was created in a decentralized manner that encourages everyone to generate a unique genesis block verifiably through the Genesis Block Generator. Nodes thus created and activated can be connected to any other node across the network to form a decentralized Common Knowledge Base.

The genesis block contains two main components:

See Also


Godwoken

Godwoken is a layer 2 rollup framework for Nervos CKB. It provides scaling capability, as well as an abstract account model to CKB.

See Also


Governance Script

A type script which defines the monetary policy of a User Defined Token (UDT).

See Also


Governance Script Hash

A Blake2b hash of a type script which is used as an identifier for the script when referenced by a cell.

Synonyms

See Also


Historical Cell

An alternative term for Dead Cell.

Synonyms

See Also


Inbound Connection

Inbound connection means it is initiated by the remote peer; and the connection itself is outgoing connection when we switch the subject to the remote peer.

See Also


Indexer

An application or library to trace live cells that comply with criteria specified by the developer or user.

See Also


initial_primary_epoch_reward

Incentives paid to miners in CKBytes by epoch in CKB base issuance. Under CKB's consensus, block interval is uncertain, while epoch can be fixed at approximately 4 hours, so reward issuance is determined by epoch. Each epoch issues 1_917_808_21917808 Shannons of CKBytes, whose total amount is fixed but halves every 4 years.

The initial base issuance is 4.2 billion CKBytes per year. Similar to Bitcoin, the base issuance halves approximately every 4 years until it stops.

To calculate, block reward = initial_primary_epoch_reward / epoch_length (the number of blocks in the epoch).

pub(crate) const INITIAL_PRIMARY_EPOCH_REWARD: Capacity = Capacity::shannons(1_917_808_21917808);

See Also


Input

A live cell that is used in a transaction. If the transaction is accepted by the network, the live cell gets consumed as input and labeled as a dead cell.

See Also


Keyper

A specification of how to manage wallet Lock Scripts which apply to a specific user.

See Also


Late Spawning

When a node joins a blockchain network for the first time after the network has already been in operation for a period of time.

A network is said to support late spawning if that participant can download and verify the entire blockchain without having to trust any of the participants in the network to feed them unaltered data.

See Also


Layer 1

Layer 1 of a decentralized ecosystem is the underlying blockchain architecture.

A proof of work blockchain known as the Common Knowledge Base (CKB) that serves as the base layer for the Nervos Network.

See Also


Layer 2

Layer 2 refers to a secondary framework or protocol that is built on top of an existing blockchain system.

The main goal of these protocols is to solve the transaction speed and scaling difficulties that are being faced by the major cryptocurrency networks.

See Also


Lina

The name of public mainnet of the Nervos CKB.

  • CKB version: >= v0.25.2 (latest stable is recommended)
  • Genesis hash: 0x92b197aa1fba0f63633922c61c92375c9c074a93e85963554f5499fe1450d0e5
  • Init command: ckb init --chain mainnet
  • Launched at: 2019-11-15 21:11:00 UTC

Synonyms

Not To Be Confused With

See Also


Live Cell

A cell that has not been consumed and is available for use.

This is similar to an unspent transaction output (UTXO) in Bitcoin.

Synonyms

See Also


Lock

A script that represents the ownership of a cell. A user successfully unlocks a cell and is able to consume it if the cell's lock script exits normally.

See Also

Lock Script

A script that enforces access and ownership of a cell. This script controls who has permission to use the cell as an input. Lock scripts accept user generated proofs or witnesses and including transaction as inputs.

See Also


Lock Script Hash

A Blake2b hash of a lock script which is used as an identifier for the script when referenced by a cell.

See Also


Mainnet

Short for "main network", the running Nervos CKB public blockchain. The name of the Nervos CKB Mainnet is Lina.

Synonyms

Not To Be Confused With


max_block_bytes

The maximum transaction size limit allowed in a block in bytes. Estimated based on the size consumed by 1000 2-in-2-out secp256k1 transactions.

pub const MAX_BLOCK_BYTES: u64 = TWO_IN_TWO_OUT_BYTES * TWO_IN_TWO_OUT_COUNT;

max_block_cycles

The maximum transaction cycle limit allowed in a block. Estimated based on the cycles consumed by 1000 2-in-2-out secp256k1 transactions.

/// cycles of a typical two-in-two-out tx.
pub const TWO_IN_TWO_OUT_CYCLES: Cycle = 3_500_000;

/// count of two-in-two-out txs a block should capable to package.
const TWO_IN_TWO_OUT_COUNT: u64 = 1_000;
pub(crate) const MAX_BLOCK_CYCLES: u64 = TWO_IN_TWO_OUT_CYCLES * TWO_IN_TWO_OUT_COUNT;

See Also


max_block_proposals_limit

The maximum amount of proposals contained in one block. The default value starts from 1.5.

TWO_IN_TWO_OUT_COUNT
pub const MAX_BLOCK_PROPOSALS_LIMIT: u64 = 1_500;

See Also


max_uncles_num

The maximum number (Uint64) of uncle blocks allowed for one block. Set as 2 by default.

const MAX_UNCLE_NUM: usize = 2;

See Also


median_time_block_count

A timestamp is valid only when it is greater than the median timestamp of the previous 37 blocks.

const MEDIAN_TIME_BLOCK_COUNT: usize = 37;

Minting

The process of creating of new tokens.

See Also


Molecule

A serialization framework for encoding data widely used on the Nervos Network.

See Also


Muta

A highly customizable, high-performance blockchain framework designed to support proof of stake, BFT consensus and smart contracts.

See Also


Nervos CKB

The layer 1 blockchain of the Nervos Network, the Common Knowledge Base.

Nervos CKB is often referred to as the Nervos Blockchain.

Synonyms

See Also


Off-Chain Computation

A programming model where all computation is done off-chain to reduce the burden on the nodes in the network and provide higher levels of scalability. Nervos uses off-chain computation and on-chain verification.

See Also


Off-Chain Scaling

Off-chain scaling is the approach that only using the blockchain as a secure asset and settlement platform in conjunction with transferring almost all transactions off the blockchain.

See Also


Off-Chain State

The data of an application that is not stored on the blockchain, or is not accessible by on-chain smart contracts.

See Also


On-Chain Computation

A programming model where all computation by smart contracts is done on-chain by every node on the network simultaneously.

Ethereum uses on-chain computation.

See Also


On-Chain Scaling

On-chain scaling solution refer to extending the throughput of the consensus process, or increasing network throughput as node number increases.

See Also


On-Chain State

The data of an application that is stored on the blockchain and is accessible by on-chain smart contracts.

Nervos provides on-chain state for all smart contracts.

See Also


On-Chain Verification

A programming model where all computation is done off-chain to reduce the burden on the nodes in the network, but verification of the resulting data is done on-chain to enforce the smart contract rules created by the developer.

Nervos uses off-chain computation and on-chain verification.

See Also


Open Transaction

A signed piece of a transaction that is incomplete and invalid on its own. When combined with other signed transaction pieces can form a complete transaction which can be processed.

One use of open transactions is to create the functionality required for a trustless decentalized exchange.

See Also


Optimistic Rollup

A rollup of transactions that use fraud proofs to offer increased layer 2 transaction throughput while using the security and data availability provided by layer 1.

See Also


Orphan

A shorthand name for Orphan Block.

Synonyms


Orphan Block

An orphan block is a valid block that is not included in the main fork due to, for example, a lag within the network itself. There can be two miners who solve a block simultaneously in NC-Max. They are non-main-chain blocks, also known as stale blocks.

In Nervos, orphan blocks are better described as Uncles.

Synonyms

See Also


Orphan Rate

A measure of the speed at which Orphan blocks occur within the blockchain network.

See Also


orphan_rate_target

The estimated orphan block rate specified in NC-max. Set as 2.5% in CKB.

// o_ideal = 1/40 = 2.5%
pub(crate) const DEFAULT_ORPHAN_RATE_TARGET: (u32, u32) = (1, 40);

See Also


Orphan Transactions

Orphan transactions are those whose parental transactions are missing at the time that they are processed. These transactions are not propagated to other nodes until all of their missing parents are received, and they thus end up languishing in a local buffer until evicted or their parents are found.

See Also


Outbound Connection

Also knowns as "outgoing connection".

A TCP connection is outgoing for the node if it was initiated (sent the TCP SYN packet) by the node in the context.

See Also


Outpoint

A particular output Cell in a transaction.

See Also


Output

A live cell that is created in a transaction.

See Also


Overlord

A byzantine fault tollerant consensus algorithm designed by Nervos for Huobi which can support thousands of transactions per second.

See Also


P2WSH

A Pay-to-Witness-Script-Hash (P2WSH) is a type of Bitcoin transaction similar to a P2SH transaction in most ways, except that it uses SegWit.


permanent_difficulty_in_dummy

Keeps the difficulty permanent if PoW is dummy when dev-chain disables NC-MAX difficulty adjustment. As boolean, it can be enabled through configuration.

See Also


Polyjuice

Polyjuice provides an Ethereum compatible runtime on Godwoken.

See Also


primary_epoch_reward_halving_interval

The halving cycle of epoch reward in CKB base issuance, typically every four years. The mining reward halves when the halving interval occurs.

pub(crate) const DEFAULT_PRIMARY_EPOCH_REWARD_HALVING_INTERVAL: EpochNumber =
4 * 365 * 24 * 60 * 60 / DEFAULT_EPOCH_DURATION_TARGET; // every 4 years

See Also


Proposal Zone

Section of the block that contains transaction proposals.

See Also


Propose

The process of taking an unconfirmed transaction out of the mempool and proposing it for commitment. A transaction is not confirmed until after it has been committed.

Miners are incentivized to propose transactions by being paid a proposal reward.

See Also


proposer_reward_ratio

The reward ratio from transaction fees for miners who submit proposals specified by NC-Max. It is set as 40% in CKB, meaning the miner who first submits the transaction proposal will be rewarded with 40% of the transaction fee.

const PROPOSER_REWARD_RATIO: Ratio = Ratio::new(4, 10);

See Also


RISC-V

An open standard instruction set architecture (ISA) for general computing.

RISC-V is the instruction set used by the CKB-VM.

See Also


Schnorr Signature

A cryptographic signature scheme for signing and verification.

See Also


Script

A program that executes on the CKB-VM. A Script can be one of two types:

  • Lock Script - Used to control ownership and access to a Cell.
  • Type Script - Used to control how a Cell is used in a transaction.

A script is a binary executable in the ELF format for the RISC-V architecture, a program that runs on the CKB-VM.

See Also


secondary_epoch_reward

The secondary reward per epoch. Issued according to CKB’s tokenomics detailed in RFC0015.

Secondary issuance is designed to collect state rent, and has an issuance amount that is constant over time. After base issuance stops, there will only be secondary issuance.

Secondary issuance has two parts. One is a fixed amount of base incentive (approximately 134.4 million CKBytes per year), while the other varies according to the number of CKBytes currently occupied.

pub(crate) const DEFAULT_SECONDARY_EPOCH_REWARD: Capacity = Capacity::shannons(613_698_63013698);

See also


secp256k1_blake160_sighash_all_type_hash

Type hash of secp256k1_blake160_sighash_all in CKB genesis scripts.

Find more details here.


secp256k1_blake160_multisig_all_type_hash

Type hash of secp256k1_blake160_multisig_all in CKB genesis scripts.

Find more details here.


Seed Cell

A design pattern on Nervos from creating unique identifiers used to create unforgeable assets.

See Also


Shannon

A fractional denomination of CKBytes. One CKByte is equal to 100,000,000 Shannons.

A Shannon is the equivalent of a Bitcoin Satoshi.

See Also


Short Address

An address format on Nervos that does not include a code hash of the associated lock script, instead using one of the many common lock scripts.

The short address format is the most common address format used, and is often referred to as simply "address".

Synonyms

See Also


Simple UDT

A standard that defines a the most basic implementation of a UDT fungible token on Nervos.

An SUDT on Nervos is the equivalent of Ethereum tokens standards ERC20 or ERC777.

Synonyms

See Also


Since

since is the u64 (unsigned 64-bit integer) field in transaction input for preventing inclusion before a certain block timestamp or a block number.

See Also


SPV

An abbreviation for Simplified Payment Verification. A protocol for using a blockchain cryptocurrency without having to operate a full node.

SPV clients require far less data to be stored, but also must requires the trust of the network clients it is connected to directly.

See Also


SPV Wallet

A light-weight cryptocurrency wallet that uses the SPV protocol.

See Also


SUDT

An abbreviation for Simple UDT.

Synonyms


Testnet

Short for “test network,” a network used to simulate the behavior of the Mainnet. The name of the Nervos CKB Testnet is Aggron.

Synonyms

Not To Be Confused With


Transaction Confirmation Number

The number of confirmations required for a transaction to be added to a block.

As permissionless blockchain designs offer only probabilistic finality, a transaction can never be fully confirmed, facing an adversary with infinite computational power. Therefore, users and apps can choose a number they deem secure. We briefly discuss one factor here that influences the level of security: the recent orphan rate. It takes 6 confirmations to fully settle a transaction when the orphan rate is 0, and 24 confirmations when the rate reaches 2.5% to achieve the same level of security (See the rationale and calculation here).

In blockchain settlement assurance, transaction confirmation is one of the variables that cannot be easily quantified (See Nic Carter’s article). The exact number is open to adjustment depending on the security level that users desire. Nervos CKB sets a minimum of 15 confirmations, which should be considered conservative.

See Also


Transaction Hash

Transaction hash, or Txhash, is the unique identifier of a transaction in a blockchain that acts as a record or proof that the transaction has taken place. To get a transaction hash in CKB, the transaction is serialized via Molecule, then the serialized raw is feed to ckbhash function. Its schema is:

table Transaction {
raw: RawTransaction,
witnesses: BytesVec,
}

Transaction hash is generated by the serialized raw structure through ckbhash.

See Also


Transaction Witness Hash

Transaction witness hash is generated by the serialized transaction through ckbhash. Transaction is serialized via molecule in CKB. Its schema is:

table Transaction {
raw: RawTransaction,
witnesses: BytesVec,
}

See Also


Transaction Root

The field transactions_root in header is

ckbhash(T || W)

ckbhash is the hash function, || denotes binary concatenation.

T is the root of a CKB Merkle Tree, which items are the transaction hashes of all the transactions in the block.

W is also the root of a CKB Merkle Tree, but the items are the Transaction Witness Hash of all the transactions in the block.

See Also


tx_proposal_window

Interval for submitting proposals in the second stage specified by NC-Max. Set between 2 and 10 blocks in CKB.

As shown above, when a transaction is first proposed in Block 13, it can be committed in the window between Block 15 and Block 23.

pub(crate) const TX_PROPOSAL_WINDOW: ProposalWindow = ProposalWindow(2, 10);

tx_version

The version of a transaction. This field is set to 0 and is reserved for the system.

pub const TX_VERSION: Version = 0;

type_id

One of the CKB system_scripts. A unique feature of Type ID is that it‘s a CKB built-in script directly implemented in Rust. It doesn't run in CKB-VM but can be used in the same way as other CKB genesis scripts.

For a deeper understanding of Type ID, check out this blog post: Introduction to CKB Script Programming 6: Type ID (also translated into Chinese).

See Also


type_id_code_hash

The code_hash of type_id. In view of the specificity of type_id, type_id_code_hash is hard-coded, not the hash of the actual code.

See Also


Type Script

A script that enforces the rules that must be followed in a transaction for a cell to be consumed as an input or for a cell to be created as an output.

See Also


Type Script Hash

Or type_hash, a Blake2b hash of a Type Script which is used as an identifier for the Script when referenced by a Cell.

The two entities in the data structure of CKB’s cell are lock and type. Type scripts can capture any validation logic needed in the cell transformation.

Type scripts can implement economic constructs as well. NervosDAO is completely implemented as a type script with minimal support from the consensus layer.

See Also


Uncle

Or Uncle Block. Uncle blocks are created when two blocks are mined and submitted to the ledger at roughly the same time. Only one can enter the ledger as an included block, and the other does not.

Uncles are paid a reduced block reward when they are found and reported.

On Nervos, Uncles are tracked by consensus to adjust the block interval of the network.

An uncle block has to meet the following conditions:

  • An uncle should not be on the main chain; in other words, it should not be an uncle if it includes any block from the main chain.
  • Uncle’s block number must be smaller than the block‘s number that later includes it.
  • Uncle‘s parent must be on the main chain, or uncle’s parent must also be an uncle. In other words, uncle must be linkable to the main chain in any way. It can never be a random block that is not on the main chain.
- if !snapshot.is_main_chain(&uncle.hash()) // It should not be on the main chain.
- && !snapshot.is_uncle(&uncle.hash()) // It should not be an uncle twice.
- && uncle.number() < candidate_number // The block number of the uncle should be smaller than that of any block on the main chain.
- && (uncles.iter().any(|u| u.hash() == parent_hash)
|| snapshot.is_main_chain(&parent_hash) // Uncle block should not be parentless. The parent of un uncle must be a block on the main chain or another uncle.
|| snapshot.is_uncle(&parent_hash))

As illustrated above, A is the main chain. B3 can be the uncle of A4 (to be included in A4), since B3 is linked to A2. However, B4 cannot be included in A4, since the uncle’s block number must be smaller than A4, the current block on the main chain.

Similarly, B4 can be the uncle of A5 (be included by A5). Although B4‘s parent, B3, is not on the main chain, B3 is the uncle of A4. For this reason, B4 is a legal uncle, and B3 cannot be included by A5.

C2 and C3 cannot be linked to the main chain as their parent is unknown, therefore, they cannot be uncles.

See Also

Synonyms

See Also


Uncle Rate

See Also


Validator

A script that is used to ensure that the transactions created by the generators are valid. Validators are scripts that run in CKB-VM as either lock scripts or type scripts.

See Also


Witness

A set of cryptographic proof containing the data required to prove authorization of the resources used in the transaction.

See Also


Zk-SNARK

A form of cryptographic proof, that when used in cryptocurrencies, allows for privacy features which do not reveal the amounts or participants in transactions.

Zk-SNARKs require a trusted setup, but are otherwise trustless.

See Also


Zk-STARK

A form of cryptographic proof, that when used in cryptocurrencies, allows for privacy features which do not reveal the amounts or participants in transactions.

Unlike Zk-SNARKs, Zk-STARKs do not require a trusted setup.

See Also


- +

Glossary

Glossary Sections


General Glossary

Account

A kind of basic object in distributed ledger used to keep the balance and other information of users.


Address

A label consists of string of letters and numbers that anonymously represents user's identity on chain. Crypto assets can be sent to and/or from addresses.

Synonyms


Asset

A piece of data that has value or that represents an entity having value.

Synonyms


Block

A grouping of transactions, marked with a timestamp, and a fingerprint of the previous block. The block header is hashed to produce a proof of work, thereby validating the transactions. Valid blocks are added to the main blockchain by network consensus.

See Also


Block Height

Block height is the total number of blocks that have been confirmed on the blockchain, also used to identify a unique block when specifying a particular block height, as there is always an exact block at any block height.

Synonyms

See Also


Block Interval

Also known as Block Time. Block interval is the length of time it takes to create a new block in a cryptocurrency blockchain. Block interval is the measure of the time it takes the miners or validators within a network to verify transactions within one block and produce a new block in that blockchain. The block interval is variable on Nervos blockchain.

The block interval on the Bitcoin blockchain is approximately every 10 minutes. The block interval on Nervos is variable, but is usually under 10 seconds.

Synonyms

See Also


Block Propagation

The process of synchronizing a new block to the majority of full nodes in the network. Block propagation is a well-known bottleneck that prevents Bitcoin from scaling.

Block propagation time is an average time that is needed for the new block to reach the majority of nodes in the network. Long block propagation delay reduces the node's resistance against 51% attacks.

Synonyms

See Also


Block Reward

The amount of cryptocurrency credited to a miner's account after the miner successfully adds a block of transactions to the blockchain.

In Nervos CKB, block rewards are the CKBytes credited to a miner's account after a block is successfully added to CKB by the miner.

See Also


Block Time

Alternatively referred to as Block Interval.

Synonyms


Blockchain

A data structure maintaining a growing list of records, organized as a chain of blocks. Each block, apart from the first one, is cryptographically linked to the previous block, thus creating a chain-like structure.

The cryptographic link ensures any party with the last block can verify that none of the historical data is modified after the creation of this block.

See Also


BLS Signature

A cryptographic signature scheme for signing and verification. BLS is short for Boneh–Lynn–Shacham.

See Also


Broadcast

Blocks are sent to all nodes in a blockchain network.

See Also


Capacity

The maximum space (in bytes) that a cell can occupy on the Nervos CKB.

Synonyms

See Also


Cell

All data on Nervos CKB is stored in cells. Cells are the primary state units in CKB, within them users can include arbitrary states.

A cell has 4 fields: capacity, data, type and lock.

Synonyms

See Also


Cell Model

A representation of how state is managed on Nervos CKB. The cell model is a more generic state model than either Bitcoin's UTXO or Ethereum's account model.

The cell model is a new construction that combines many of the advantages of Ethereum's account model with the asset ownership and proof-based verification properties of Bitcoin's UTXO model.

See Also


Censorship Resistance

Censorship resistance in blockchain generally means that it is difficult for a malicious party to prevent the blockchain from confirming a set of transactions generated by honest users.


Chain

A shorthand name for blockchain.

Synonyms


CKB

An abbreviation which can have different meanings depending on the context:

  • Common Knowledge Base - The layer 1 blockchain of the Nervos Network.
  • Common Knowledge Byte - The native token of the Nervos Common Knowledge Base.

Synonyms


CKByte

A shorthand name for Common Knowledge Byte.

CKByte is also sometimes shortened to CKB. Exchanges often use CKB as the ticker symbol.

Synonyms

Not To Be Confused With


CKB-VM

CKB VM is a crypto-agnostic virtual machine, a RISC-V instruction set based VM for executing both on-chain and off-chain code.

See Also


Code Hash

A field in a cell which contains a hash value that can refer to a specific piece of data, or a specific cell referenced by Type ID.

See Also


Cold Storage

A method of securing funds by placing them in a cold wallet; a type of wallet that is never connected to the internet.

See Also


Cold Wallet

A wallet that is used to secure assets offline. This wallet is permanently disconnected from the internet, and not vulnerable to attacks which rely on an active internet connection.

See Also


Commit

Nervos CKB's consensus algorithm, NC-Max consensus, has two phases: propose and commit. Commit is the process of including a valid proposed transaction into a new block.


Commit-Chain

A scheme that enables the off-chain processing of transactions by one or more operators with on-chain state update commitments that do not contain per-transaction data.


Commit Reward

A reward paid to miners in CKBytes on inclusion of previously proposed transactions.


Common Knowledge Base

A layer 1 proof of work blockchain that provides a foundation of decentralized trust for the Nervos Network.

Synonyms

Not To Be Confused With

See Also


Common Knowledge Byte

The native token of the Nervos layer 1 blockchain, the Common Knowledge Base.

Common Knowledge Byte is often abbreviated as CKByte or CKB.

Owning a CKByte entitles the holder to store one byte of data on the Nervos CKB blockchain.

Synonyms

Not To Be Confused With

See Also


Confirmation

A process where a transaction has been accepted and verified by the network and included in a block.

See Also


Consensus

An algorithm executed among a number of distributed participants, ensuring that all participants faithfully executing this algorithm can reach agreement on some data value even if the other participants are faulty or malicious.

See Also


Consume

The process of using a live cell as an input to a transaction. The consumption processes indicate that live cell turns into a dead cell.


Contract Account

An account containing code that executes automatically whenever it receives an event from another account.

See Also


Cryptocurrency

A cryptocurrency is a digital or virtual currency that is secured by blockchain and cryptography, which makes it nearly impossible to counterfeit or double-spend.

See Also


Cryptographic Signature

A concise piece of proof data. Cryptographic signature schemes are a fundamental component of cryptocurrency networks that verify the integrity and non-repudiation of transaction messages across the network.

Synonyms


Cryptography

Cryptography is the practice and study of techniques for secure communication in the presence of adversarial behavior.

See Also


Cycles

The number of RISC-V computational cycles required by a script to execute. It's a metric used to prevent malicious behavior such as infinite loops, that's why it is called cycles.

This is a similar concept to Ethereum's Gas, we set cycles to ensure optimal performance and security. Scripts must stay within cycle limits, otherwise the block will be rejected by CKB nodes.

See Also


DAO

A decentralized autonomous organization (DAO) is an organization represented by rules encoded as a computer program that is transparent, controlled by the organization members and not influenced by a centralized entity, in other words they are member-owned communities without centralized leadership. A DAO's financial transaction record and program rules are maintained on a blockchain.

See Also


DApp

Decentralized application. At a minimum, it is a smart contract and a web user interface. In a broader sense, DApps are web applications that are built on top of open, decentralized, peer-to-peer infrastructure services. Additionally, many DApps include decentralized storage and/or a message protocol and platform.


Data

In cell model, data is a field in a cell which can store arbitrary bytes.

See Also


Decentralization

In blockchain, decentralization refers to the transfer of control and decision-making from a centralized entity (individual, organization, or group thereof) to a distributed network.

See Also


DeFi

Short for "decentralized finance", a broad category of DApps aiming to provide financial services backed by the blockchain, without any intermediaries, so anyone with an internet connection can participate.


Digital Asset

A digital asset is an individual piece of data that has value, or represents another entity that has value.

Digital assets are most commonly represented as tokens, which may be used as digital currency or represent physical items such as real estate.

Synonyms


Digital Currency

A type of currency that primarily exists digitally over the internet. Physical representations of the currency, in the form of cards, bills, or coins, may exist, but are secondary mediums.

See Also


Distributed

A system where components are spread across multiple nodes to parallelize workloads, add redundancy, or eliminate single points of failure.

See Also


Double-Spending

Double-spending is the risk that a digital token is spent twice or more. In the context of blockchain, it happens when the transaction spending a digital token is cancelled after confirmation, and the same token is spent in another transaction.

See Also


Epoch

An epoch is a period of time for a set of blocks.

In Nervos, the PoW difficulty changes on a new epoch. All the blocks in the same epoch share the same difficulty target. The difficulty adjustment algorithm aims to stabilize the orphan block rate at 2.5% and the epoch duration at 4 hours.

See Also


Fee

The sender of a transaction often includes a fee to the network for processing the requested transaction. There's no minimum fee rate set in consensus, but there's a minimum fee rate 1,000 Shannons/KB in CKB's P2P network. (1 Shannon = 10-8 CKB)

See Also


Fee Rate

A tip per byte that a user offers to the miners for including his transaction in a block on the blockchain.

This is a same concept to Bitcoin's Fee Rate(often spelled feerate).

See Also

First-Class Assets

Assets that 1. the asset itself (rather than a reference to the asset) can be passed directly in smart contract interactions, and 2. directly controlled by owners without any intermediaries.

See Also


Fork

A change in protocol causing the creation of an alternative chain, or a temporal divergence in two potential block paths during mining.


Full Node

A full node is an essential component of the CKB network. It stores and syncs the entire blockchain, verifies the validity of blocks and transactions, and enforces the network's consensus rules.

ckb init --chain mainnet && ckb run

See Also


Full Payload Format

The deprecated full payload format directly encodes all data field of lock script. The encode rule of deprecated full payload format is Bech32.

See Also


Fungible Token

A fungible token can be fiat currencies like the dollar or a cryptocurrency like Bitcoin.

Fungible tokens or assets are divisible and non-unique.

See Also


Gas Limit

The maximum amount of gas a transaction or block may consume.

See Also


Hard-Fork

A permanent divergence in the blockchain; also known as a hard-forking change. One commonly occurs when nonupgraded nodes can’t validate blocks created by upgraded nodes that follow newer consensus rules. Not to be confused with a fork, soft fork, software fork, or Git fork.


Hardware Wallet

A hardware wallet is a form of cold wallet. A hardware wallet is a cryptocurrency wallet that stores the user's private keys (a critical piece of information used to authorize outgoing transactions on the blockchain network) in a secure hardware device.

See Also


Hash

A fixed-length fingerprint of variable-size input, produced by a hash function.


Hash Rate

Hash rate is a measure of the computational power per second used when mining. These operations are known as "hashing".

See Also


Height

A shorthand name for block height.

Synonyms


Light Client

As a low-resource node, a light client allows users to sync with a blockchain in a cryptographically secure manner without having to store the whole blockchain.


Light Node

A light node downloads only the headers of the blockchain, conserving resources. It relies on other nodes for full transaction data and is a lightweight option for network participation.

ckb-light-client run --config-file ./testnet.toml

See Also


Mempool

Short for "memory pool". A waiting area on full nodes for transactions that have been broadcasted to the network but have not yet been confirmed on the blockchain.

See Also


Metadata

Metadata is data that provides information about other data. capacity, type and lock in cells are metadata, they occupy cell capacity and incur a state cost as well.

See Also


Micro-State

A small piece of state that is isolated and often able to be acted upon independently without knowing the total state of the network.

On Nervos, micro-state is represented by a Cell.

Synonyms

See Also


Miner

A network node that finds valid proof of work for new blocks, by repeated hashing.

See Also


Miner Fee

Another term for transaction fee.

Synonyms


Mining

Mining is the process by which a blockchain node get new token reward by verifying new transactions, finding valid proof of work and creating new blocks.

See Also


Mining Node

Mining nodes create new blocks by solving computational puzzles. They contribute to the network's security and consensus by actively validating and adding blocks to the blockchain.

ckb init --chain mainnet && ckb miner

See Also


Mining Reward

Native tokens paid to miners as a reward for providing the necessary computing resources for mining.

See Also


Multisig

The term multisig stands for multi-signature, which is a specific type of digital signatures that can be created through the combination of multiple unique signatures.


Native Token

The token issued as reward to a blockchain's consensus nodes. Nervos CKB's native token is CKByte.

See Also


NC-MAX

Nervos CKB's consensus algorithm, which follows NC's backbone protocol. The main innovation here is a two-step transaction confirmation mechanism

See Also


Neighbor

A node that is directly connected to another node in the blockchain peer to peer network.

See Also


Nervos Blockchain

The layer 1 blockchain of the Nervos Network known as the Common Knowledge Base.

Synonyms


Nervos DAO

Nervos DAO enable users to lock CKBytes to get compensation from Nervos CKB secondary issuance. This process is similar to staking on other platforms. Nervos DAO provides a "virtual hardcap" for CKByte holders to insulate them from inflation.

See Also


Network Hash Rate

A measurement of the total computational processing power which is dedicated to providing security to the network.

See Also


Node

A software client that participates in the network.

See Also


Nonce

In cryptography, a value that can only be used once. Nonce can refer to two things in blockchain context: 1. a proof-of-work nonce is the random value in a block satisfying the proof of work requirement; 2. an account nonce is a transaction counter in each account, which is used to prevent replay attacks.

See Also


Non-Fungible Token

Non-fungible tokens or NFTs are cryptographic assets on a blockchain with unique identification codes and metadata that distinguish them from each other.

See Also


Open Source

A piece of software where source code is freely available for examination or alteration by any third-party.

See Also


P2P

A shortname name for peer to peer.

Synonyms


Paper Wallet

A form of storing a recovery phrase or private keys offline by printing them on a piece of paper. This document would then be stored by traditional means in a secured location of the user's choosing, such as a safe.

See Also


Payment Address

A string of letters and numbers that cryptocurrency and assets can be sent to and from.

Nervos CKB mainnet addresses always begin with the prefix "ckb".

Synonyms


Payment Channel

A micropayment channel or payment channel is class of techniques designed to allow users to make multiple payment transactions without committing all of the transactions to the layer 1 blockchain. In a typical payment channel, only two transactions are added to the block chain but an unlimited or nearly unlimited number of payments can be made between the participants.

See Also


Peer to Peer

A peer-to-peer (P2P) service is a decentralized platform whereby two individuals interact directly with each other, without intermediation by a third party.

Synonyms

See Also


Private Key

A private key, also known as a secret key, is a variable in cryptography, known only to the owner(s) of the key, that is used with an algorithm to encrypt and decrypt data.

See Also


Proof of Work

PoW asks users to solve a cryptographic puzzle to prove ownershipo of a certain amount of computational resource to participate in the consensus. In general PoW is a more permissionless consensus mechanism than PoS.

In contrast to wildly spread misconception, PoW is not a "waste" of energy and does not induce more carbon emission. PoW is used in the Nervos layer 1 blockchain CKB.

See Also


Proof of Stake

PoS asks users to prove ownership of a certain amount of cryptocurrency (their “stake” in the network) in order to be able to participate in the consensus. PoS relies on weak-subjectivity due to unsolvable issues like long-range attack. In PoS system the future consensus quorum is decided by existing participants completely. PoS is used in layer 2 protocols on Nervos Network.

See Also


Propagation

A shorthand name for Block Propagation.

Synonyms


Public Key

A notion used only in public-key cryptography, a.k.a. asymmetric cryptography. A public key is a piece of information that can be known to others without compromising security. Unique for each user, a public key is associated with a private key known only to the user. The public key can be used to encrypt a message so that it can only be decrypted with the corresponding private key, or to verify that a message is authorized by the user with the corresponding private key.

See Also


Reward

An amount of CKBytes included in each new block as a reward by the network to the miner who found the proof-of-work solution.

See Also


Signature

A shorthand name for cryptographic signature.

Synonyms


Smart Contract

A smart contract is a self-executing contract with the terms of the agreement between contract creators and contract users being directly written into lines of code. The code and the agreements contained therein exist across a distributed, decentralized blockchain network. Also known as script on Nervos CKB.


State

Data stored on the blockchain. In most contexts this this means current data and excludes historical data.

See Also


State Bloat

The unlimited increase of state data in Ethereum. State bloat slows down node synchronization, raises the barrier of full node, thus hurts network decentralization.


State Channel

A layer 2 solution where a channel is set up between participants, where they can transact freely and cheaply. Only a transaction to set up the channel and close the channel is sent to mainnet. This allows for very high transaction throughput, but does rely on knowing number of participants up front and locking up of funds.


Tip

A shorthand name for tip block.

Synonyms


Tip Block

The most recent block to be confirmed in a blockchain. The tip block has the highest block height in the blockchain.

Synonyms

See Also


Transaction

Transaction is the basic object created and signed by users to interact with distributed ledger. Transactions update ledger state at users requests. A CKB transaction destroys some outputs created in previous transactions and creates some new outputs. We call the transaction output a cell in CKB.

See Also


Transaction Fee

A fee which is paid in the native token to miners in exchange for processing a transaction.

Synonyms

See Also


Token

A “token” often refers to non-native token on smart contract platform, such as UDT on Nervos Network or ERC20 on Ethereum.

See Also


Turing Complete

Turing Complete refers to a machine that, given enough time and memory along with the necessary instructions, can solve any computational problem, no matter how complex. The term is normally used to describe modern programming languages as most of them are Turing Complete (C++, Python, JavaScript, etc.).


UDT

Short for User-Defined Token, a customised token created with properties defined by the user. In normal usage, this most commonly refers to fungible tokens.

Synonyms


Unconfirmed

The state of a transaction that has not yet been confirmed. An unconfirmed transaction is not finalized and cannot be guaranteed.

Synonyms

See Also


Unconfirmed Transaction

A transaction that has not yet been confirmed. An unconfirmed transaction is not finalized and cannot be guaranteed.

Synonyms

See Also


User-Defined Token

A custom token created with properties defined by the user. In normal usage, this most commonly refers to fungible tokens.

A User-Defined Token is usually referred to by its abbreviation, UDT.

Synonyms

See Also


Wallet

User-facing software used to interact with on-chain entities such as assets, smart contracts and dapps. A wallet can include key management itself or delegate key management to external hardware for improved security.

See Also


Economics Glossary

Base Issuance

Base issuance is the basic CKByte issuance with a fixed and decreasing schedule. Base issuance is awarded to miners as incentives to protect the network and also as an indirect token distribution method.

Base issuance is limited to a finite total supply 33.6G (33.6 billion) CKBytes.

See Also


Base Reward

Base reward is the block reward (in CKBytes) to miners generated from the base issuance. Base reward halves approximately every 4 years until eventually reaching 0, like Bitcoin.

See Also


Commit Reward

A reward paid to miners in CKBytes for committing a previously proposed transaction. After the transaction has been committed it is confirmed.

See Also


Economic Abstraction

With proper tool support, users can use tokens other than CKByte (for example, stable coins) to pay transactions fees, a concept known as "Economic Abstraction".


Fiat Currency

Fiat currencies are a medium of exchange established as money, often by government regulation. Fiat money does not have intrinsic value and does not have use value. It has value only because a government maintains its value, or because parties engaging in exchange agree on its value.

See Also


Heavy Asset Problem

A common problem found in multi-asset blockchain platforms where the value of the assets stored on the chain gains significant value but the native token of the chain does not. This raises the incentive to attack the the network, but does not increase the security because the value of the native token is what is used to secure the network.

See Also


Liquidity

The ability for an asset to be bought or sold easily without causing a significant change in the current market price.

See Also


Proposal Reward

A reward paid to miners in CKBytes for proposing an unconfirmed transaction.

See Also


Secondary Issuance

The creation of new CKBytes that is paid to miners through secondary rewards. Secondary issuance follows a fixed inflation schedule of 1.344 billion CKBytes per year. Nervos DAO stakers are not affected by secondary issuance.

See Also


Secondary Reward

A subsidy paid to miners in CKBytes for providing the compute and storage requirements required for processing transactions and persisting data on Nervos.

Secondary rewards are created from secondary issuance, and continuously pay miners for the verification of transactions and preservation of blockchain state.

See Also


Selfish Mining Attack

Selfish mining is a concept that was addressed by Cornell University researchers in detail in a 2013 report. In this attack, malicious miners gain unfair block rewards by deliberately orphaning blocks mined by others.

See Also


Starving Layer 1 Problem

A scenario that can arise in multi-layer blockchain platforms where the vast majority of the transaction traffic moves from layer 1 to layer 2, taking the vast majority of transaction fees with it. If layer 1 relies exclusively on transaction fees to support the security of the platform, it may end up not having enough incentives available to properly secure it.

See Also


State Rent

A recurring fee that is paid to persist and secure state data.

On Nervos, secondary issuance is used to boost the payment of state rent by users who occupy space on the Nervos blockchain.

See Also


Store of Assets

Similar to the concept of "Store of Value" in the context of Bitcoin, we call the utility "Store of Assets" when a blockchain keeps any crypto-assets securely and censorship-resistantly. Nervos CKB is such a Store of Assets or SoA.

See Also


Store of Value

Assets which can maintain their worth over time without depreciating

A good store of value either match or outpace the inflation rate of fiat currency, and has a reasonable amount of liquidity, allowing the asset to be easily sold.

See Also


Tail Emission

A type of reward that is paid to miners through a fixed amount of inflation.

See Also


Targeted Inflation

A form of inflation that only affects a specific subset of users.

Nervos uses Secondary Issuance to create targeted inflation on users who occupy space on the Nervos blockchain to pay State Rent. Long-term holders of CKBytes have the option of locking them in the Nervos DAO, which acts and an inflation shelter.

See Also


Tragedy of the Commons

A situation in a system where the participants act in accordance with their own self interest and deplete or destroy a shared resource through their collective action.

See Also


Tragedy of the Security Commons

A situation that can emerge on multi-asset blockchain platforms where asset tokens rely on the storage and security of the blockchain platform, but do not contribute back to the platform. As the number of assets that "ride for free" increases, so does the burden placed on the underlying blockchain platform. If the assets do not contribute to the underlying platform, the available security may not properly support the network.

See Also


Tragedy of the Storage Commons

A situation that can emerge on incentivized blockchain platforms where mining rewards are paid for inclusion of data to the blockchain, but no rewards exist for the long-term persistence of the blockchain data. As the size of the chain grows, so do the costs associated with persisting the data. If there is no direct incentive for persisting data, fewer and fewer nodes will do so. Eventually, too few nodes will be available to properly support the network.

See Also


Technical Glossary

Active Cell

Or live cell, a cell exists in the current CKB state. Only active cells can be used as inputs to new transactions.

Synonyms

See Also


Aggron

The first Nervos CKB testnet corresponding to mainnet Lina.

  • CKB version: >= v0.101.0 (latest stable is recommended)
  • Genesis hash: 0x10639e0895502b5688a6be8cf69460d76541bfa4821629d86d62ba0aae3f9606
  • Init command: ckb init --chain testnet
  • Launched at: 2020-05-22 04:00:00 UTC
  • ckb2021 activated at: 2021-10-24 03:00:00 UTC

Synonyms

Not To Be Confused With


Animagus

A framework layer that runs on top of Nervos CKB which provides an easy way to query for account balances without having to go through the cell collection process.

See Also


Args

Args is short for arguments. Arguments are data provided to the lock script or type script of a cell, similar to args provided to a function or method call.

Arguments are stored as part of the Cell when it is created.

See Also


Axon

Axon is a chain-based layer 2 protocol and framework with a practical security and economic model. Axon chains allow anyone to stake tokens on CKB to become a validator and participate in consensus.

See Also


Blake2b

A cryptographic hash function. BLAKE2b (or BLAKE2) is optimized for 64-bit platforms including NEON-enabled ARMs and produces digests of any size between 1 and 64 bytes. BLAKE2b is optimized for 8- to 32-bit platforms, and produces digests of any size between 1 and 32 bytes. CKB uses BLAKE2b as the default hash algorithm.

See Also


Block Subsidy

A payment that is made in the native currency of the blockchain that is paid to to miners for providing the computational resources create a block and secure the blockchain.

The subsidy consists is the portion of the total block reward that is issued out of inflation for creating the block, but does not include any additional transaction fees that may be paid on top.

Synonyms


Boxer

A lightweight Rust library for verifying the Nervos layer 1 blockchain, the Common Knowledge Base.

See Also


block_version

Version of a block. This field is reserved for the system, set to 0 by default.

pub const BLOCK_VERSION: Version = 0;

See Also


Cell Collection

The process of gathering cells that meet certain criteria.

For example: To find the balance of a particular account, all active cells for the address would need to be collected.

See Also


Cellbase

The transaction in each block that is responsible for the minting of new CKBytes.

This is the equivalent of a coinbase transaction in Bitcoin.

See Also


cellbase_maturity

Any referenced cellbase output must meet this requirement in a transaction; otherwise, the transaction is rejected. Cellbase outputs are "locked" and have to wait for 4 epochs (approximately 16 hours) to be confirmed before they become ready to be spent. This restriction is to avoid the risk of later transactions with cellbase root being rollbacked when a soft fork occurs.

pub(crate) const CELLBASE_MATURITY: EpochNumberWithFraction =
EpochNumberWithFraction::new_unchecked(4, 0, 1);

See Also


cell_deps

Pointers to live cells on the chain that allow scripts in the transaction to access (read-only) referenced live cells.

Find more in the essay Script dependencies.

See Also


Ckbhash

CKB uses blake2b as the default hash algorithm with the following configurations:

  • output digest size in bytes: 32
  • personalization: ckb-default-hash

ckbhash is used to denote the blake2b hash with the configurations above, there are example and test vectors in python 3:

import hashlib
import unittest

def ckbhash():
return hashlib.blake2b(digest_size=32, person=b'ckb-default-hash')

class TestCKBBlake2b(unittest.TestCase):

def test_empty_message(self):
hasher = ckbhash()
hasher.update(b'')
self.assertEqual('44f4c69744d5f8c55d642062949dcae49bc4e7ef43d388c5a12f42b5633d163e', hasher.hexdigest())

if __name__ == '__main__':
unittest.main()

See Also


CKB Merkle Tree

CKB Merkle Tree is a CBMT( Complete Binary Merkle Tree ) using following merge function:

ckbhash(left || right)

ckbhash is the hash function, || denotes binary concatenation.

See Also


Code Hash

A field in a Cell that contains a hash value which could refer to a specific piece of data, or a specific cell referenced by Type ID.

See Also


Commit

The process of taking a proposed transaction and adding it to the blockchain. After the transaction has been committed it is confirmed.

Miners are incentivized to commit transactions by being paid a commit reward.

See Also


Commitment Zone

Section of the block that contains transaction commitments. The commitment zone can only contain valid transactions which have appeared in the proposal zone of one of the previous 2 to 10 blocks.

See Also


Consume

The process of using a Live Cell as an input to a transaction.

The process of consumption marks the Live Cell as a Dead Cell. This is the equivalent of marking a UTXO as spent in Bitcoin.

See Also


Crypto Primitives

Well-established, low-level cryptographic algorithm commonly used to build out a cryptographic protocol.

See Also


dao_type_hash

NervosDAO’s type_hash.

Find more in CKB Genesis Script List.

See Also


Data

In Nervos specific contexts, data may refer to the data structure within a Cell. This structure is used to hold any form of information that needs to be stored on the Nervos blockchain.

In more general contexts, data may refer to any form of information.

See Also


Dead Cell

A cell that has been used as an input to a previous transaction and is consumed.

A dead cell cannot be used as an input to a new transaction, nor can it be used as a dependency. It is effectively destroyed and removed from the active state of the network.

A dead cell is the equivalent of a "spent UTXO" in Bitcoin.

Synonyms

See Also


Dep Group

A method for referencing multiple dependencies which are commonly used together using a single dependency field.

See Also


Dep Type

A field that specifies the type of the dependency.

See Also


Deps

A shorthand name for dependencies.

Synonyms


Dependencies

Dependencies are commonly referred to as deps. Dependencies are cells that are referenced in a transaction. Cells that are referenced as dependencies are read-only and made available to any scripts executing within the transaction. Dependencies, or deps, are not consumed.

Synonyms

See Also


Duktape

Duktape is an embeddable Javascript engine, with a focus on portability and compact footprint.

Duktape is used to run JavaScript based smart contracts on Nervos.

See Also


Difficulty

A measurement of how difficult it is to solve the Proof of Work cryptographic puzzle required to create a block.

Networks automatically adjust the difficulty to control the speed at which blocks are generated as mining participants enter and exit the network.

See Also


Diviner

A deterministic testing framework for Rust.

See Also


Eaglesong

Eaglesong is a new hash function developed specifically for Nervos CKB proof-of-work, which is also suitable in other use cases in which a secure hash function is needed.

See Also


epoch_duration_target

The estimated epoch duration specified by NC-Max. Set as 4 hours in CKB.

pub(crate) const DEFAULT_EPOCH_DURATION_TARGET: u64 = 4 * 60 * 60; // 4 hours, unit: second

See Also


ERC20

An Ethereum token standard for basic fungible tokens.

An SUDT on Nervos is the equivalent of Ethereum tokens standards ERC20 or ERC777.

See Also


ERC721

An Ethereum token standard for non-fungible tokens.

See Also


ERC777

An updated Ethereum token standard for basic fungible tokens that is backwards compatible with ERC20.

An SUDT on Nervos is the equivalent of Ethereum tokens standards ERC20 or ERC777.

See Also


ERC1155

An Ethereum token standard that supports the creation any number of fungible or non-fungible tokens on a single contract.

See Also


Full Address

An address format used on Nervos that includes the full code hash of the lock script associated.

See Also


Generator

A program used to create transactions that can be broadcast to the Nervos CKB network.

Generators run locally on the client side (off-chain). They utilize user input and existing cells as program inputs, to create new cells with new states as output.


Genesis Block

The first block in the blockchain, used to initialize the global state. The genesis block is unique because it does not contain a reference to the previous block because it is the first.

See Also


genesis_hash

Hash of CKB genesis block. CKB Genesis Block was created in a decentralized manner that encourages everyone to generate a unique genesis block verifiably through the Genesis Block Generator. Nodes thus created and activated can be connected to any other node across the network to form a decentralized Common Knowledge Base.

The genesis block contains two main components:

See Also


Godwoken

Godwoken is a layer 2 rollup framework for Nervos CKB. It provides scaling capability, as well as an abstract account model to CKB.

See Also


Governance Script

A type script which defines the monetary policy of a User Defined Token (UDT).

See Also


Governance Script Hash

A Blake2b hash of a type script which is used as an identifier for the script when referenced by a cell.

Synonyms

See Also


Historical Cell

An alternative term for Dead Cell.

Synonyms

See Also


Inbound Connection

Inbound connection means it is initiated by the remote peer; and the connection itself is outgoing connection when we switch the subject to the remote peer.

See Also


Indexer

An application or library to trace live cells that comply with criteria specified by the developer or user.

See Also


initial_primary_epoch_reward

Incentives paid to miners in CKBytes by epoch in CKB base issuance. Under CKB's consensus, block interval is uncertain, while epoch can be fixed at approximately 4 hours, so reward issuance is determined by epoch. Each epoch issues 1_917_808_21917808 Shannons of CKBytes, whose total amount is fixed but halves every 4 years.

The initial base issuance is 4.2 billion CKBytes per year. Similar to Bitcoin, the base issuance halves approximately every 4 years until it stops.

To calculate, block reward = initial_primary_epoch_reward / epoch_length (the number of blocks in the epoch).

pub(crate) const INITIAL_PRIMARY_EPOCH_REWARD: Capacity = Capacity::shannons(1_917_808_21917808);

See Also


Input

A live cell that is used in a transaction. If the transaction is accepted by the network, the live cell gets consumed as input and labeled as a dead cell.

See Also


Keyper

A specification of how to manage wallet Lock Scripts which apply to a specific user.

See Also


Late Spawning

When a node joins a blockchain network for the first time after the network has already been in operation for a period of time.

A network is said to support late spawning if that participant can download and verify the entire blockchain without having to trust any of the participants in the network to feed them unaltered data.

See Also


Layer 1

Layer 1 of a decentralized ecosystem is the underlying blockchain architecture.

A proof of work blockchain known as the Common Knowledge Base (CKB) that serves as the base layer for the Nervos Network.

See Also


Layer 2

Layer 2 refers to a secondary framework or protocol that is built on top of an existing blockchain system.

The main goal of these protocols is to solve the transaction speed and scaling difficulties that are being faced by the major cryptocurrency networks.

See Also


Lina

The name of public mainnet of the Nervos CKB.

  • CKB version: >= v0.25.2 (latest stable is recommended)
  • Genesis hash: 0x92b197aa1fba0f63633922c61c92375c9c074a93e85963554f5499fe1450d0e5
  • Init command: ckb init --chain mainnet
  • Launched at: 2019-11-15 21:11:00 UTC

Synonyms

Not To Be Confused With

See Also


Live Cell

A cell that has not been consumed and is available for use.

This is similar to an unspent transaction output (UTXO) in Bitcoin.

Synonyms

See Also


Lock

A script that represents the ownership of a cell. A user successfully unlocks a cell and is able to consume it if the cell's lock script exits normally.

See Also

Lock Script

A script that enforces access and ownership of a cell. This script controls who has permission to use the cell as an input. Lock scripts accept user generated proofs or witnesses and including transaction as inputs.

See Also


Lock Script Hash

A Blake2b hash of a lock script which is used as an identifier for the script when referenced by a cell.

See Also


Mainnet

Short for "main network", the running Nervos CKB public blockchain. The name of the Nervos CKB Mainnet is Lina.

Synonyms

Not To Be Confused With


max_block_bytes

The maximum transaction size limit allowed in a block in bytes. Estimated based on the size consumed by 1000 2-in-2-out secp256k1 transactions.

pub const MAX_BLOCK_BYTES: u64 = TWO_IN_TWO_OUT_BYTES * TWO_IN_TWO_OUT_COUNT;

max_block_cycles

The maximum transaction cycle limit allowed in a block. Estimated based on the cycles consumed by 1000 2-in-2-out secp256k1 transactions.

/// cycles of a typical two-in-two-out tx.
pub const TWO_IN_TWO_OUT_CYCLES: Cycle = 3_500_000;

/// count of two-in-two-out txs a block should capable to package.
const TWO_IN_TWO_OUT_COUNT: u64 = 1_000;
pub(crate) const MAX_BLOCK_CYCLES: u64 = TWO_IN_TWO_OUT_CYCLES * TWO_IN_TWO_OUT_COUNT;

See Also


max_block_proposals_limit

The maximum amount of proposals contained in one block. The default value starts from 1.5.

TWO_IN_TWO_OUT_COUNT
pub const MAX_BLOCK_PROPOSALS_LIMIT: u64 = 1_500;

See Also


max_uncles_num

The maximum number (Uint64) of uncle blocks allowed for one block. Set as 2 by default.

const MAX_UNCLE_NUM: usize = 2;

See Also


median_time_block_count

A timestamp is valid only when it is greater than the median timestamp of the previous 37 blocks.

const MEDIAN_TIME_BLOCK_COUNT: usize = 37;

Minting

The process of creating of new tokens.

See Also


Molecule

A serialization framework for encoding data widely used on the Nervos Network.

See Also


Muta

A highly customizable, high-performance blockchain framework designed to support proof of stake, BFT consensus and smart contracts.

See Also


Nervos CKB

The layer 1 blockchain of the Nervos Network, the Common Knowledge Base.

Nervos CKB is often referred to as the Nervos Blockchain.

Synonyms

See Also


Off-Chain Computation

A programming model where all computation is done off-chain to reduce the burden on the nodes in the network and provide higher levels of scalability. Nervos uses off-chain computation and on-chain verification.

See Also


Off-Chain Scaling

Off-chain scaling is the approach that only using the blockchain as a secure asset and settlement platform in conjunction with transferring almost all transactions off the blockchain.

See Also


Off-Chain State

The data of an application that is not stored on the blockchain, or is not accessible by on-chain smart contracts.

See Also


On-Chain Computation

A programming model where all computation by smart contracts is done on-chain by every node on the network simultaneously.

Ethereum uses on-chain computation.

See Also


On-Chain Scaling

On-chain scaling solution refer to extending the throughput of the consensus process, or increasing network throughput as node number increases.

See Also


On-Chain State

The data of an application that is stored on the blockchain and is accessible by on-chain smart contracts.

Nervos provides on-chain state for all smart contracts.

See Also


On-Chain Verification

A programming model where all computation is done off-chain to reduce the burden on the nodes in the network, but verification of the resulting data is done on-chain to enforce the smart contract rules created by the developer.

Nervos uses off-chain computation and on-chain verification.

See Also


Open Transaction

A signed piece of a transaction that is incomplete and invalid on its own. When combined with other signed transaction pieces can form a complete transaction which can be processed.

One use of open transactions is to create the functionality required for a trustless decentalized exchange.

See Also


Optimistic Rollup

A rollup of transactions that use fraud proofs to offer increased layer 2 transaction throughput while using the security and data availability provided by layer 1.

See Also


Orphan

A shorthand name for Orphan Block.

Synonyms


Orphan Block

An orphan block is a valid block that is not included in the main fork due to, for example, a lag within the network itself. There can be two miners who solve a block simultaneously in NC-Max. They are non-main-chain blocks, also known as stale blocks.

In Nervos, orphan blocks are better described as Uncles.

Synonyms

See Also


Orphan Rate

A measure of the speed at which Orphan blocks occur within the blockchain network.

See Also


orphan_rate_target

The estimated orphan block rate specified in NC-max. Set as 2.5% in CKB.

// o_ideal = 1/40 = 2.5%
pub(crate) const DEFAULT_ORPHAN_RATE_TARGET: (u32, u32) = (1, 40);

See Also


Orphan Transactions

Orphan transactions are those whose parental transactions are missing at the time that they are processed. These transactions are not propagated to other nodes until all of their missing parents are received, and they thus end up languishing in a local buffer until evicted or their parents are found.

See Also


Outbound Connection

Also knowns as "outgoing connection".

A TCP connection is outgoing for the node if it was initiated (sent the TCP SYN packet) by the node in the context.

See Also


Outpoint

A particular output Cell in a transaction.

See Also


Output

A live cell that is created in a transaction.

See Also


Overlord

A byzantine fault tollerant consensus algorithm designed by Nervos for Huobi which can support thousands of transactions per second.

See Also


P2WSH

A Pay-to-Witness-Script-Hash (P2WSH) is a type of Bitcoin transaction similar to a P2SH transaction in most ways, except that it uses SegWit.


permanent_difficulty_in_dummy

Keeps the difficulty permanent if PoW is dummy when dev-chain disables NC-MAX difficulty adjustment. As boolean, it can be enabled through configuration.

See Also


Polyjuice

Polyjuice provides an Ethereum compatible runtime on Godwoken.

See Also


primary_epoch_reward_halving_interval

The halving cycle of epoch reward in CKB base issuance, typically every four years. The mining reward halves when the halving interval occurs.

pub(crate) const DEFAULT_PRIMARY_EPOCH_REWARD_HALVING_INTERVAL: EpochNumber =
4 * 365 * 24 * 60 * 60 / DEFAULT_EPOCH_DURATION_TARGET; // every 4 years

See Also


Proposal Zone

Section of the block that contains transaction proposals.

See Also


Propose

The process of taking an unconfirmed transaction out of the mempool and proposing it for commitment. A transaction is not confirmed until after it has been committed.

Miners are incentivized to propose transactions by being paid a proposal reward.

See Also


proposer_reward_ratio

The reward ratio from transaction fees for miners who submit proposals specified by NC-Max. It is set as 40% in CKB, meaning the miner who first submits the transaction proposal will be rewarded with 40% of the transaction fee.

const PROPOSER_REWARD_RATIO: Ratio = Ratio::new(4, 10);

See Also


RISC-V

An open standard instruction set architecture (ISA) for general computing.

RISC-V is the instruction set used by the CKB-VM.

See Also


Schnorr Signature

A cryptographic signature scheme for signing and verification.

See Also


Script

A program that executes on the CKB-VM. A Script can be one of two types:

  • Lock Script - Used to control ownership and access to a Cell.
  • Type Script - Used to control how a Cell is used in a transaction.

A script is a binary executable in the ELF format for the RISC-V architecture, a program that runs on the CKB-VM.

See Also


secondary_epoch_reward

The secondary reward per epoch. Issued according to CKB’s tokenomics detailed in RFC0015.

Secondary issuance is designed to collect state rent, and has an issuance amount that is constant over time. After base issuance stops, there will only be secondary issuance.

Secondary issuance has two parts. One is a fixed amount of base incentive (approximately 134.4 million CKBytes per year), while the other varies according to the number of CKBytes currently occupied.

pub(crate) const DEFAULT_SECONDARY_EPOCH_REWARD: Capacity = Capacity::shannons(613_698_63013698);

See also


secp256k1_blake160_sighash_all_type_hash

Type hash of secp256k1_blake160_sighash_all in CKB genesis scripts.

Find more details here.


secp256k1_blake160_multisig_all_type_hash

Type hash of secp256k1_blake160_multisig_all in CKB genesis scripts.

Find more details here.


Seed Cell

A design pattern on Nervos from creating unique identifiers used to create unforgeable assets.

See Also


Shannon

A fractional denomination of CKBytes. One CKByte is equal to 100,000,000 Shannons.

A Shannon is the equivalent of a Bitcoin Satoshi.

See Also


Short Address

An address format on Nervos that does not include a code hash of the associated lock script, instead using one of the many common lock scripts.

The short address format is the most common address format used, and is often referred to as simply "address".

Synonyms

See Also


Simple UDT

A standard that defines a the most basic implementation of a UDT fungible token on Nervos.

An SUDT on Nervos is the equivalent of Ethereum tokens standards ERC20 or ERC777.

Synonyms

See Also


Since

since is the u64 (unsigned 64-bit integer) field in transaction input for preventing inclusion before a certain block timestamp or a block number.

See Also


SPV

An abbreviation for Simplified Payment Verification. A protocol for using a blockchain cryptocurrency without having to operate a full node.

SPV clients require far less data to be stored, but also must requires the trust of the network clients it is connected to directly.

See Also


SPV Wallet

A light-weight cryptocurrency wallet that uses the SPV protocol.

See Also


SUDT

An abbreviation for Simple UDT.

Synonyms


Testnet

Short for “test network,” a network used to simulate the behavior of the Mainnet. The name of the Nervos CKB Testnet is Aggron.

Synonyms

Not To Be Confused With


Transaction Confirmation Number

The number of confirmations required for a transaction to be added to a block.

As permissionless blockchain designs offer only probabilistic finality, a transaction can never be fully confirmed, facing an adversary with infinite computational power. Therefore, users and apps can choose a number they deem secure. We briefly discuss one factor here that influences the level of security: the recent orphan rate. It takes 6 confirmations to fully settle a transaction when the orphan rate is 0, and 24 confirmations when the rate reaches 2.5% to achieve the same level of security (See the rationale and calculation here).

In blockchain settlement assurance, transaction confirmation is one of the variables that cannot be easily quantified (See Nic Carter’s article). The exact number is open to adjustment depending on the security level that users desire. Nervos CKB sets a minimum of 15 confirmations, which should be considered conservative.

See Also


Transaction Hash

Transaction hash, or Txhash, is the unique identifier of a transaction in a blockchain that acts as a record or proof that the transaction has taken place. To get a transaction hash in CKB, the transaction is serialized via Molecule, then the serialized raw is feed to ckbhash function. Its schema is:

table Transaction {
raw: RawTransaction,
witnesses: BytesVec,
}

Transaction hash is generated by the serialized raw structure through ckbhash.

See Also


Transaction Witness Hash

Transaction witness hash is generated by the serialized transaction through ckbhash. Transaction is serialized via molecule in CKB. Its schema is:

table Transaction {
raw: RawTransaction,
witnesses: BytesVec,
}

See Also


Transaction Root

The field transactions_root in header is

ckbhash(T || W)

ckbhash is the hash function, || denotes binary concatenation.

T is the root of a CKB Merkle Tree, which items are the transaction hashes of all the transactions in the block.

W is also the root of a CKB Merkle Tree, but the items are the Transaction Witness Hash of all the transactions in the block.

See Also


tx_proposal_window

Interval for submitting proposals in the second stage specified by NC-Max. Set between 2 and 10 blocks in CKB.

As shown above, when a transaction is first proposed in Block 13, it can be committed in the window between Block 15 and Block 23.

pub(crate) const TX_PROPOSAL_WINDOW: ProposalWindow = ProposalWindow(2, 10);

tx_version

The version of a transaction. This field is set to 0 and is reserved for the system.

pub const TX_VERSION: Version = 0;

type_id

One of the CKB system_scripts. A unique feature of Type ID is that it‘s a CKB built-in script directly implemented in Rust. It doesn't run in CKB-VM but can be used in the same way as other CKB genesis scripts.

For a deeper understanding of Type ID, check out this blog post: Introduction to CKB Script Programming 6: Type ID (also translated into Chinese).

See Also


type_id_code_hash

The code_hash of type_id. In view of the specificity of type_id, type_id_code_hash is hard-coded, not the hash of the actual code.

See Also


Type Script

A script that enforces the rules that must be followed in a transaction for a cell to be consumed as an input or for a cell to be created as an output.

See Also


Type Script Hash

Or type_hash, a Blake2b hash of a Type Script which is used as an identifier for the Script when referenced by a Cell.

The two entities in the data structure of CKB’s cell are lock and type. Type scripts can capture any validation logic needed in the cell transformation.

Type scripts can implement economic constructs as well. NervosDAO is completely implemented as a type script with minimal support from the consensus layer.

See Also


Uncle

Or Uncle Block. Uncle blocks are created when two blocks are mined and submitted to the ledger at roughly the same time. Only one can enter the ledger as an included block, and the other does not.

Uncles are paid a reduced block reward when they are found and reported.

On Nervos, Uncles are tracked by consensus to adjust the block interval of the network.

An uncle block has to meet the following conditions:

  • An uncle should not be on the main chain; in other words, it should not be an uncle if it includes any block from the main chain.
  • Uncle’s block number must be smaller than the block‘s number that later includes it.
  • Uncle‘s parent must be on the main chain, or uncle’s parent must also be an uncle. In other words, uncle must be linkable to the main chain in any way. It can never be a random block that is not on the main chain.
- if !snapshot.is_main_chain(&uncle.hash()) // It should not be on the main chain.
- && !snapshot.is_uncle(&uncle.hash()) // It should not be an uncle twice.
- && uncle.number() < candidate_number // The block number of the uncle should be smaller than that of any block on the main chain.
- && (uncles.iter().any(|u| u.hash() == parent_hash)
|| snapshot.is_main_chain(&parent_hash) // Uncle block should not be parentless. The parent of un uncle must be a block on the main chain or another uncle.
|| snapshot.is_uncle(&parent_hash))

As illustrated above, A is the main chain. B3 can be the uncle of A4 (to be included in A4), since B3 is linked to A2. However, B4 cannot be included in A4, since the uncle’s block number must be smaller than A4, the current block on the main chain.

Similarly, B4 can be the uncle of A5 (be included by A5). Although B4‘s parent, B3, is not on the main chain, B3 is the uncle of A4. For this reason, B4 is a legal uncle, and B3 cannot be included by A5.

C2 and C3 cannot be linked to the main chain as their parent is unknown, therefore, they cannot be uncles.

See Also

Synonyms

See Also


Uncle Rate

See Also


Validator

A script that is used to ensure that the transactions created by the generators are valid. Validators are scripts that run in CKB-VM as either lock scripts or type scripts.

See Also


Witness

A set of cryptographic proof containing the data required to prove authorization of the resources used in the transaction.

See Also


Zk-SNARK

A form of cryptographic proof, that when used in cryptocurrencies, allows for privacy features which do not reveal the amounts or participants in transactions.

Zk-SNARKs require a trusted setup, but are otherwise trustless.

See Also


Zk-STARK

A form of cryptographic proof, that when used in cryptocurrencies, allows for privacy features which do not reveal the amounts or participants in transactions.

Unlike Zk-SNARKs, Zk-STARKs do not require a trusted setup.

See Also


+ \ No newline at end of file diff --git a/docs/basics/guides/ckb-on-windows/index.html b/docs/basics/guides/ckb-on-windows/index.html index b591d0d26..72fff3a07 100644 --- a/docs/basics/guides/ckb-on-windows/index.html +++ b/docs/basics/guides/ckb-on-windows/index.html @@ -14,7 +14,7 @@ Get CKB Binary on Windows | Nervos CKB - + @@ -22,7 +22,7 @@

Get CKB Binary on Windows

Please note that, All commands listed below should be used through PowerShell.

Build from Source

Setup the Build Environment

Install Visual Studio 2019

Install Visual Studio 2019 with the workload: "Desktop development with C++".

minimum requirements: You can just select two individual components: "MSVC v142 - VS 2019 C++ x64/x86 build tools (vXX.XX)" and "Windows 10 SDK (10.0.X.0)".

Install Tools with Scoop

  • Install Scoop.

  • Install git, llvm, yasm and rustup via Scoop.

    scoop install git
    scoop install llvm
    scoop install yasm
    scoop install rustup
  • Install dependencies.

    • Add "extras" bucket for Scoop.

      scoop bucket add extras
    • yasm requires Microsoft Visual C++ 2010 runtime Libraries.

      scoop install vcredist2010
  • Configure Rust.

    rustup set default-host x86_64-pc-windows-msvc

Build CKB on Windows 10

  • Checkout the source code of CKB.

    git clone https://github.com/nervosnetwork/ckb
    cd ckb
  • Build CKB.

    devtools/windows/make prod

Download from Releases

We publish binaries for each release via Github Releases. You can download the package directly. They requires The Visual C++ Redistributable Packages, which can be downloaded under section Other Tools and Frameworks here or here.

- + \ No newline at end of file diff --git a/docs/basics/guides/crypto wallets/bitpie/index.html b/docs/basics/guides/crypto wallets/bitpie/index.html index 891e27f03..df09c908b 100644 --- a/docs/basics/guides/crypto wallets/bitpie/index.html +++ b/docs/basics/guides/crypto wallets/bitpie/index.html @@ -14,13 +14,13 @@ Bitpie | Nervos CKB - +

Bitpie

Set Up a CKB Wallet

To set up a CKB wallet:

  1. Download Bitpie from iOS or Android App Store.

  2. Open Bitpie, and click Create Wallet.

  3. Click Noticed, start to backup to back up the seed phrase.

    Note: Do not reveal the seed phrase or take a picture of it. Keep the seed phrase offline.

  4. Click I know it on the pop-up window to confirm NOT to reveal the seed phrase to anyone.

  5. Write down the phrase.

  6. Click Backup Finished and go to verify.

  7. Enter the 12 words seed phrase.

  8. Click OK.

  9. Enter a pin code.

  10. Confirm the PIN code and click OK.

  11. Choose CKB from the selection list to add CKB asset.

  12. Choose CKB on the Choose Wallet System page.

- + \ No newline at end of file diff --git a/docs/basics/guides/crypto wallets/imtoken/index.html b/docs/basics/guides/crypto wallets/imtoken/index.html index ef947e166..d8f53f4e0 100644 --- a/docs/basics/guides/crypto wallets/imtoken/index.html +++ b/docs/basics/guides/crypto wallets/imtoken/index.html @@ -14,13 +14,13 @@ imToken & imKey | Nervos CKB - +

imToken & imKey

imToken

imToken is a mobile wallet that supports encrypted assets on multiple chains.

  1. Download and install imToken.

  2. Open imToken, click Create Identity and confirm Terms of Service.

  3. Enter the identity name and the password to create an account.

  4. Click Confirm to add the default coins (ETH, BTC, and ATOM) or choose other coins, such as CKB.

  5. Click Backup Wallet under Manage your identity wallet to back up the mnemonic phrase.

    Note: Never give the phrase away; otherwise, your coins will be at risk.

    The mnemonic phrase consists of 12 random words. Write them down in a safe place by order. These mnemonic words are required when restoring the wallet. Once the words have been written down, select Confirmed Backup.

  6. Confirm the phrase has been well noted. Choose the word in the correct order, and click Next. Now the wallet has been successfully configured.

Transfer CKB

To transfer CKB:

  1. Click CKB to enter the CKB Wallet.

  2. Click the CKB balance that is visible under the Assets section.

  3. Click Send to transfer CKB.

  4. Fill in the address of the recipient and the desired transfer amount.

  5. Enter the wallet password, then the payment details will be shown.

  6. Once the payment is confirmed, the transaction will be broadcast to the network. Click on Query Details to see the on-chain confirmation status of the transaction. The on-chain information can be found on the Nervos Explorer.

  7. It takes 24 blocks for a transaction to be confirmed.

Receive CKB

To receive CKB:

  1. Click CKB to enter the CKB Wallet.

  2. Click the CKB balance that is visible under the Assets section.

  3. Click Receive.

  4. The QR code and wallet address will appear on the Receive page. If both parties are using imToken, simply show the QR code to the sender to receive payment.

A Word to Note

As the unique Cell model of CKB, there are several things to be aware of for CKB transfers. CKB has a minimum transfer amount of 61 CKBs, which means that the transfer amount cannot be less than 61 CKBs excluding the fee or miner fee.

There is no problem transferring all CKBs from the account. In the case of a partial transfer of CKB, if the account balance is less than 61 CKBs, it is impossible to make any future transfers. If the balance is equal to 61, transfers will also be impossible. For an account balance less than 61, the wallet will indicate that the transfer does not meet the required amount or will directly report an error when transferring. Due to the minimum transfer amount requirement, ensure that the account balance is at least 62 CKBs so that the full amount can be transferred the next time.

imKey

imKey is a hardware wallet, or cold wallet. The imKey is used to protect privkeys and other confidential data of the user. imKey is integrated with the CC EAL 6+ security chip, fully compatible with all imToken 2.0 supported digital assets such as BTC, ETH, COSMOS and EROS. For more details and usage processes, see imkey support.

Troubleshooting

Network connection issue is a common cause for data sync failure, such as the problem that withdrawn asset is unreceived in imToken.

Try the following process to solve the problem:

  1. Upgrade imToken to the latest version.
  2. Set up a VPN on the phone.
  3. If it still doesn't work out, go to My Profile -> Settings -> Network Detection to check the network connection. Copy the detected information and send it to the imToken support team.
- + \ No newline at end of file diff --git a/docs/basics/guides/crypto wallets/neuron/index.html b/docs/basics/guides/crypto wallets/neuron/index.html index 1bc49438e..a806eb66b 100644 --- a/docs/basics/guides/crypto wallets/neuron/index.html +++ b/docs/basics/guides/crypto wallets/neuron/index.html @@ -14,14 +14,14 @@ Neuron Wallet | Nervos CKB - +

Neuron Wallet

Neuron Wallet is a CKB wallet produced by Nervos Foundation. The wallet holds keys and is capable of creating and broadcasting transactions.

Neuron Wallet is bundled with a CKB Mainnet node and configured to connect to the CKB Mainnet. The bundled Mainnet node runs automatically when a Neuron wallet is set up and launched.

Install Neuron Wallet

Download and install the latest version of Neuron Wallet from the Neuron Wallet releases page on Github.

Note: For Windows versions before Windows 10, the latest Microsoft Visual C++ Redistributable for Visual Studio 2015, 2017 and 2019 must be installed before installing Neuron Wallet.

Set Up a Neuron Wallet

Here are three options to set up a Neuron wallet.

  • Create a new Neuron wallet.

  • Import a wallet seed of a backed up wallet.

  • Import a keystore file of a backed up wallet.

Create a New Neuron Wallet

To create a new wallet, select Create a New Wallet.

A new wallet seed consisting of 12 mnemonic words is generated.

Note: Screenshots and copies of the mnemonic words may be read by third parties. Hand-copying is recommended for keeping the mnemonic words.

Import a Wallet Seed of a Backed Up Wallet

To import a mnemonic seed:

  1. Select Import Wallet Seed.
  2. Enter the password and wait for the sync to complete.

Import a Keystore File of a Backed Up Wallet

To import a keystore file:

  1. Select Import from Keystore.
  2. Enter the password, then wait for the sync to complete.

Await the Sync to Complete

The Block Number can be cross-checked with the Latest Block on the CKB Explorer page to ensure that the sync is completed.

After the Neuron wallet is synced, full access to the tokens of the wallet is available. Sending, receiving CKBs, and depositing CKBs to Nervos DAO is possible.

Transfer CKB from Neuron Wallet to Other Wallets or Exchanges

Note: The wallet must have a minimum of 61 CKBs for a transfer operation.

To transfer CKB:

  1. Fill in the Send to field with the address of the third party wallet or exchange on the Send page.

  2. Use the default fee settings or change the fee settings in Advanced fee settings.

  3. Click the Send button.

  4. Input the password and click Confirm to complete the transfer.

Deposit CKB into Nervos DAO

Note: The wallet must have a minimum of 102 CKBs for a Nervos DAO deposit operation.

The economic model of Nervos CKB is designed to allow token holders to lock their tokens in Nervos DAO to mitigate the inflationary effect of the secondary issuance. In this case, the inflationary effect of the secondary issuance is expected to be nominal and equivalent to holding tokens with a hard cap.

To deposit CKB into Nervos DAO:

  1. Select the Nervos DAO tab, then click Deposit.

  2. Input the amount of CKB tokens for the deposit and then click Proceed.

  3. Input the password and click Confirm to submit the deposit transaction.

Withdraw CKB from Nervos DAO

Note: The wallet must have a minimum of 61 CKBs for a Nervos DAO withdrawal operation.

To withdraw CKB from Nervos DAO:

  1. Choose the deposit that you want to withdraw from the deposits list and click Withdraw.

  2. Click Proceed on the pop-up window to complete the withdrawal operation.

Claim Vested or Locked Tokens

Vested or locked tokens can be claimed by using the latest version of Neuron Wallet. When a Neuron wallet is fully synced, the vested or locked assets are visible on the Custom Assets page.

After the customized assets are claimed, they can be transferred or deposited to Nervos DAO.

To claim vested or locked tokens:

  1. View details of Customized Assets.

  2. Click Claim when the lock time is expired, and enter the password for the wallet.

Manage Asset Account

Asset Account is used for managing the accounts including anyone-can-pay (RFC: Anyone-Can-Pay Lock) cells and sUDTs (RFC: Simple UDT). It's recommended to use ckb-udt-cli to issue or transfer UDTs. For more information, see the GitHub repository of ckb-udt-cli.

Note: The feature is experimental and only can be used on Testnet Aggron now.

Manage SUDT Accounts

Preparation

  1. Run a CKB Testnet node. For more information, see Run a CKB Testnet Node.

  2. Create a new account and export the privkey by using ckb-cli.

    ckb-cli account new
    Click here to view response

    Your new account is locked with a password. Please give a password. Do not forget this password.
    Password:
    Repeat password:
    address:
    mainnet: ckb1qyqwuea9tpxr2equ75rskyn30r3wjans7fnq477mmm
    testnet: ckt1qyqwuea9tpxr2equ75rskyn30r3wjans7fnqgmqyh8
    lock_arg: 0xee67a5584c35641cf5070b127178e2e97670f266
    lock_hash: 0x8b2595bb1c4720951a5363fbf0adb0ab1e2ff5acd7391f123837242712fc8490

    ckb-cli account export --extended-privkey-path wallet --lock-arg `Your lock_arg`
    Click here to view response

    ./ckb-cli account export --extended-privkey-path wallet --lock-arg 0xee67a5584c35641cf5070b127178e2e97670f266
    Password:
    Success exported account as extended privkey to: "wallet", please use this file carefully

    cat wallet

    The first line of the result is the exported private key.

    Click here to view response

    0a348a7cd1449ece26f1cede3916266793ce18beb280b75dda690057ebfcda3c  // It is the privkey
    c152037977043a11e7e6ef220ba050da12da16455a0ef303907865a15fa9c484

  3. Issue UDTs by using ckb-udt-cli.

    To issue UDTs:

    1. Clone and build ckb-udt-cli.

      git clone https://github.com/ququzone/ckb-udt-cli.gitcd ckb-udt-cliexport GOPROXY=https://goproxy.iogo mod downloadgo build .
    2. Claim CKBs on Testnet by using Nervos Aggron Faucet.

    3. Issue UDTs and back up the uuid.

      ckb-udt-cli issue -c config.yaml -k YOUR_PRIVATE_KEY -a AMOUNT // AMOUNT means the number of issued tokens
      Click here to view response

      ./ckb-udt-cli issue -c config.yaml -k 0a348a7cd1449ece26f1cede3916266793ce18beb280b75dda690057ebfcda3c -a 1000000
      Issued sUDT transaction hash: 0x6b4458143b25e8aa37d36c1035f15e63e5051144685a4da20cf92fd7af59e56e, uuid: 0x8b2595bb1c4720951a5363fbf0adb0ab1e2ff5acd7391f123837242712fc8490

Add an SUDT Account to Asset Accounts

To add the SUDT account into Asset Accounts:

  1. Open the Asset Account page in Neuron Wallet, and click the + button to create an asset account.

  2. Fill the uuid in the Token ID field.

  3. Fill in the other required fields and click Confirm.

  4. Await until the transaction is successful.

Manage CKB Accounts

CKB accounts can be used for anyone-can-pay cells and support any amount of payment.

  1. Create two CKB accounts, Anyone-can-pay1 and Anyone-can-pay2. The following figures show the steps of creating Anyone-can-pay1. The steps of creating Anyone-can-pay2 are the same as creating Anyone-can-pay1.

  2. Fill the address of Anyone-can-pay1 in Nervos Testnet Faucet to claim CKBs on Testnet for Anyone-can-pay1.

  3. Transfer 1 CKB from Anyone-can-pay1 to Anyone-can-pay2.

    1. Click Send on the Anyone-can-pay1 card.

    2. Fill the address of Anyone-can-pay2 and other required input on the Send page.

    3. Click Submit.

    4. Check the balance on the Anyone-can-pay2 card.

Sync Failure Troubleshooting

There are several causes that lead to Neuron Wallet sync errors. Here is a step-by-step troubleshooting guide to help you resolve the issue.

General Troubleshooting Process

First, check if ckb and ckb-indexer are running.

  • Windows: Open Task Manager

  • MacOS: Open Activity Monitor

If ckb and ckb-indexer are both down, to restart, add a network in setting -> network -> add network with rpc url: [http://localhost:8114](http://localhost:8114) and name: mainnet. Switch to the mainnet. Neuron will reconnect to the running CKB node.

If the above doesn't work, we need more information to locate the problem. Get the info by menu -> help -> export debug info and export the files below:

bundled-ckb.log        # ckb log file
hd_public_key_info.csv # generated address index with its transaction count
main.log # log of Neuron's main process
renderer.log # log of Neuron's renderer process
status.json # general info including neuron's version, ckb's version.

Open bundled-ckb.log and scroll down to the bottom. The error (if exists) is usually displayed there. Listed below are four potential cases:

  • If you see text like  Neuron\chains\mainnet\data\db\LOCK or Neuron/chains/mainnet/data/db/LOCK It's a problem with the database lock. Remove the .../LOCK file.
    • Remove the entire directory by selecting tools -> clear all synchronized data, but it leads to a new sync from scratch.

Windows:

MacOS:

  • If you see text like main INFO main ckb version:, check if the version is up to date; If not, remove chain data and restart the synchronization by tools -> clear all synchronized data

  • If you see text like thread 'main' panicked at 'Internal(DataCorrupted(failed to load the options file: IO error: No such file or directory or EINVAL: invalid argument, follow this issue to check if your username of PC has non-UTF8 characters.

  • If you see text like error while loading shared libraries: libssl.so.1.1: cannot open shared object file, follow this issue to check if it's caused by the incompatibility of OpenSSL.

Non UTF-8 Characters In Username

If an exception like this occurs, make sure that your username in file path \Users\{username}\AppData\Roaming\Neuron\... is inside the UTF-8 charset. usename outside of UTF-8 is not allowed, which leads to the failure of running ckb node in Neuron Wallet.

Please follow these steps to check if it's caused by the non-UTF8 issue.

Once confirmed, the simplest way to run Neuron is to create a new account with UTF-8 characters.

Report Your Issue

If you’ve followed the above troubleshooting guide but still cannot locate the problem, export the log and use this template to submit the issue.

- + \ No newline at end of file diff --git a/docs/basics/guides/crypto wallets/portalwallet/index.html b/docs/basics/guides/crypto wallets/portalwallet/index.html index a4e221db1..b2f90af19 100644 --- a/docs/basics/guides/crypto wallets/portalwallet/index.html +++ b/docs/basics/guides/crypto wallets/portalwallet/index.html @@ -14,13 +14,13 @@ Portal Wallet | Nervos CKB - +

Portal Wallet

Portal Wallet is a web wallet that runs directly in a browser. It is a dApp wallet that allows users to receive and send Nervos CKBs with existing Ethereum addresses and wallets.

Portal Wallet (PW) currently supports the following wallets: MetaMask, imToken, Huobi Wallet, BitKeep, Coinbase Wallet, Opera, ABC Wallet, Bitpie, TokenPocket, AlphaWallet.

The Portal wallet is a superb alternative to Neuron Wallet by allowing users to use on the mobile phone. In addition, it does not require manual sync with a Mainnet node and supports a variety of wallets. Using Portal Wallet is quite simple. The user needs to possess at least one cryptocurrency account and at least one cryptocurrency wallet in use. On the Portal Wallet, users can check the Ethereum address and CKB address, view the balance, and lock the CKB in the Nervos DAO.

Note: The wallet must have a minimum of 102 CKBs for a Nervos DAO deposit operation and 61 CKBs for a Nervos DAO withdrawal operation.

Use PW With MetaMask

To use PW with MetaMask:

  1. Open ckb.pw in a browser that has installed the MetaMask wallet extension. Type the password to log in to the MetaMask.

  2. A MetaMask connection request will automatically pop up. Choose the address desired for login.

  3. Sign the Authorised Signature, then click Connect to open the Portal Wallet in the browser.

Receive Payments

To receive payments:

  1. Choose CKB and click Receive on the home page.

  2. Two addresses will appear, ETH address and CKB address.

    The address needs to be modified depending on where to receive payments:

    • To receive funds from another Portal Wallet, click ETH address on the left.
    • To transfer from other wallets or exchanges to Portal Wallet, click CKB address on the right.

Portal Wallet currently supports multi-chain addresses, users can transfer payments to each other using CKB addresses, Ether addresses, ENS, etc., in Portal Wallet. However, other wallets/exchanges are less supported at the moment, so it is necessary to align the receiving address with where the payment is to be made.

  • Ethereum address is the current Ethereum address bundled at login that can be used to send and receive CKB assets directly in Portal Wallet.
  • CKB address: since most exchanges and CKB wallets do not yet support the transfer of CKB full address, Portal Wallet can assist with transferring assets by transferring CKB to a ckb address for the first time using.

Transfer CKB

Note: The wallet must have a minimum of 61 CKBs for a transfer operation.

  1. Click Send to access the transfer page.

    • Currently supported transfer address formats are Ethereum address, CKB address, and ENS domain address.
    • To enter the address: manually input or copy & paste, QR code scanning, common contacts.
  2. After entering the transfer address and transfer amount, Portal Wallet will automatically calculate the transfer fee.

  3. Then, click Send and sign to complete the transfer.

Set Transfer Fees

Portal Wallet has a fee-setting function that allows users to customize the fee rate for transfers based on their personal preferences. With a higher fee rate, users will have priority to package transactions.

Transfer fee for CKB = transaction size * exchange rate

The minimum fee rate on CKB is 1000 Shannon/KB (1 Shannon = 108 CKB).

Add a Transfer Note

Portal Wallet supports notes on transfers to make it easier to keep track of each transfer. When initiating a transfer, users can add notes to check the transfer later on.

- + \ No newline at end of file diff --git a/docs/basics/guides/crypto wallets/safepal/index.html b/docs/basics/guides/crypto wallets/safepal/index.html index 2c4f5c04d..cd7b1fe80 100644 --- a/docs/basics/guides/crypto wallets/safepal/index.html +++ b/docs/basics/guides/crypto wallets/safepal/index.html @@ -14,14 +14,14 @@ SafePal | Nervos CKB - +

SafePal

Download and Install

Download SafePal from iOS or Android App Store. It provides both software wallet and hardware wallet.

Hardware Wallet

To order SafePal hardware wallet online, visit https://safepal.io/.

To use SafePal hardware wallet:

  1. Use SafePal hardware wallet to scan the QRCode which will be displayed by tapping the Next button.

  2. Follow the instructions on the hardware wallet and finish pairing.

Software Wallet

Set Up a SafePal Wallet

Here are two ways to set up a SafePal wallet:

  • Create a new SafePal wallet.
  • Import an existing wallet.

Create a New SafePal Wallet

  1. Tap Create Wallet to set the wallet's name and the mnemonic phrase that can be 12 or 24 mnemonic words.

  2. Click Back up my phrase immediately after having successfully created the wallet.

  3. Follow the instructions and write the mnemonics in the given order on a piece of physical paper. Store it offline safely.

    To protect user data, SafePal disables screenshot for mnemonics setting.

Import an Existing Wallet

SafePal provides four options to Import wallet. Choose a preferred one, follow the guidance and enter the corresponding information correctly.

Once the wallet has been successfully imported, click the wallet icon in the top left to view the wallet in the Wallet list.

To add another existing wallet simply tap on the + icon.

Add CKB to Asset List

SafePal lists 5 coins by default on the Asset page.

To add CKB to Asset list:

  1. Enter CKB in the Search bar.

  2. Add CKB (Nervos) to the list.

    Note: The search results show such tokens as CKB (Godwoken), CKB(ERC20) and CKB(BEP20), all of which serve different purposes here. Do NOT add them to the asset list.

  3. Now CKB (Nervos) is successfully added. It's time to create the first transaction.

Receive CKB

Two ways to receive money:

  • By text: Tap Copy to get the CKB address in the format of a series of letters and numbers, starting with "ckb".

  • By QRCode: Tap Share to get a QRCode image.

Share either form of the address information with the sender. Once the transaction is completed and verified, the related transaction information will appear in the CKB transaction history.

Send CKB

  1. Tap Send, then fill in the address of the recipient and the desired transfer amount. Tap Next.

  2. Recheck the information to make sure the information is correct. If so, tap Send.

    Once the payment is completed, the transaction Status turns to Pending. That means the transaction has been broadcast to the network for verification.

  3. Click on More Details to see the on-chain confirmation information of the transaction.

  4. You will be redirected to Nervos Explorer where the transaction details are displayed.

    Once the transaction is verified by the entire network, an overview will be available in the CKB transaction history.

- + \ No newline at end of file diff --git a/docs/basics/guides/devchain/index.html b/docs/basics/guides/devchain/index.html index 3eaa523da..089de2b3c 100644 --- a/docs/basics/guides/devchain/index.html +++ b/docs/basics/guides/devchain/index.html @@ -14,13 +14,13 @@ Run a CKB Dev Blockchain | Nervos CKB - +
-

Run a CKB Dev Blockchain

Nervos CKB supports a special development mode that is particularly useful for building and testing applications. This mode of operation is highly configurable, and allows the developer to speed up the block interval, adjust epochs lengths, create blocks without having to do Proof-of-Work (PoW) mining.

When running a development blockchain you have the option of selecting between Dummy-Worker and Eaglesong-Worker. Dummy-Worker allows the mining of blocks at a constant block interval without PoW. Eaglesong-Worker uses real PoW to produce blocks.

Note: It is highly recommended that Dummy-Worker be used for most development scenarios. Eaglesong-Worker should only be used when validating the PoW function is necessary, because the block time can behave erratically with extremely low hashrates.

Setup a Dummy-Worker Blockchain

1. Download the Latest CKB Binary

Download the latest ckb binary file from the CKB releases page on GitHub.

The following commands can be used to verify the binaries are working and to check versions:

ckb --version
ckb-cli --version
(click here to view result)
ckb 0.32.1 (9ebc9ce 2020-05-29)
ckb-cli 0.32.0 (0fc435d 2020-05-22)

2. Initialize the Configuration

Use the following command to initialize the development blockchain and generate the required configuration files:

ckb init --chain dev
(click here to view result)
WARN: mining feature is disabled because of lacking the block assembler config options
Initialized CKB directory in /PATH/ckb_v0.32.1_x86_64-apple-darwin
create specs/dev.toml
create ckb.toml
create ckb-miner.toml

3. Configure the Block Assembler

The Block Assembler configuration specifies which address should be receive block rewards for mining.

3a. Create a New Account

An address to receive the block rewards must be created. We can do this using ckb-cli.

Note: Be sure to record the lock_arg value in the response which we will use in the next step.

ckb-cli account new
(click here to view result)
Your new account is locked with a password. Please give a password. Do not forget this password.
Password:
Repeat password:
address:
mainnet: ckb1qyqyrm8w0w8uq7puwhdp7s6xqzdjuknhf2tqzdztph
testnet: ckt1qyqyrm8w0w8uq7puwhdp7s6xqzdjuknhf2tqlgu5dt
lock_arg: 0x41ecee7b8fc0783c75da1f4346009b2e5a774a96
lock_hash: 0xeb31c5232b322905b9d52350c0d0cf55987f676d86704146ce67d92ddef05ed3

3b. Update the Configuration

Modify the args and message parameters in the ckb.toml file under the block_assembler section:

[block_assembler]
code_hash = "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8" # Do not change this.
args = "0x8d627decece439977a3a0a97815b63debaff2874" # Change this to your lock_arg value.
hash_type = "type" # Do not change this.
message = "A 0x-prefixed hex string" # Change this to "0x" to supply an empty message.

4. Adjust the Parameters to Shorten the Block Interval (Optional)

For most development the default configuration should be sufficient, but sometimes it is beneficial to speed up certain operations so results can be viewed quickly.

4a. Change the Number of Blocks in an Epoch

The default epoch length is 1000 blocks. Reducing this to 10 or 100 can help with testin Nervos DAO operations.

Modify the genesis_epoch_length parameter in the specs/dev.toml file under the params section:

[params]
genesis_epoch_length = 1000 # The unit of meansurement is "block".

4b. Use Permanent Difficulty

When permanent_difficulty_in_dummy is set to true, all epochs will use the same length as the genesis epoch length, skipping the difficulty adjustment entirely. This param is typically used in conjunction with genesis_epoch_length.

Modify the permanent_difficulty_in_dummy parameter in the specs/dev.toml file under the params section:

[params]
genesis_epoch_length = 10
permanent_difficulty_in_dummy = true

4c. Change the Mining Interval

The default mining interval is 5000, which is a value in milliseconds, meaning 5 seconds. Reducing this value will create blocks faster.

Modify the value parameter in the ckb-miner.toml file under the miner.workers section:

[[miner.workers]]
worker_type = "Dummy"
delay_type = "Constant"
value = 5000 # The unit of measurement is "ms".

5. Start the CKB Node

ckb run
(click here to view result)
2020-06-05 18:31:14.970 +08:00 main INFO sentry  sentry is disabled
2020-06-05 18:31:15.058 +08:00 main INFO ckb-db Initialize a new database
2020-06-05 18:31:15.136 +08:00 main INFO ckb-db Init database version 20191127135521
2020-06-05 18:31:15.162 +08:00 main INFO ckb-memory-tracker track current process: unsupported
2020-06-05 18:31:15.164 +08:00 main INFO main ckb version: 0.32.1 (9ebc9ce 2020-05-29)
2020-06-05 18:31:15.164 +08:00 main INFO main chain genesis hash: 0x823b2ff5785b12da8b1363cac9a5cbe566d8b715a4311441b119c39a0367488c
2020-06-05 18:31:15.166 +08:00 main INFO ckb-network Generate random key
2020-06-05 18:31:15.166 +08:00 main INFO ckb-network write random secret key to "/PATH/ckb_v0.32.1_x86_64-apple-darwin/data/network/secret_key"
2020-06-05 18:31:15.177 +08:00 NetworkRuntime INFO ckb-network p2p service event: ListenStarted { address: "/ip4/0.0.0.0/tcp/8115" }
2020-06-05 18:31:15.179 +08:00 NetworkRuntime INFO ckb-network Listen on address: /ip4/0.0.0.0/tcp/8115/p2p/QmSHk4EucevEuX76Q44hEdYpRxr3gyDmbKtnMQ4kxGaJ6m
2020-06-05 18:31:15.185 +08:00 main INFO ckb-db Initialize a new database
2020-06-05 18:31:15.211 +08:00 main INFO ckb-db Init database version 20191201091330
2020-06-05 18:31:26.586 +08:00 ChainService INFO ckb-chain block: 1, hash: 0x47995f78e95202d2c85ce11bce2ee16d131a57d871f7d93cd4c90ad2a8220bd1, epoch: 0(1/1000), total_diff: 0x200, txs: 1

6. Start the CKB Miner

This should be performed in a separate terminal.

ckb miner
(click here to view result)
2020-06-05 18:31:21.558 +08:00 main INFO sentry  sentry is disabled
Dummy-Worker ⠁ [00:00:00]
Found! #1 0x47995f78e95202d2c85ce11bce2ee16d131a57d871f7d93cd4c90ad2a8220bd1
Found! #2 0x19978085abfa6204471d42bfb279eac0c20e3b81745b48c4dcaea85643e301f9
Found! #3 0x625b230f84cb92bcd9cb0bf76d1397c1d948ab25c19df3c4edc246a765f94427
Found! #4 0x4550fb3b62d9d5ba4d3926db6704b25b90438cfb67037d253ceceb2d86ffdbf7

Setup an Eaglesong-Worker Blockchain

1. Download the Latest CKB Binary

Download the latest ckb binary file from the CKB releases page on GitHub.

The following commands can be used to verify the binaries are working and to check versions:

ckb --version
ckb-cli --version
(click here to view result)
ckb 0.32.1 (9ebc9ce 2020-05-29)
ckb-cli 0.32.0 (0fc435d 2020-05-22)

2. Create a New Account

An address to receive the block rewards must be created. We can do this using ckb-cli.

Note: Be sure to record the lock_arg value in the response which we will use in the next step.

ckb-cli account new
(click here to view result)
Your new account is locked with a password. Please give a password. Do not forget this password.
Password:
Repeat password:
address:
mainnet: ckb1qyqyrm8w0w8uq7puwhdp7s6xqzdjuknhf2tqzdztph
testnet: ckt1qyqyrm8w0w8uq7puwhdp7s6xqzdjuknhf2tqlgu5dt
lock_arg: 0x41ecee7b8fc0783c75da1f4346009b2e5a774a96
lock_hash: 0xeb31c5232b322905b9d52350c0d0cf55987f676d86704146ce67d92ddef05ed3

3. Initialize the Configuration with the Miner Account

ckb init -c dev --ba-arg 0x41ecee7b8fc0783c75da1f4346009b2e5a774a96 // Change this to your lock_arg value. 
(click here to view result)
Initialized CKB directory in /PATH/ckb_v0.32.1_x86_64-apple-darwin
create specs/dev.toml
create ckb.toml
create ckb-miner.toml

4. Change the PoW Function to Eaglesong

Modify the func parameter in the specs/dev.toml file under the pow section:

func = "Eaglesong"

Replace the miner.workers section in the ckb-miner.toml file with the following:

[[miner.workers]]
worker_type = "EaglesongSimple"
threads = 1

5. Start the CKB Node

ckb run
(click here to view result)
2020-06-05 11:25:31.433 +08:00 main INFO sentry  sentry is disabled
2020-06-05 11:25:31.508 +08:00 main INFO ckb-db Initialize a new database
2020-06-05 11:25:31.590 +08:00 main INFO ckb-db Init database version 20191127135521
2020-06-05 11:25:31.604 +08:00 main INFO ckb-memory-tracker track current process: unsupported
2020-06-05 11:25:31.604 +08:00 main INFO main ckb version: 0.32.1 (9ebc9ce 2020-05-29)
2020-06-05 11:25:31.604 +08:00 main INFO main chain genesis hash: 0x823b2ff5785b12da8b1363cac9a5cbe566d8b715a4311441b119c39a0367488c
2020-06-05 11:25:31.604 +08:00 main INFO ckb-network Generate random key
2020-06-05 11:25:31.604 +08:00 main INFO ckb-network write random secret key to "/PATH/ckb_v0.32.1_x86_64-apple-darwin/data/network/secret_key"
2020-06-05 11:25:31.608 +08:00 NetworkRuntime INFO ckb-network p2p service event: ListenStarted { address: "/ip4/0.0.0.0/tcp/8115" }
2020-06-05 11:25:31.610 +08:00 NetworkRuntime INFO ckb-network Listen on address: /ip4/0.0.0.0/tcp/8115/p2p/QmcCGH7VeXbpV4jj7VgSEM7NANuud6TmGHV2DXPsSVrRkR
2020-06-05 11:25:31.612 +08:00 main INFO ckb-db Initialize a new database
2020-06-05 11:25:31.638 +08:00 main INFO ckb-db Init database version 20191201091330

6. Start the CKB Miner

This should be performed in a separate terminal.

ckb miner
(click here to view result)
2020-06-05 11:25:37.867 +08:00 main INFO sentry  sentry is disabled
EaglesongSimple-Worker-0 ⠁ [00:00:00]
2020-06-05 11:25:37.870 +08:00 main INFO ckb-memory-tracker track current proceFound! #1 0x57e6ad0f15bacc4f30e53811d488d895e6619c17222981eca5484f0115f84acd
Found! #2 0xe5831f39f928dca599a02e490c482a881ccdc47a2376371dec4e440e363fa5c0
Found! #3 0x605b3e6449954c2daa996c06b2412bbf60b8231763149742119fb623f9de27b2
Found! #4 0x64064e7257ea4589e8cb177cf119c68ab1b4559de005a20dc13ef3d42949e04b

Transferring CKBytes Using ckb-cli

Included in CKB releases is the ckb-cli command line tool. This is can be used to directly invoke RPC calls to perform actions such as managing accounts, transferring CKBytes, and checking account balances. We will demonstrate a CKBytes transfer below. Please refer to ckb-cli for full instructions.

Note: Using ckb-cli to transfer CKBytes is recommended for developing and testing purposes only. For management of real funds and assets please use a wallet.

1. Enter the ckb-cli Interface

ckb-cli
(click here to view result)
[  ckb-cli version ]: 0.31.0 (a531b3b 2020-04-17)
[ url ]: http://127.0.0.1:8114 (network: Dev)
[ pwd ]: /Users/zengbing/Documents/projects/ckb_v0.32.0-rc1_x86_64-apple-darwin-dev
[ color ]: true
[ debug ]: false
[ output format ]: yaml
[ completion style ]: List
[ edit style ]: Emacs
[ index db state ]: Waiting for first query

2. Create a New Account

account new
(click here to view result)
Your new account is locked with a password. Please give a password. Do not forget this password.
Password:
Repeat password:
address:
mainnet: ckb1qyq0g9p6nxf5cdy38fm35zech5f90jl5aueqw4c8mg
testnet: ckt1qyq0g9p6nxf5cdy38fm35zech5f90jl5aueqnsxch5
lock_arg: 0xf4143a99934c34913a771a0b38bd1257cbf4ef32
lock_hash: 0xea4db70029dd393789a6be0e4137a3e95cd8d20b2b028a0fc0eab07622a894f4
  1. Check the Balance of an Existing Account

In the previous sections you created a miner account that collects all mining rewards. Using the following command with the correct address will show you the current CKByte balance:

wallet get-capacity --address "miner's address" 
(click here to view result)
CKB> wallet get-capacity --address "ckt1qyqg6cnaankwgwvh0gaq49uptd3aawhl9p6qpg5cus"
immature: 8027902.89083717 (CKB)
total: 46253677.72927512 (CKB)

4. Transfer 10,000 CKBytes to the New Account

wallet transfer --from-account "miner's address" --to-address "new account's address" --capacity 10000 --tx-fee 0.00001
(click here to view result)
CKB> wallet transfer --from-account ckt1qyqg6cnaankwgwvh0gaq49uptd3aawhl9p6qpg5cus --to-address ckt1qyq0g9p6nxf5cdy38fm35zech5f90jl5aueqnsxch5 --capacity 10000 --max-tx-fee 0.00001
Password:
0x1b66aafaaba5ce34de494f60374ef78e8f536bb3af9cab4fa63c0f29374c3f89

5. Check the New Account's Balance

wallet get-capacity --address "new account's address"
(click here to view result)
CKB> wallet get-capacity --address ckt1qyq0g9p6nxf5cdy38fm35zech5f90jl5aueqnsxch5
total: 10000.0 (CKB)

The transfer is successful!

Adding the Genesis Issued Cells

When the development blockchain configuration is generated with ckb init --chain dev, a few Cells are created with large amounts of capacity. These are specified in specs/dev.toml and exist only for your local development blockchain, and they can be useful for testing purposes.

Genesis Issued Cell #1
Private Key0xd00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc
Lock Arg0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7
Testnet Addressckt1qyqvsv5240xeh85wvnau2eky8pwrhh4jr8ts8vyj37
Capcity20,000,000,000 CKBytes
Genesis Issued Cell #2
Private Key0x63d86723e08f0f813a36ce6aa123bb2289d90680ae1e99d4de8cdb334553f24d
Lock Arg0x470dcdc5e44064909650113a274b3b36aecb6dc7
Testnet Addressckt1qyqywrwdchjyqeysjegpzw38fvandtktdhrs0zaxl4
Capcity5,198,735,037 CKBytes

1. Create Private Key Files

Private keys must be added to a text file before they can be used.

echo 0xd00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc > pk1
echo 0x63d86723e08f0f813a36ce6aa123bb2289d90680ae1e99d4de8cdb334553f24d > pk2

2. Import the Private Keys

Import the private key files using ckb-cli:

CKB> account import --privkey-path pk1
CKB> account import --privkey-path pk2
(click here to view result)
Password:
address:
mainnet: ckb1qyqvsv5240xeh85wvnau2eky8pwrhh4jr8ts6f6daz
testnet: ckt1qyqvsv5240xeh85wvnau2eky8pwrhh4jr8ts8vyj37
lock_arg: 0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7
Password:
address:
mainnet: ckb1qyqywrwdchjyqeysjegpzw38fvandtktdhrsj8renf
testnet: ckt1qyqywrwdchjyqeysjegpzw38fvandtktdhrs0zaxl4
lock_arg: 470dcdc5e44064909650113a274b3b36aecb6dc7
- +

Run a CKB Dev Blockchain

Nervos CKB supports a special development mode that is particularly useful for building and testing applications. This mode of operation is highly configurable, and allows the developer to speed up the block interval, adjust epochs lengths, create blocks without having to do Proof-of-Work (PoW) mining.

When running a development blockchain you have the option of selecting between Dummy-Worker and Eaglesong-Worker. Dummy-Worker allows the mining of blocks at a constant block interval without PoW. Eaglesong-Worker uses real PoW to produce blocks.

Note: It is highly recommended that Dummy-Worker be used for most development scenarios. Eaglesong-Worker should only be used when validating the PoW function is necessary, because the block time can behave erratically with extremely low hashrates.

Setup a Dummy-Worker Blockchain

1. Download the Latest CKB Binary

Download the latest ckb binary file from the CKB releases page on GitHub.

The following commands can be used to verify the binaries are working and to check versions:

ckb --version
ckb-cli --version
(click here to view result)
ckb 0.32.1 (9ebc9ce 2020-05-29)
ckb-cli 0.32.0 (0fc435d 2020-05-22)

2. Initialize the Configuration

Use the following command to initialize the development blockchain and generate the required configuration files:

ckb init --chain dev
(click here to view result)
WARN: mining feature is disabled because of lacking the block assembler config options
Initialized CKB directory in /PATH/ckb_v0.32.1_x86_64-apple-darwin
create specs/dev.toml
create ckb.toml
create ckb-miner.toml

3. Configure the Block Assembler

The Block Assembler configuration specifies which address should be receive block rewards for mining.

3a. Create a New Account

An address to receive the block rewards must be created. We can do this using ckb-cli.

Note: Be sure to record the lock_arg value in the response which we will use in the next step.

ckb-cli account new
(click here to view result)
Your new account is locked with a password. Please give a password. Do not forget this password.
Password:
Repeat password:
address:
mainnet: ckb1qyqyrm8w0w8uq7puwhdp7s6xqzdjuknhf2tqzdztph
testnet: ckt1qyqyrm8w0w8uq7puwhdp7s6xqzdjuknhf2tqlgu5dt
lock_arg: 0x41ecee7b8fc0783c75da1f4346009b2e5a774a96
lock_hash: 0xeb31c5232b322905b9d52350c0d0cf55987f676d86704146ce67d92ddef05ed3

3b. Update the Configuration

Modify the args and message parameters in the ckb.toml file under the block_assembler section:

[block_assembler]
code_hash = "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8" # Do not change this.
args = "0x8d627decece439977a3a0a97815b63debaff2874" # Change this to your lock_arg value.
hash_type = "type" # Do not change this.
message = "A 0x-prefixed hex string" # Change this to "0x" to supply an empty message.

4. Adjust the Parameters to Shorten the Block Interval (Optional)

For most development the default configuration should be sufficient, but sometimes it is beneficial to speed up certain operations so results can be viewed quickly.

4a. Change the Number of Blocks in an Epoch

The default epoch length is 1000 blocks. Reducing this to 10 or 100 can help with testing Nervos DAO operations.

Modify the genesis_epoch_length parameter in the specs/dev.toml file under the params section:

[params]
genesis_epoch_length = 1000 # The unit of meansurement is "block".

4b. Use Permanent Difficulty

When permanent_difficulty_in_dummy is set to true, all epochs will use the same length as the genesis epoch length, skipping the difficulty adjustment entirely. This param is typically used in conjunction with genesis_epoch_length.

Modify the permanent_difficulty_in_dummy parameter in the specs/dev.toml file under the params section:

[params]
genesis_epoch_length = 10
permanent_difficulty_in_dummy = true

4c. Change the Mining Interval

The default mining interval is 5000, which is a value in milliseconds, meaning 5 seconds. Reducing this value will create blocks faster.

Modify the value parameter in the ckb-miner.toml file under the miner.workers section:

[[miner.workers]]
worker_type = "Dummy"
delay_type = "Constant"
value = 5000 # The unit of measurement is "ms".

5. Start the CKB Node

ckb run
(click here to view result)
2020-06-05 18:31:14.970 +08:00 main INFO sentry  sentry is disabled
2020-06-05 18:31:15.058 +08:00 main INFO ckb-db Initialize a new database
2020-06-05 18:31:15.136 +08:00 main INFO ckb-db Init database version 20191127135521
2020-06-05 18:31:15.162 +08:00 main INFO ckb-memory-tracker track current process: unsupported
2020-06-05 18:31:15.164 +08:00 main INFO main ckb version: 0.32.1 (9ebc9ce 2020-05-29)
2020-06-05 18:31:15.164 +08:00 main INFO main chain genesis hash: 0x823b2ff5785b12da8b1363cac9a5cbe566d8b715a4311441b119c39a0367488c
2020-06-05 18:31:15.166 +08:00 main INFO ckb-network Generate random key
2020-06-05 18:31:15.166 +08:00 main INFO ckb-network write random secret key to "/PATH/ckb_v0.32.1_x86_64-apple-darwin/data/network/secret_key"
2020-06-05 18:31:15.177 +08:00 NetworkRuntime INFO ckb-network p2p service event: ListenStarted { address: "/ip4/0.0.0.0/tcp/8115" }
2020-06-05 18:31:15.179 +08:00 NetworkRuntime INFO ckb-network Listen on address: /ip4/0.0.0.0/tcp/8115/p2p/QmSHk4EucevEuX76Q44hEdYpRxr3gyDmbKtnMQ4kxGaJ6m
2020-06-05 18:31:15.185 +08:00 main INFO ckb-db Initialize a new database
2020-06-05 18:31:15.211 +08:00 main INFO ckb-db Init database version 20191201091330
2020-06-05 18:31:26.586 +08:00 ChainService INFO ckb-chain block: 1, hash: 0x47995f78e95202d2c85ce11bce2ee16d131a57d871f7d93cd4c90ad2a8220bd1, epoch: 0(1/1000), total_diff: 0x200, txs: 1

6. Start the CKB Miner

This should be performed in a separate terminal.

ckb miner
(click here to view result)
2020-06-05 18:31:21.558 +08:00 main INFO sentry  sentry is disabled
Dummy-Worker ⠁ [00:00:00]
Found! #1 0x47995f78e95202d2c85ce11bce2ee16d131a57d871f7d93cd4c90ad2a8220bd1
Found! #2 0x19978085abfa6204471d42bfb279eac0c20e3b81745b48c4dcaea85643e301f9
Found! #3 0x625b230f84cb92bcd9cb0bf76d1397c1d948ab25c19df3c4edc246a765f94427
Found! #4 0x4550fb3b62d9d5ba4d3926db6704b25b90438cfb67037d253ceceb2d86ffdbf7

Setup an Eaglesong-Worker Blockchain

1. Download the Latest CKB Binary

Download the latest ckb binary file from the CKB releases page on GitHub.

The following commands can be used to verify the binaries are working and to check versions:

ckb --version
ckb-cli --version
(click here to view result)
ckb 0.32.1 (9ebc9ce 2020-05-29)
ckb-cli 0.32.0 (0fc435d 2020-05-22)

2. Create a New Account

An address to receive the block rewards must be created. We can do this using ckb-cli.

Note: Be sure to record the lock_arg value in the response which we will use in the next step.

ckb-cli account new
(click here to view result)
Your new account is locked with a password. Please give a password. Do not forget this password.
Password:
Repeat password:
address:
mainnet: ckb1qyqyrm8w0w8uq7puwhdp7s6xqzdjuknhf2tqzdztph
testnet: ckt1qyqyrm8w0w8uq7puwhdp7s6xqzdjuknhf2tqlgu5dt
lock_arg: 0x41ecee7b8fc0783c75da1f4346009b2e5a774a96
lock_hash: 0xeb31c5232b322905b9d52350c0d0cf55987f676d86704146ce67d92ddef05ed3

3. Initialize the Configuration with the Miner Account

ckb init -c dev --ba-arg 0x41ecee7b8fc0783c75da1f4346009b2e5a774a96 // Change this to your lock_arg value. 
(click here to view result)
Initialized CKB directory in /PATH/ckb_v0.32.1_x86_64-apple-darwin
create specs/dev.toml
create ckb.toml
create ckb-miner.toml

4. Change the PoW Function to Eaglesong

Modify the func parameter in the specs/dev.toml file under the pow section:

func = "Eaglesong"

Replace the miner.workers section in the ckb-miner.toml file with the following:

[[miner.workers]]
worker_type = "EaglesongSimple"
threads = 1

5. Start the CKB Node

ckb run
(click here to view result)
2020-06-05 11:25:31.433 +08:00 main INFO sentry  sentry is disabled
2020-06-05 11:25:31.508 +08:00 main INFO ckb-db Initialize a new database
2020-06-05 11:25:31.590 +08:00 main INFO ckb-db Init database version 20191127135521
2020-06-05 11:25:31.604 +08:00 main INFO ckb-memory-tracker track current process: unsupported
2020-06-05 11:25:31.604 +08:00 main INFO main ckb version: 0.32.1 (9ebc9ce 2020-05-29)
2020-06-05 11:25:31.604 +08:00 main INFO main chain genesis hash: 0x823b2ff5785b12da8b1363cac9a5cbe566d8b715a4311441b119c39a0367488c
2020-06-05 11:25:31.604 +08:00 main INFO ckb-network Generate random key
2020-06-05 11:25:31.604 +08:00 main INFO ckb-network write random secret key to "/PATH/ckb_v0.32.1_x86_64-apple-darwin/data/network/secret_key"
2020-06-05 11:25:31.608 +08:00 NetworkRuntime INFO ckb-network p2p service event: ListenStarted { address: "/ip4/0.0.0.0/tcp/8115" }
2020-06-05 11:25:31.610 +08:00 NetworkRuntime INFO ckb-network Listen on address: /ip4/0.0.0.0/tcp/8115/p2p/QmcCGH7VeXbpV4jj7VgSEM7NANuud6TmGHV2DXPsSVrRkR
2020-06-05 11:25:31.612 +08:00 main INFO ckb-db Initialize a new database
2020-06-05 11:25:31.638 +08:00 main INFO ckb-db Init database version 20191201091330

6. Start the CKB Miner

This should be performed in a separate terminal.

ckb miner
(click here to view result)
2020-06-05 11:25:37.867 +08:00 main INFO sentry  sentry is disabled
EaglesongSimple-Worker-0 ⠁ [00:00:00]
2020-06-05 11:25:37.870 +08:00 main INFO ckb-memory-tracker track current proceFound! #1 0x57e6ad0f15bacc4f30e53811d488d895e6619c17222981eca5484f0115f84acd
Found! #2 0xe5831f39f928dca599a02e490c482a881ccdc47a2376371dec4e440e363fa5c0
Found! #3 0x605b3e6449954c2daa996c06b2412bbf60b8231763149742119fb623f9de27b2
Found! #4 0x64064e7257ea4589e8cb177cf119c68ab1b4559de005a20dc13ef3d42949e04b

Transferring CKBytes Using ckb-cli

Included in CKB releases is the ckb-cli command line tool. This is can be used to directly invoke RPC calls to perform actions such as managing accounts, transferring CKBytes, and checking account balances. We will demonstrate a CKBytes transfer below. Please refer to ckb-cli for full instructions.

Note: Using ckb-cli to transfer CKBytes is recommended for developing and testing purposes only. For management of real funds and assets please use a wallet.

1. Enter the ckb-cli Interface

ckb-cli
(click here to view result)
[  ckb-cli version ]: 0.31.0 (a531b3b 2020-04-17)
[ url ]: http://127.0.0.1:8114 (network: Dev)
[ pwd ]: /Users/zengbing/Documents/projects/ckb_v0.32.0-rc1_x86_64-apple-darwin-dev
[ color ]: true
[ debug ]: false
[ output format ]: yaml
[ completion style ]: List
[ edit style ]: Emacs
[ index db state ]: Waiting for first query

2. Create a New Account

account new
(click here to view result)
Your new account is locked with a password. Please give a password. Do not forget this password.
Password:
Repeat password:
address:
mainnet: ckb1qyq0g9p6nxf5cdy38fm35zech5f90jl5aueqw4c8mg
testnet: ckt1qyq0g9p6nxf5cdy38fm35zech5f90jl5aueqnsxch5
lock_arg: 0xf4143a99934c34913a771a0b38bd1257cbf4ef32
lock_hash: 0xea4db70029dd393789a6be0e4137a3e95cd8d20b2b028a0fc0eab07622a894f4
  1. Check the Balance of an Existing Account

In the previous sections you created a miner account that collects all mining rewards. Using the following command with the correct address will show you the current CKByte balance:

wallet get-capacity --address "miner's address" 
(click here to view result)
CKB> wallet get-capacity --address "ckt1qyqg6cnaankwgwvh0gaq49uptd3aawhl9p6qpg5cus"
immature: 8027902.89083717 (CKB)
total: 46253677.72927512 (CKB)

4. Transfer 10,000 CKBytes to the New Account

wallet transfer --from-account "miner's address" --to-address "new account's address" --capacity 10000 --tx-fee 0.00001
(click here to view result)
CKB> wallet transfer --from-account ckt1qyqg6cnaankwgwvh0gaq49uptd3aawhl9p6qpg5cus --to-address ckt1qyq0g9p6nxf5cdy38fm35zech5f90jl5aueqnsxch5 --capacity 10000 --max-tx-fee 0.00001
Password:
0x1b66aafaaba5ce34de494f60374ef78e8f536bb3af9cab4fa63c0f29374c3f89

5. Check the New Account's Balance

wallet get-capacity --address "new account's address"
(click here to view result)
CKB> wallet get-capacity --address ckt1qyq0g9p6nxf5cdy38fm35zech5f90jl5aueqnsxch5
total: 10000.0 (CKB)

The transfer is successful!

Adding the Genesis Issued Cells

When the development blockchain configuration is generated with ckb init --chain dev, a few Cells are created with large amounts of capacity. These are specified in specs/dev.toml and exist only for your local development blockchain, and they can be useful for testing purposes.

Genesis Issued Cell #1
Private Key0xd00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc
Lock Arg0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7
Testnet Addressckt1qyqvsv5240xeh85wvnau2eky8pwrhh4jr8ts8vyj37
Capcity20,000,000,000 CKBytes
Genesis Issued Cell #2
Private Key0x63d86723e08f0f813a36ce6aa123bb2289d90680ae1e99d4de8cdb334553f24d
Lock Arg0x470dcdc5e44064909650113a274b3b36aecb6dc7
Testnet Addressckt1qyqywrwdchjyqeysjegpzw38fvandtktdhrs0zaxl4
Capcity5,198,735,037 CKBytes

1. Create Private Key Files

Private keys must be added to a text file before they can be used.

echo 0xd00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc > pk1
echo 0x63d86723e08f0f813a36ce6aa123bb2289d90680ae1e99d4de8cdb334553f24d > pk2

2. Import the Private Keys

Import the private key files using ckb-cli:

CKB> account import --privkey-path pk1
CKB> account import --privkey-path pk2
(click here to view result)
Password:
address:
mainnet: ckb1qyqvsv5240xeh85wvnau2eky8pwrhh4jr8ts6f6daz
testnet: ckt1qyqvsv5240xeh85wvnau2eky8pwrhh4jr8ts8vyj37
lock_arg: 0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7
Password:
address:
mainnet: ckb1qyqywrwdchjyqeysjegpzw38fvandtktdhrsj8renf
testnet: ckt1qyqywrwdchjyqeysjegpzw38fvandtktdhrs0zaxl4
lock_arg: 470dcdc5e44064909650113a274b3b36aecb6dc7
+ \ No newline at end of file diff --git a/docs/basics/guides/get-ckb/index.html b/docs/basics/guides/get-ckb/index.html index ccdc8ad1f..0571d957b 100644 --- a/docs/basics/guides/get-ckb/index.html +++ b/docs/basics/guides/get-ckb/index.html @@ -14,7 +14,7 @@ Get CKB Binary | Nervos CKB - + @@ -32,7 +32,7 @@ target/release/ckb. Please add the directory to PATH or copy/link the file into a directory already in the PATH.

export PATH="$(pwd)/target/release:$PATH"
# or
# ln -snf "$(pwd)/target/release/ckb" /usr/local/bin/ckb

Download from Releases

We publish binaries for each release via Github Releases. You can download the package directly.

If you are CentOS user, please use the x86_64-unknown-centos-gnu package, which also requires OpenSSL 1.0:

sudo yum install openssl-libs
- + \ No newline at end of file diff --git a/docs/basics/guides/mainnet/index.html b/docs/basics/guides/mainnet/index.html index 8b2838e4a..697cbb02d 100644 --- a/docs/basics/guides/mainnet/index.html +++ b/docs/basics/guides/mainnet/index.html @@ -14,13 +14,13 @@ Run a CKB Node | Nervos CKB - +

Run a CKB Node

Running a CKB node not only contributes to the robustness and decentralized nature of the network, but also allows you to access data from the blockchain without any third party, which in turn increases your security.

To run a node, you need to use the command line. If you have never used it before, you may refer to how to use the command line tool to get started on your computer. Although it may seem complicated at first, it is quite simple and following the specific instructions below should allow you to easily run a CKB mainnet node.

Run a CKB Mainnet Node

Step 1: Download the latest CKB binary file from CKB releases page on GitHub

Step 2: Unzip and extract the downloaded file to an easily accessible folder. We recommend C:\ckb for Windows and ~/Documents for Mac.

Step 3: Open Terminal on Mac or Command Prompt on Windows.

  • Mac:

You can open Terminal in two ways: either go to the Applications folder, then open Utilities and double-click on Terminal, or launch Spotlight search by pressing Command - Spacebar or Control -Spacebar, then type "Terminal" and double-click on the search result. The subsequent steps will be executed in Terminal.

  • Windows:

(If you are familiar with command line in Windows, you can skip this step and open cmd or Power Shell instead.)

Download and install Git for Windows, once the installation is complete, open the Command Prompt.

In the Command Prompt window, type the following git command and press Enter:

git --version

This verify Git commands are available and its current version (--version)

Step 4:Copy and paste the commands below into the Terminal (Mac) or Command Prompt (Windows):

Note: make sure to edit the commands according to your folder names and directory.

  • Mac
cd /Users/(NAME)/Documents/ckb_v0.32.1_x86_64-apple-darwin
./ckb --version
./ckb-cli --version
  • Windows
cd C:/ckb_v0.32.1_x86_64-pc-windows-msvc 
ckb --version
ckb-cli --version
(click here to view response)

ckb 0.32.1 (9ebc9ce 2020-05-29)
ckb-cli 0.32.0 (0fc435d 2020-05-22)

Step 5: To run the CKB mainnet node, copy and paste the commands below into Terminal (Mac) / Command Prompt (Windows):

  • Initialize the node (run only once)
ckb init --chain mainnet
(click here to view response)

WARN: mining feature is disabled because of lacking the block assembler config options
Initialized CKB directory in /PATH/ckb_v0.32.1_x86_64-apple-darwin
create ckb.toml
create ckb-miner.toml

** Start the node.

ckb run
(click here to view response)

2020-06-05 18:10:19.785 +08:00 main INFO sentry sentry is disabled
2020-06-05 18:10:19.869 +08:00 main INFO main Miner is disabled, edit ckb.toml to enable it
2020-06-05 18:10:19.942 +08:00 main INFO ckb-memory-tracker track current process: unsupported
2020-06-05 18:10:19.942 +08:00 main INFO main ckb version: 0.32.1 (9ebc9ce 2020-05-29)
2020-06-05 18:10:19.942 +08:00 main INFO main chain genesis hash: 0x92b197aa1fba0f63633922c61c92375c9c074a93e85963554f5499fe1450d0e5
2020-06-05 18:10:19.944 +08:00 NetworkRuntime INFO ckb-network p2p service event: ListenStarted { address: "/ip4/0.0.0.0/tcp/8115" }
2020-06-05 18:10:19.946 +08:00 NetworkRuntime INFO ckb-network Listen on address: /ip4/0.0.0.0/tcp/8115/p2p/QmWKGXVhYx2T8YmbsC1RYjnrRf1hfz2ZNTMywrkN9y2bVg
2020-06-05 18:10:19.951 +08:00 main INFO ckb-db Initialize a new database
2020-06-05 18:10:19.983 +08:00 main INFO ckb-db Init database version 20191201091330
2020-06-05 18:10:20.146 +08:00 NetworkRuntime INFO ckb-relay RelayProtocol(1).connected peer=SessionId(1)
2020-06-05 18:10:20.146 +08:00 NetworkRuntime INFO ckb-sync SyncProtocol.connected peer=SessionId(1)
2020-06-05 18:10:20.451 +08:00 NetworkRuntime INFO ckb-sync Ignoring getheaders from peer=SessionId(1) because node is in initial block download
2020-06-05 18:10:20.749 +08:00 ChainService INFO ckb-chain block: 1, hash: 0x2567f226c73b04a6cb3ef04b3bb10ab99f37850794cd9569be7de00bac4db875, epoch: 0(1/1743), total_diff: 0x3b1bb3d4c1376a, txs:1

Run a Public RPC Node

CKB nodes have built-in RPC functionality, which becomes available as soon as the node is started.

RPC is private by default. Exposing RPC through the rpc.listen_address configuration option allows arbitrary machines to access the JSON-RPC port, posing a security risk. Therefore, it is strongly discouraged.

However, if you have to expose them, make sure to strictly limit the access to trusted machines only, by following the method below.

RPC Access Control

Here is an example to use Nginx API Gateway to configure the RPC access control. Explore more solutions or submit new ones using the GitHub tag ckb-rpc-proxy.

Step 1: Install Docker-Compose and Docker

apt install docker-compose
apt install docker

Step 2: Clone Code

git clone https://github.com/cryptape/ckb-nginx-proxy.git

Step 3: Replace Default Value With Your CKB RPC Address

cd ckb-nginx-proxy

sed -i "s/YOUR_CKR_RPC_IP:8114/192.168.1.100:8114/" nginx.conf

Step 4: Run Proxy

docker-compose up -d

Example

Get tip block hash and number:

echo '{
"id": 2,
"jsonrpc": "2.0",
"method": "get_tip_header",
"params": []
}' \
| tr -d '\n' \
| curl -H 'content-type: application/json' -d @- \
http://192.168.1.100:80

// Note that http://192.168.1.100:80 needs to be changed to your proxy IP!

Result:

{
"jsonrpc": "2.0",
"result": {
"compact_target": "0x1d090fbe",
"dao": "0xba17553fab3db84154bc4aa9f09b2600e826a2b0df99010400ed51b4686b5808",
"epoch": "0x7080687001539",
"extra_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"hash": "0x7a46e779a3fc2d5b55c82aad852e721b0097bf873927b9751409b1d185599ce4",
"nonce": "0xd265e70dfd205dbbed33b29294121856",
"number": "0x7037f2",
"parent_hash": "0x3d105fe9ec60f138baa6623abd16af70ba1be90ad23d1943bcaa55d5f14fcb6f",
"proposals_hash": "0x2581d1769886226a8c90ee99baf2d8696e24c7f6bb6751748ff8b4452f8006e5",
"timestamp": "0x1847a2bfad2",
"transactions_root": "0x28157a5962c4ae1d3e153b1d8d331e5fd3c158866287f5398ab7f7d38210dfb0",
"version": "0x0"
},
"id": 2
}

Execute clear_tx_pool:

echo '{
"id": 2,
"jsonrpc": "2.0",
"method": "clear_tx_pool",
"params": []
}' | tr -d '\n' | curl -H 'content-type: application/json' -d @- \
http://192.168.1.100:80

Result:

This method has been banned

List of Restricted Methods

clear_banned_addresses
set_ban
set_network_active
add_node
remove_node
remove_transaction
clear_tx_pool
- + \ No newline at end of file diff --git a/docs/basics/guides/mining-ckb/index.html b/docs/basics/guides/mining-ckb/index.html index 52c217c45..bff3889a4 100644 --- a/docs/basics/guides/mining-ckb/index.html +++ b/docs/basics/guides/mining-ckb/index.html @@ -14,13 +14,13 @@ Mining CKB | Nervos CKB - +

Mining CKB

Nervos Network's layer 1 blockchain, the Common Knowledge Base, relies on Proof of Work (PoW) mining to provide consensus at the bottom-most layer of the ecosystem. PoW mining serves a critical role in the ecosystem, providing both security and decentralization guarantees to the entire ecosystem.

Miners are an important part of the community, and they provide an essential service to Nervos. In exchange for providing this service, they are paid a reward in CKBytes (CKB) to align their interests in a way that benefits all users of the blockchain. Mining can be both fun and profitable, but it also has inherent risks and challenges that are not for everyone. It is important to understand what you're getting into before diving in.

This guide will help those who are interested in mining get started on Nervos. We will discuss the essential basics, such as how to find compatible equipment, the importance of choosing a mining pool, and most importantly, we will point out a few other informational resources that will help you to make your mining operation successful.

Step 1 - Research and Planning

Planning is the most important step in any successful mining operation. Do you have a well-ventilated place where the sound of the miners will not bother anyone? Do you have the proper electrical wiring to support your miners? Are your electricity rates competitive year-round? These are the kinds of questions you need to be able to answer before you start buying equipment.

Many of these considerations and covered in the articles written here and here. There are also many video resources on YouTube that may also help you to get a better idea of what is involved with mining on Nervos. Using free tools like mining calculators can help you to understand what your costs will be. You can ask questions to other miners in the community-run Nervos Mining CKB Telegram channel or in the #mining-chat channel on the Nervos Discord server.

Unlike mining for gold, there is very little guesswork in cryptocurrency mining. If you have properly done your research, then you should have realistic expectations about miner operation and profitability before you have made any kind of commitment. Don't skip out here! A little bit of research goes a very long way.

Step 2 - Select Your Mining Hardware

Nervos uses the Eaglesong hashing algorithm in mining, and specialized miners called ASICs are used to mine CKB. You must use a miner that is specifically designed for Nervos. You cannot use a miner from a different currency, because it is likely to be incompatible.

In the past, mining was done using GPUs and FPGA miners, but now ASICs are required. This is because ASICs are more specialized, and are the fastest and most efficient. GPUs and FPGA mining is still possible, but it is not efficient enough to be profitable.

There are many ASIC miners available, but not all are created equally. Some are better than others. New and improved miners come out regularly. Sites like ASIC Miner Value have information on what miners are available for the Eaglesong algorithm, as well as the specifications. Some are quiet, and some are extremely noisy. Some run on 110-volt electricity and others require 220-volt electricity. All these things must be considered.

If you're unsure, you can always ask other miners on Telegram or Discord about their experiences.

Step 3 - Select a Wallet

The CKB that you earn from mining are sent to the Nervos address that you specify. To create an address you will need to install wallet software. Nervos has many different wallet options available for both desktop computers and mobile phones, and any of them can be used for mining.

Neuron Wallet is a desktop wallet produced by the Nervos Foundation. It is a full node wallet, which means that it will download the full Nervos blockchain in the background. Because it runs a full node, it is often regarded to be the most secure wallet. However, the full node takes many gigabytes of disk space and may take up to 72 hours to complete the initial synchronization. Ledger hardware wallets can also be used with Neuron to give an extra layer of security.

CKBull, imToken, and SafePal are popular mobile wallets provided by third-party companies. All three wallets support both Google Android devices and Apple iOS devices.

Many other wallets are also available. The Nervos Community maintains a more comprehensive list of wallets within the Nervos ecosystem.

Step 4 - Select a Mining Pool

Selecting a mining pool is one of the most important decisions you will make when you start mining. This is not only important for your profitability as a miner, but it is also important for the long-term health of the network itself.

Decentralized blockchains can become more vulnerable to a 51% attack when too much mining power is concentrated in single mining pools. When choosing a pool, consider selecting one of the smaller pools to help keep the hash power decentralized.

Larger pools tend to find blocks more quickly, and thus have faster payouts for miners. However, the payouts are smaller since you represent a smaller slice of the total pool. Smaller pools will have slower payouts but each payout will be larger. In theory, total earnings between a large and small pool should be roughly the same in the long term.

A few other things to consider when selecting a pool:

  • Mining Pool Fees: Mining pool fees normally hover between 1% and 3%. In addition to the percentage, there are also different payment systems to consider.
  • Transparency: Most pools have metrics and charts available that give users the ability to see how the pool is performing. A dishonest pool could claim to have a low fee and then take an unfair share of the mining rewards. The more transparent the pool is, the less likely this is to occur.
  • Security: A well-run pool should have some history and a track record of successful payouts. Remember, you are trusting the pool with your earnings. If they have poor security, they may lose some of your funds.
  • Proximity: Pools that are closer to your location are usually better. This is because PoW is inherently a race to find answers. The closer you are to a pool, the faster you can communicate, and this can result in slightly higher payouts.

Part of a miner's duty is to protect the integrity of the network. A successful 51% attack on the network would likely result in lower profitability for all miners. This is why we stress so thoroughly that you perform your due diligence when selecting a pool and do your part to promote decentralization by supporting smaller pools.

The steps to create a pool account and the settings needed for your miner can differ from pool to pool. This information is specific to each pool and provided by the pools themselves.

Here are a few more helpful resources to see the hashrate, fees, and various features on several of the pools that support Nervos.

Step 5 - Set Up and Configure Your CKB Miner

Once you have your miner, wallet address, and pool account, you are ready to start mining. If this is the first time you're setting up a miner, there are a few things you may want to check.

  • Inspect your miner for damage carefully. Most miners are shipped internationally, and equipment can easily be damaged in transit.
  • Check your area for loose materials like paper and plastic bags. Some miners have strong fans which can become clogged easily. That can lead to overheating which results in poor performance or even hardware damage.
  • After your miner is running, verify the temperature of the miner and all power cables in the area periodically. It's normal for miners to be warm to the touch, but a scorching hot miner or cable could indicate a ventilation problem that could lead to a fire.

Every miner has different interfaces and specific procedures that must be followed for setup and configuration. However, most will follow these basic steps:

  1. Connect your miner's network and power cables.
  2. Locate your miner's IP address on the network.
  3. Open your miner's admin panel in a web browser.
  4. Check for updates to your miner's firmware.
  5. Update your miner's configuration with your pool settings.

After these steps are completed, your miner should be up and running. Sometimes it can take a few minutes to start but after 10-15 minutes your miner's activity should be visible within your pool dashboard.

Where to Get Help

If you have trouble with your miner, check to see if the manufacturer provides support. Some pools will also offer support for users who need help configuring their miners.

You can also ask other CKB miners on Telegram and Discord for help since many of them will be running similar equipment on similar pools.

The Nervos Community maintains a list of mining resources that has lots of helpful information and tips.

- + \ No newline at end of file diff --git a/docs/basics/guides/monitor-nodes/index.html b/docs/basics/guides/monitor-nodes/index.html index 0fc7bba58..76d207471 100644 --- a/docs/basics/guides/monitor-nodes/index.html +++ b/docs/basics/guides/monitor-nodes/index.html @@ -14,13 +14,13 @@ Monitor Nodes With CKBGuardian | Nervos CKB - +

Monitor Nodes With CKBGuardian

CKBGuardian is a RPC status monitor for CKB public nodes. It can also check whether CKB and CKB proxy have been started properly. Its purpose is to verify the connectivity of the RPC, not the validity of the results.

Local Testting

Step 1: Clone Code

git clone https://github.com/cryptape/CkbGuardian.git

Step 2: Add Check Node Message

Modify the rpc field only.

echo "[
{
\"name\": \"public\",
\"url\": \"web url\",
\"network\": \"MIRANA\",
\"rpc\": \"http://localhost:8114\",
\"excludeMethods\": [\"send_alert\",\"clear_banned_addresses\",\"set_ban\",\"set_network_active\",\"add_node\",\"remove_node\",\"remove_transaction\",\"clear_tx_pool\",\"subscribe\",\"unsubscribe\"]
}
]" > CkbGuardian/ckb/resource/ckb.json

Step 3: Run Test

cd CkbGuardian/ckb
npm i
npm run test

Daily Monitoring with GitHub Action

To add a new node to CKBGuardian:

Step 1: Edit this JSON file by adding the relevant information for the new node.

Step 2: Fill in the following fields in the CkbNodeConfig class:

export class CkbNodeConfig {
name: string. // server name
url: string. // server url
network: string. // now noly support main
rpc: string. // rpc url
apiKeyName: string. // if need api-key
excludeMethods: string[]. // service not support methods
}

Step 3: Once you have updated the file, send a pull request.

Here is an example.

If an API key is needed to connect to CKB service, follow these steps:

  1. Add apikeyName: SERVICE_API_KEY

  2. Add [.env](https://github.com/gpBlockchain/CkbGuardian/blob/main/ckb/.env) and fill out the SERVICE_API_KEY

GET_BLOCK_API_KEY=""
  1. Modify the relevant workflow.

  2. Contact the project administrator to add the action secret.

- + \ No newline at end of file diff --git a/docs/basics/guides/run-ckb-with-docker/index.html b/docs/basics/guides/run-ckb-with-docker/index.html index 256b42b2b..b368168d5 100644 --- a/docs/basics/guides/run-ckb-with-docker/index.html +++ b/docs/basics/guides/run-ckb-with-docker/index.html @@ -14,7 +14,7 @@ Run a CKB Mainnet Node and Testnet Node with Docker | Nervos CKB - + @@ -23,7 +23,7 @@ and start CKB from it.

  • Create a volume
docker volume create ckb-mainnet
  • Initialize the directory with mainnet chain spec.
docker run --rm -it \
-v ckb-mainnet:/var/lib/ckb \
nervos/ckb:latest init --chain mainnet --force
  • Create a container ckb-mainnet-node to run a node:
docker create -it \
-v ckb-mainnet:/var/lib/ckb \
--name ckb-mainnet-node \
nervos/ckb:latest run
  • Copy the generated config files from the container:
docker cp ckb-mainnet-node:/var/lib/ckb/ckb.toml .
docker cp ckb-mainnet-node:/var/lib/ckb/ckb-miner.toml .
  • Edit the config files. If you want to run a miner, remember to replace [block_assembler] section in ckb.toml. you can refer to Configure the Block Assembler.

  • Copy back the edited config files back to container:

tar --owner=1000 --group=1000 -cf - ckb.toml ckb-miner.toml | \
docker cp - ckb-mainnet-node:/var/lib/ckb/
  • start the node:
docker start -i ckb-mainnet-node
  • And start the miner in the same container
docker exec ckb-mainnet-node ckb miner

Run a CKB Testnet node

Get the CKB image

After the release of ckb v0.26.1, by modifying the environment variable CKB_CHAIN, you can run CKB Testnet node with default configuration,such as:

docker run -e CKB_CHAIN=testnet --rm -it nervos/ckb:latest run

Mount the configuration file and Run a CKB Testnet node

  • Create a volume
docker volume create ckb-testnet
  • Initialize the directory with testnet chain spec.
docker run --rm -it \
-v ckb-testnet:/var/lib/ckb \
nervos/ckb:latest init --spec testnet --force
  • Create a container ckb-testnet-node to run a node:
docker create -it \
-v ckb-testnet:/var/lib/ckb \
--name ckb-testnet-node \
nervos/ckb:latest run
  • Copy the generated config files from the container:
docker cp ckb-testnet-node:/var/lib/ckb/ckb.toml .
docker cp ckb-testnet-node:/var/lib/ckb/ckb-miner.toml .
  • Edit the config files. If you want to run a miner, remember to replace [block_assembler] section in ckb.toml. you can refer to Configure the Block Assembler.

  • Copy back the edited config files back to container:

docker cp ckb-testnet-node:/var/lib/ckb/ckb.toml .
docker cp ckb-testnet-node:/var/lib/ckb/ckb-miner.toml .
  • start the node:
docker start -i ckb-testnet-node
  • And start the miner in the same container
docker exec ckb-testnet-node ckb miner
- + \ No newline at end of file diff --git a/docs/basics/guides/testnet/index.html b/docs/basics/guides/testnet/index.html index a928f6550..f6bde0a3b 100644 --- a/docs/basics/guides/testnet/index.html +++ b/docs/basics/guides/testnet/index.html @@ -14,14 +14,14 @@ Run a CKB Testnet Node | Nervos CKB - +

Run a CKB Testnet Node

We have launched Aggron Testnet for developers to test their integration and smart contracts in real environment.The Aggron Testnet’s info has been published via Wiki: Chains .Please refer it for more details. Because of the hash rate surge, Aggron will reset regularly.

Run a CKB Testnet node

System Requirements

Any modern computer with macOS/Linux/Windows operating system should be able to run a CKB node and mining programs. Alternatively, you can also use Docker if your operating system is not properly supported by CKB for now.

To run a CKB node, please follow the instructions explained in detail below:

Step 1: Download the latest ckb binary file from the CKB releases page on [GitHub] (https://github.com/nervosnetwork/ckb/releases), then check if it works with:

ckb --version 
ckb-cli --version
(click here to view response)
ckb 0.32.1 (9ebc9ce 2020-05-29)
ckb-cli 0.32.0 (0fc435d 2020-05-22)

Step 2: Connect to Aggron Testnet

  • Init CKB node with ckb init --chain testnet
ckb init --chain testnet
(click here to view response)
WARN: mining feature is disabled because of lacking the block assembler config options
Initialized CKB directory in /PATH/ckb_v0.32.1_x86_64-apple-darwin
create ckb.toml
create ckb-miner.toml

Step 3: Start the CKB Testnet node

<p>ckb run</p>
(click here to view response)
2020-06-05 18:23:10.086 +08:00 main INFO sentry  **Notice**: The ckb process will send stack trace to sentry on Rust panics. This is enabled by default before mainnet, which can be opted out by setting the option `dsn` to empty in the config file. The DSN is now https://dda4f353e15f4b62800d273a2afe70c2@sentry.nervos.org/4
2020-06-05 18:23:10.172 +08:00 main INFO main Miner is disabled, edit ckb.toml to enable it
2020-06-05 18:23:10.176 +08:00 main INFO ckb-db Initialize a new database
2020-06-05 18:23:10.263 +08:00 main INFO ckb-db Init database version 20191127135521
2020-06-05 18:23:10.283 +08:00 main INFO ckb-memory-tracker track current process: unsupported
2020-06-05 18:23:10.284 +08:00 main INFO main ckb version: 0.32.1 (9ebc9ce 2020-05-29)
2020-06-05 18:23:10.284 +08:00 main INFO main chain genesis hash: 0x10639e0895502b5688a6be8cf69460d76541bfa4821629d86d62ba0aae3f9606
2020-06-05 18:23:10.285 +08:00 main INFO ckb-network Generate random key
2020-06-05 18:23:10.285 +08:00 main INFO ckb-network write random secret key to "/PATH/ckb_v0.32.1_x86_64-apple-darwin/data/network/secret_key"
2020-06-05 18:23:10.296 +08:00 NetworkRuntime INFO ckb-network p2p service event: ListenStarted { address: "/ip4/0.0.0.0/tcp/8115" }
2020-06-05 18:23:10.298 +08:00 NetworkRuntime INFO ckb-network Listen on address: /ip4/0.0.0.0/tcp/8115/p2p/QmWpdvd65BhJV3KVyidSkGjd3SuTdCSNgk1WuRpnggMLWj
2020-06-05 18:23:10.303 +08:00 main INFO ckb-db Initialize a new database
2020-06-05 18:23:10.336 +08:00 main INFO ckb-db Init database version 20191201091330
2020-06-05 18:23:10.484 +08:00 NetworkRuntime INFO ckb-sync SyncProtocol.connected peer=SessionId(1)
2020-06-05 18:23:10.484 +08:00 NetworkRuntime INFO ckb-relay RelayProtocol(1).connected peer=SessionId(1)
2020-06-05 18:23:10.732 +08:00 NetworkRuntime INFO ckb-sync Ignoring getheaders from peer=SessionId(1) because node is in initial block download
2020-06-05 18:23:10.927 +08:00 ChainService INFO ckb-chain block: 1, hash: 0xd5ac7cf8c34a975bf258a34f1c2507638487ab71aa4d10a9ec73704aa3abf9cd, epoch: 0(1/1000), total_diff: 0x1800060, txs: 1

- + \ No newline at end of file diff --git a/docs/basics/introduction/index.html b/docs/basics/introduction/index.html index fd9f51e81..e4ea4d745 100644 --- a/docs/basics/introduction/index.html +++ b/docs/basics/introduction/index.html @@ -14,13 +14,13 @@ Introduction | Nervos CKB - +

Introduction

The Basics section covers the most common essential topics relevant to users of all technical levels.

Being familiar with blockchain technology is helpful, but it's not absolutely essential. Links to additional reading materials will be provided along the way.

Concepts

An introduction to the key concepts that serve as a foundation for the Nervos platform and differentiate Nervos from other blockchain ecosystems. We explore concepts at a high-level in a simplified way that is easy to understand.

Guides

Walkthroughs on common topics such as setting up a full node and using the Neuron Wallet.

Tools

A list of common tools used with Nervos, such as the Neuron Wallet, the CKB Explorer, and Testnet Faucet.

Glossary

A comprehensive list of terminology used in blockchain and cryptocurrency.

FAQ

The FAQ section includes questions that are commonly asked by customers and cover topics including CKB address or layer 1, cell model, consensus and more.

- + \ No newline at end of file diff --git a/docs/basics/tools/index.html b/docs/basics/tools/index.html index a443e56f2..03e0d14f9 100644 --- a/docs/basics/tools/index.html +++ b/docs/basics/tools/index.html @@ -14,13 +14,13 @@ Tools | Nervos CKB - +

Tools

Nervos Community is a cohesive community that embraces the contributions of every member. We welcome everyone to provide passion, innovation and diversity of ideas to improve Nervos.If you are new here, there are three tools Neuron Wallet, CKB-Explorer and Testnet Faucet, hope it will be helpful for you.

Neuron Wallet

Github | Download

A blockchain wallet is very important in the blockchain ecosystem, it is a user’s gateway to the blockchain world.

Neuron Wallet is a CKB wallet produced by the Nervos Foundation, it holds your keys and can create and broadcast transactions on your behalf. The functionality of the Neuron Wallet is focused on transfer of CKBytes and deposit/withdrawal functions of the Nervos DAO.

Now Neuron Wallet has bundled a CKB Mainnet node and configured to connect to the CKB Mainnet. After installation, as you open the Neuron Wallet, the bundled Mainnet node will run.

You can also run a CKB node yourself and launch Neuron wallet, then Neuron will NOT start the bundled node, but connects to your node instead. You may refer to Neuron Wallet Guide for more details.

CKB-Explorer

Github | Mirana Mainnet | Pudge Testnet

CKB-Explorer allows you to explore addresses, tokens, blocks, hashrate, Nervos DAO info and all other activities taking place on Nervos CKB.

Please note that CKB-Explorer is not a wallet service provider. We do not store your private keys and we have no control over the transactions that take place over the CKB Network.

Nervos Pudge Faucet

Github | Link

Nervos Pudge Faucet is where you can claim free Testnet CKBytes to use while developing and testing. You may claim 50,000 CKB from the faucet once every 24 hours on Testnet Pudge.

- + \ No newline at end of file diff --git a/docs/essays/ckb-core-dev/index.html b/docs/essays/ckb-core-dev/index.html index 6123982bf..a76e79d7f 100644 --- a/docs/essays/ckb-core-dev/index.html +++ b/docs/essays/ckb-core-dev/index.html @@ -14,7 +14,7 @@ Tips for CKB Development | Nervos CKB - + @@ -22,8 +22,8 @@

Tips for CKB Development

Nervos CKB is the layer 1 of Nervos Network, a public/permissionless blockchain, which is an open source project on github. There are some tips for ckb development below, hope it will be useful for you.

Molecule

We have developed a particular serialization format called Molecule.It is recommended to check the molecule github repo for more details.

Well-known Hashes

The command ckb list-hashes prints the well-known hashes for current effective chain spec.

The file docs/hashes.toml in ckb release package and source code repository contains the well-known hashes for all the bundled chain specs. The file is -generated by:

cargo run list-hashes -b > docs/hashes.toml

Running Test

Install dependencies

rustup component add rustfmt
rustup component add clippy

Run tests

make ci

Run acceptance integration tests

make integration

Debug CKB

Note: Only support linux system.

Track Memory Usage in Logs

Add the follow configuration into ckb.toml:

[logger]
filter = "error,ckb-memory-tracker=trace"

[memory_tracker]
# Seconds between checking the process, 0 is disable, default is 0.
interval = 600

Profile Memory

  • Compile ckb with feature profiling.

    make build-for-profiling

    After compiling, a script named jeprof will be generated in target direcotry.

    find target/ -name "jeprof"
  • Enable RPC module Debug in ckb.toml.

    [rpc]
    modules = ["Debug"]
  • Run ckb.

  • Dump memory usage to a file via call RPC jemalloc_profiling_dump.

    curl -H 'content-type: application/json' -d '{ "id": 2, "jsonrpc": "2.0", "method": "jemalloc_profiling_dump", "params": [] }' http://localhost:8114

    Then, a file named ckb-jeprof.$TIMESTAMP.heap will be generated in the working directory of the running ckb.

  • Generate a PDF of the call graph.

    Required: graphviz and ghostscript

    jeprof --show_bytes --pdf target/debug/ckb ckb-jeprof.$TIMESTAMP.heap > call-graph.pdf

References

- +generated by:

cargo run list-hashes -b > docs/hashes.toml

Running Test

Install dependencies

rustup component add rustfmt
rustup component add clippy

Run tests

make ci

Run acceptance integration tests

make integration

Debug CKB

Note: Only support linux system.

Track Memory Usage in Logs

Add the follow configuration into ckb.toml:

[logger]
filter = "error,ckb-memory-tracker=trace"

[memory_tracker]
# Seconds between checking the process, 0 is disable, default is 0.
interval = 600

Profile Memory

  • Compile ckb with feature profiling.

    make build-for-profiling

    After compiling, a script named jeprof will be generated in target directory.

    find target/ -name "jeprof"
  • Enable RPC module Debug in ckb.toml.

    [rpc]
    modules = ["Debug"]
  • Run ckb.

  • Dump memory usage to a file via call RPC jemalloc_profiling_dump.

    curl -H 'content-type: application/json' -d '{ "id": 2, "jsonrpc": "2.0", "method": "jemalloc_profiling_dump", "params": [] }' http://localhost:8114

    Then, a file named ckb-jeprof.$TIMESTAMP.heap will be generated in the working directory of the running ckb.

  • Generate a PDF of the call graph.

    Required: graphviz and ghostscript

    jeprof --show_bytes --pdf target/debug/ckb ckb-jeprof.$TIMESTAMP.heap > call-graph.pdf

References

+ \ No newline at end of file diff --git a/docs/essays/debug/index.html b/docs/essays/debug/index.html index 0e13bffdc..2b6d52a4a 100644 --- a/docs/essays/debug/index.html +++ b/docs/essays/debug/index.html @@ -14,13 +14,13 @@ Tips for Debugging CKB Script | Nervos CKB - +

Tips for Debugging CKB Script

CKB uses RISC-V ISA to implement VM layer and CKB VM is very different from other VMs with hard-code functionality through opcodes. Given the generalized nature of CKB VM, various languages and toolchains can be supported- every language and toolchain will be a bit different and implementers should provide appropriate documentation and support for the community.

This document introduces several tips about debugging CKB scripts.

Error codes

The CKB node only reports an exit code on transaction verification failure; the most straightforward way to distinguish errors is to use a different exit code (between -128 and 127) to represent errors.

For example, see the default lock script error codes: secp256k1 error codes

A common mistake is mixing up lock script errors and type script errors. It is recommended that remove the type script, then run again; if the error still exists, you can make sure the error is being caused by the lock script; otherwise, it is caused by the type script.

Debug syscall

When we want to output additional information from the script; we need use the debug syscall.

By default, the CKB node does not output the debug syscall message, however ckb.toml can be configured to enable it.

[logger]
filter = "info,ckb-script=debug"

You can also choose to run the script under a debugging environment like ckb-cli, VM debugger, or ckb-contract-tool.

For language / toolchain developers, it is recommended that integrate debug syscall to print the error backtrace if the language supports it.

Rust and ckb-std

Rust developers who use the ckb-std crate can utilize the debug macro.

debug!("there is a universal error caused by {}", 42);

This macro triggers the debug syscall in Rust's debug build profile. In the release build profile, it does nothing. To debug the release build, append the --cfg debug_assertions arguments to cargo build. For users of Capsule, the debug macro can be enabled in the release build by running capsule build --release --debug-output.

ckb-cli

ckb-cli supports to generate mock transactions and verification under the debugging environment.

1. Generate mock-tx template

ckb-cli mock-tx template --lock-arg <your lock-arg> --output-file debug-tx.json

2. Modify the template

Add your script cell to the cell_deps and modify the transaction structure to use a lock script or type script.

3. Complete the template

ckb-cli mock-tx complete --tx-file debug-tx.json

This command is used to sign the transaction with the private key according to your lock arg.

4. Verify the transaction

ckb-cli mock-tx verify --tx-file debug-tx.json

You will see the verification result and the debug output.

Please refer to the transaction RFC for constructing a transaction.

Using VM debugger and GDB

1. Install ckb-standalone-debugger

git clone https://github.com/nervosnetwork/ckb-standalone-debugger
cd ckb-standalone-debugger/bins
cargo build --release

2. Start standalone debugger

ckb-standalone-debugger supports a ckb-cli generated template. To debug a script, we indicate the script group type with -g <script type> . This indicates the script group we want to debug with the referenced -h <script hash>.

ckb-debugger -l 0.0.0.0:2000 -g type -h <type script hash> -t debug-tx.json

3. Start GDB

docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:bionic-20191012 bash
# start gdb
riscv64-unknown-elf-gdb <path of script binary>
# connect to debugger server
target remote <ip>:2000

You may refer to the tutorial: introduction to CKB script programming for more details.

Report bugs

When you find security-related bugs in script, please don't post them on public issues. Instead, try to contact maintainers privately, they can be found on the CKB dev telegram. Responsible disclosure could help maintainers, as well as prevent users from losing funds.

When you find security-related bugs in CKB official scripts or CKB VM, join the bug bounty program to be rewarded for your valuable contribution!

- + \ No newline at end of file diff --git a/docs/essays/dependencies/index.html b/docs/essays/dependencies/index.html index fec88a5b6..12ffc01e1 100644 --- a/docs/essays/dependencies/index.html +++ b/docs/essays/dependencies/index.html @@ -14,13 +14,13 @@ Script Dependencies | Nervos CKB - +

Script Dependencies

Deploy a VM and run code on the VM

Since we are working with a virtualized mini computer in CKB VM, there’s nothing stopping us from embedding another VM as a CKB script that runs on CKB VM and in this article we will explore this VM on top of VM path.

Through this method, we can have JavaScript on CKB via duktape, Ruby on CKB via mruby, we can even have Bitcoin Script or EVM on chain if we just compile those VMs and store them as scripts on CKB. This compatibility ensures CKB VM can both help to preserve legacy code and build a diversified ecosystem.

All languages should are treated equal on CKB, giving freedom to blockchain contract developers to build on top of CKB however they feel is best.

To use duktape on CKB, first you need to compile duktape itself into a RISC-V executable binary:

$ git clone https://github.com/xxuejie/ckb-duktape
$ cd ckb-duktape
$ git submodule init
$ git submodule update
$ sudo docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:xenial bash
root@0d31cad7a539:~# cd /code
root@0d31cad7a539:/code# make
riscv64-unknown-elf-gcc -Os -DCKB_NO_MMU -D__riscv_soft_float -D__riscv_float_abi_soft -Iduktape -Ic -Wall -Werror c/entry.c -c -o build/entry.o
riscv64-unknown-elf-gcc -Os -DCKB_NO_MMU -D__riscv_soft_float -D__riscv_float_abi_soft -Iduktape -Ic -Wall -Werror duktape/duktape.c -c -o build/duktape.o
riscv64-unknown-elf-gcc build/entry.o build/duktape.o -o build/duktape -lm -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-s
root@0d31cad7a539:/code# exit
exit
$ ls build/duktape
build/duktape*

Here we use the ruby SDK to interact with CKB, please refer to the official README for how to set it up. Then deploy the duktape script code in a CKB cell:

pry(main)> data = File.read("../ckb-duktape/build/duktape")
pry(main)> duktape_data.bytesize
=> 269064
pry(main)> duktape_tx_hash = wallet.send_capacity(wallet.address, CKB::Utils.byte_to_shannon(280000), CKB::Utils.bin_to_hex(duktape_data))
pry(main)> duktape_data_hash = CKB::Blake2b.hexdigest(duktape_data)
pry(main)> duktape_cell_dep = CKB::Types::CellDep.new(out_point: CKB::Types::OutPoint.new(tx_hash: duktape_tx_hash, index: 0))

The duktape script code now requires one argument: the JavaScript source you want to execute

pry(main)> duktape_hello_type_script = CKB::Types::Script.new(code_hash: duktape_data_hash, args: CKB::Utils.bin_to_hex("CKB.debug(\"I'm running in JS!\")"))

Notice that with a different argument, you can create a different duktape powered type script for a different use case:

pry(main)> duktape_hello_type_script = CKB::Types::Script.new(code_hash: duktape_data_hash, args: CKB::Utils.bin_to_hex("var a = 1;\nvar b = a + 2;"))

This echoes the differences mentioned above on script code vs script: here duktape serves as script code providing a JavaScript engine, while a different script leveraging duktape script code serves a different function on chain.

Now we can create a cell with the duktape type script attached:

pry(main)> tx = wallet.generate_tx(wallet2.address, CKB::Utils.byte_to_shannon(200))
pry(main)> tx.cell_deps.push(duktape_out_point.dup)
pry(main)> tx.outputs.type = duktape_hello_type_script.dup
pry(main)> tx.witnesses[0] = "0x"
pry(main)> tx = tx.sign(wallet.key, api.compute_transaction_hash(tx))
pry(main)> api.send_transaction(tx)
=> "0x2e4d3aab4284bc52fc6f07df66e7c8fc0e236916b8a8b8417abb2a2c60824028"

We can see that the script executes successfully and if you have the ckb-script module’s log level set to debug in your ckb.toml file, you will also notice the following log:

2019-07-15 05:59:13.551 +00:00 http.worker8 DEBUG ckb-script  script group: c35b9fed5fc0dd6eaef5a918cd7a4e4b77ea93398bece4d4572b67a474874641 DEBUG OUTPUT: I'm running in JS!

Now you have successfully deployed a JavaScript engine on CKB, and have also run JavaScript-based script on CKB! Feel free to try any JavaScript code you want here.

Dynamic linking

There are two dynamic linking functions implemented in nervosnetwork/ckb-c-stdlib, which are ckb_dlopen() and ckb_dlsym().

ckb_dlopen() loads the dynamic library from a cell by its data hash and returns an opaque "handle" for the dynamic library. ckb_dlsym() takes a "handle" of a dynamic library returned by ckb_dlopen() and the symbol name, and returns the address where that symbol is loaded into memory.

nervosnetwork/ckb-miscellaneous-scripts has a simple example for using these two functions.

int ckb_dlopen(const uint8_t *dep_cell_data_hash, uint8_t *aligned_addr,
size_t aligned_size, void **handle, size_t *consumed_size);

void *ckb_dlsym(void *handle, const char *symbol);

How dependencies work

There are two different dependency fields in the transaction data structure: cell_deps and header_deps.

cell_deps allow scripts in the transaction to access (read-only) referenced live cells.

header_deps allow scripts in the transaction to access (read-only) data of referenced past block headers of the blockchain.

Please refer to the CKB Transaction Structure RFC for more details.

- + \ No newline at end of file diff --git a/docs/essays/developer-materials-guide/index.html b/docs/essays/developer-materials-guide/index.html index 1ea9682e4..966514516 100644 --- a/docs/essays/developer-materials-guide/index.html +++ b/docs/essays/developer-materials-guide/index.html @@ -14,13 +14,13 @@ Developer Materials Guide | Nervos CKB - +

Developer Materials Guide

This guide will help introduce new developers to the essential topics and tools needed to get started.

Section 1: Introduction and Absolute Basics

These materials are for participants who are brand new, or need a refresher on the basics of what makes Nervos a unique and powerful alternative to the existing blockchain smart contract platforms.

We recommend all new developers review these materials to get a high-level conceptual understanding of how Nervos works.

More In-Depth Materials (Optional)

These materials cover similar topics to the recommended materials, but are much more in-depth. Reading these is optional.

Section 2: Developer Concepts

Learn the unique concepts and design patterns that developers will need to understand to create Dapps on Nervos.

These materials are recommended for all developers who want to develop Dapps or Smart Contracts on Nervos.

Available When You Need Them (Optional)

These materials are much more in-depth, but only relevant for specific topics. We recommend reviewing them only as needed.

Section 3: Developer Tooling

Learn about the tools that are available for developing on Nervos.

These are the recommended tools for developing on Nervos CKB.

Available When You Need Them (Optional)

Testnet Funds

When building on the Aggron Testnet, free testnet CKB can be obtained from this faucet.

Section 4: Sample Projects

View functioning example smart contract scripts and Dapps.

Example Scripts

These are smart contract scripts written in C and Rust. For most developers we recommend building scripts in Rust.

Example Dapps

These are fully functioning Dapps which were built using our recommended tooling.

Recommendations for setting up your development environment and which technologies to build your application with.

These are the minimum software recommendations for any developer building on Nervos CKB.

These are the recommended software stacks for any team building on Nervos CKB. These selections are based on current industry trends and the tooling available today.

- + \ No newline at end of file diff --git a/docs/essays/faq/index.html b/docs/essays/faq/index.html index 7312fbc6f..f583fd0a8 100644 --- a/docs/essays/faq/index.html +++ b/docs/essays/faq/index.html @@ -14,7 +14,7 @@ CKB FAQs | Nervos CKB - + @@ -22,7 +22,7 @@

CKB FAQs

How do you allocate transaction fees to the committer and proposer?

one transaction fee is F Shannon, poposer will get

floor(F * 4 / 10)

and committer will get

F - floor(F * 4 / 10)

We should allocate each transaction fee separately, instead of summing all transaction fees and then allocating to the committer and proposer.


What is the RPC send_transaction Outputs Validator?

Outputs validator prevents improperly formed transactions from entering the tx-pool, in most cases, the main reason for the client to send these transactions is simply due to error codes or abuse of the SDK, which makes the transactions unlockable.

Implementation details

CKB provides two built-in validators: default and passthrough.

For default validator, these checks should conform to the pseudocode described below

transaction.outputs.all{ |output|
script = output.script
(script.code_hash == secp256k1_blake160_sighash_all && script.hash_type == "type" && script.args.size == 20) ||
(script.code_hash == secp256k1_blake160_multisig_all && script.hash_type == "type" && (script.args.size == 20 || (script.args.size == 28 && script.args[20..28].is_valid_since_format))
}
transaction.outputs.all{ |output|
script = output.type
script.is_null || script.code_hash == dao && script.hash_type == "type"
}

For passthrough validator, it will skip validation.


How the primary and secondary epoch reward is allocated among blocks?

Let's suppose that the epoch reward is R, and the epoch length is L. The start block number of the epoch is S.

M = R mod L

For block from S (inclusively) to S + M (exclusively), the reward is

floor(R / L) + 1

And for block from S + M (inclusively) to S + L (exclusively), the reward is

floor(R / L)

How do you calculate transaction fee?

Let's start with a brief introduction to Transaction Weight.

Transaction Weight

The miners select transactions to fill the limited block space which gives the highest fee. Because there are two different limits, serialized size and consumed cycles, the selection algorithm is a multi-dimensional knapsack problem. Introducing the Transaction weight converts the multi-dimensional knapsack to a typical knapsack problem.

/// Equal to MAX_BLOCK_BYTES / MAX_BLOCK_CYCLES, see [glossary](https://docs.nervos.org/docs/basics/glossary).
pub const BYTES_PER_CYCLES: f64 = 0.000_170_571_4_f64;

get_transaction_weight(tx_size: usize, cycles: u64) -> u64 {
max(
tx_size as u64,
(cycles as f64 * BYTES_PER_CYCLES) as u64,
)
}

Estimate cycles

The cycles of the transaction can be obtained via rpc estimate_cycles

Here depends on the type of transaction to be built, if the transaction consists of small cycles of scripts, you can disregard cycles and directly replace weight with tx_size to calculate the transaction fee

(tx_size + 4) * fee_rate / 1000

If the transaction consists of large cycles of script, then you need to include cycles in the calculation of the fee, otherwise the fee rate of the transaction will not meet the expectations, of course, it also depends on the scenario, if the priority of the transaction confirm does not need so precise control, you can also directly use a rough estimate of the cycles, or do not consider cycles can also be, according to your own needs trade-offs.

Estimate FeeRate

Normally, you can just use the majority of the default values, which is min_fee_rate, but when network congestion occurs, if you want the confirmation time of the transaction to be manageable, then you need to focus on fee rate of the on-chain transaction, through get_fee_rate_statics rpc can get the statistics of the fee rate of confirmed transactions on the chain in the recent history, you can use it according to your needs, for example, directly using the mean of the rates of the transactions in the last 21 blocks, or if you want to reduce the confirmation time even further, you can use the mean * 1.2.

Transaction Fee

The size of a normal two-in-two-out transaction is 597 bytes, to calculate transaction fee we need to add extra 4 bytes size due to the cost of serialized tx in a block.

get_transaction_weight(tx_size + 4, cycles) * fee_rate / 1000

Let's suppose that we use 1000 shannons/KB as fee_rate(how many shannons per KB charge),3_600_000 as cycles, the transaction weight is max((597 + 4), 3_600_000 * 0.000_170_571_4), 614.05704, the transaction fee is 614.05704 * 1000 / 1000, approximately 615 shannons (0.00000615 CKB).


What is the min_fee_rate?

CKB Node operator can set the value called min_fee_rate in ckb.toml to decide ignore txs with lower fees than min_fee_rate.

  • send_transaction RPC will not accept txs which fee lower than min_fee_rate
  • The node will stop to relay txs with lower fee than min_fee_rate

The default value of min_fee_rate is 1000.

min_fee_rate = 1_000 # shannons/KB

Which mean a tx need at least (tx_size + 4) * 1000 / 1000 shannons as the tx fee. min_fee_rate is used for cheap check threshold, so cycles are not considered in the calculation, this is different from when fee rate is used as a transaction processing priority.

NOTICE: Even though you can set min_fee_rate lower than the default value, other nodes in the network may still use the default value, which may cause the tx you accept still can't be relayed to other nodes, unless your node is also a miner or mining pool so that you can mine those txs by yourself.


Can you estimate transaction fee?

The CKB node supports to estimate transaction fee, you can open the Experiment in ckb.toml RPC modules to use the feature. For more details, you may refer to estimate_fee_rate


What is compact_target in the block header?

compact_target is the encoded form of the target threshold which appears in the block header.

It is similar to nBits of bitcoin, the original nBits implementation inherits properties from a signed data class,if the high bit of the effective number of bits is set, the target threshold will be negative. This is useless—the header hash is considered as an unsigned number, so it can never be equal to or lower than a negative target threshold.

In CKB, the "compact" format is represented a whole number N using an unsigned 32bit number,which is similar to a floating-point format.

  • The most significant 8 bits are the unsigned exponent of base 256.
  • The exponent can be considered as "number of bytes of N".
  • The lower 24 bits are the mantissa.
N = mantissa * 256^(exponent-3)

There are example and test vectors in Python 3, you may refer here for more details :

import unittest

def compact_to_target(compact):
exponent = compact >> 24
mantissa = compact & 0x00ffffff
rtn = 0
if (exponent <= 3):
mantissa >>= (8 * (3 - exponent))
rtn = mantissa
else:
rtn = mantissa
rtn <<= (8 * (exponent - 3))
overflow = mantissa != 0 and (exponent > 32)
return rtn, overflow


def target_to_compact(target):
bits = (target).bit_length()
exponent = ((bits + 7) // 8)
compact = target << (
8 * (3 - exponent)) if exponent <= 3 else (target >> (8 * (exponent - 3)))
compact = (compact | (exponent << 24))
return compact


class TestCompactTarget(unittest.TestCase):

def test_compact_target1(self):
compact = target_to_compact(0x2)
self.assertEqual('0x1020000', hex(compact))
target, overflow = compact_to_target(0x1020000)
self.assertTupleEqual((2, False), (target, overflow))

def test_compact_target2(self):
compact = target_to_compact(0xfe)
self.assertEqual('0x1fe0000', hex(compact))
target, overflow = compact_to_target(0x1fedcba)
self.assertTupleEqual((0xfe, False), (target, overflow))


if __name__ == '__main__':
unittest.main()


How do you set the value of capacity in a Cell?

The field capacity in a cell must be larger than or equal to cell's own occupied capacity. The minimal occupied capacity of a secp256k1 cell is 61 bytes.

occupied(cell: Cell) = sum of
- capacity: 8 bytes
- data: len(data) bytes
- lock: occupied(lock: Script)
- type:
- when present: occupied(type: Script)
- when absent: 0 bytes

occupied(script: Script) = sum of:
- args: len(args) bytes
- code\_hash: 32 bytes
- hash\_type: 1 byte

There is a demo in JavaScript:

function hex_data_occupied_bytes(hex_string) {
// Exclude 0x prefix, and every 2 hex digits are one byte
return (hex_string.length - 2) / 2;
}

function script_occupied_bytes(script) {
if (script !== undefined && script !== null) {
return (
1 + hex_data_occupied_bytes(script.code_hash) +
hex_data_occupied_bytes(script.args)
);
}
return 0;
}

function cell_occupied_bytes(cell) {
return (
8 +
hex_data_occupied_bytes(cell.data) +
script_occupied_bytes(cell.lock) +
script_occupied_bytes(cell.type)
);
}

There is the test case:

console.log(
cell_occupied_bytes({
capacity: "4500000000",
data: "0x72796c6169",
lock: {
args: "0x",
hash_type: "data",
code_hash:
"0xb35557e7e9854206f7bc13e3c3a7fa4cf8892c84a09237fb0aab40aab3771eee"
},
type: null
})
);
// => 46

How do you use the RPC subscription?

RPC subscriptions require a full duplex connection. CKB provides this kind of connection by tcp (enable with rpc.tcp_listen_address configuration option) and websockets (enable with rpc.ws_listen_address).

tcp rpc subscription example:

telnet localhost 18114
> {"id": 2, "jsonrpc": "2.0", "method": "subscribe", "params": ["new_tip_header"]}
< {"jsonrpc":"2.0","result":0,"id":2}
< {"jsonrpc":"2.0","method":"subscribe","params":{"result":"...block header json...","subscription":0}}
< {"jsonrpc":"2.0","method":"subscribe","params":{"result":"...block header json...","subscription":0}}
< ...
> {"id": 2, "jsonrpc": "2.0", "method": "unsubscribe", "params": [0]}
< {"jsonrpc":"2.0","result":true,"id":2}

websocket rpc subscription example:

let socket = new WebSocket("ws://localhost:28114")

socket.onmessage = function(event) {
console.log(`Data received from server: ${event.data}`);
}

socket.send(`{"id": 2, "jsonrpc": "2.0", "method": "subscribe", "params": ["new_tip_header"]}`)

socket.send(`{"id": 2, "jsonrpc": "2.0", "method": "unsubscribe", "params": [0]}`)

What are the special live cells in CKB?

There are some special live cells deployed in Testnet.

duktape VM (JavaScript) cell

The VM cell is deployed in transaction 0xff4893d8054a365e505074c1d0ee2cc13e72dd9be4c0487fe7a48478f075b036 output index 0. We should put the out_point in cell_deps, looks like:

{
"out_point": {
"tx_hash": "0xff4893d8054a365e505074c1d0ee2cc13e72dd9be4c0487fe7a48478f075b036",
"index": "0x0"
},
"dep_type": "code"
}

And your type script may use this VM like:

{
"code_hash": "0xfb8e791d70c4622ae0bd0127ee9597aea612e42929e725f7f3f25475bb954ce9",
"hash_type": "data",
"args": "0x<your javascript code in hex>",
}

There is an example transaction using duktape VM. If your logger(in ckb.toml) filter is set to filter = "info,ckb-script=debug" , you will see a log:

DEBUG ckb-script  script group: Byte32(0xafe527276275a4a25defee32ed59ecebf4813256866a7577431e5293acd2048b) DEBUG OUTPUT: I'm running in JS!

If you want to deploy the duktape VM cell by yourself, please refer to this article.

mruby VM (Ruby)cell

The VM cell is deployed in transaction 0x1850f997f867b6d3f1154444498a15e9fc4ce080215e34d0c41b33349bcc119a output index 0. We should put the out_point in cell_deps, looks like:

{
"out_point": {
"tx_hash": "0x1850f997f867b6d3f1154444498a15e9fc4ce080215e34d0c41b33349bcc119a",
"index": "0x0"
},
"dep_type": "code"
}

And your type script may use this VM like:

{
"code_hash": "0xc3815b09286d825574f672bf4e04566ae6daaf1b45f3f1bcfd20c720198652ec",
"hash_type": "data",
"args": "0x<your ruby code in hex>",
}

If you want to deploy the mruby VM (Ruby)cell by yourself, you may follow these instructions below

  • Step 1, build the mruby binary:
$ git clone --recursive https://github.com/nervosnetwork/ckb-mruby
$ cd ckb-mruby
$ sudo docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:bionic-20191012 bash
root@982d1e906b76:/# apt-get update
root@982d1e906b76:/# apt-get install -y ruby
root@982d1e906b76:/# cd /code
root@982d1e906b76:/code# make
root@982d1e906b76:/code# exit
  • Step 2, deploy the binary via create a cell with the binary data:
$ ckb-cli wallet transfer --from-account <from-account> --to-address <to-address> --capacity 462000 --to-data-path build/entry --tx-fee 0.01
0x1850f997f867b6d3f1154444498a15e9fc4ce080215e34d0c41b33349bcc119a
  • Step 3, query the data hash of the binary:
$ ckb-cli rpc get_live_cell --tx-hash 0x1850f997f867b6d3f1154444498a15e9fc4ce080215e34d0c41b33349bcc119a --index 0 --with-data

How do you estimate the timestamp in CKB?

In CKB, based on the deterministic state of the chain,there is no way to know which block a transaction will be packaged into, and there is no way to get an accurate time,so we can estimate the timestamp like this:

median of previous 37 block timpstamp < timestamp <= local_time + 15s

What gotchas should you pay attention to in Nervos DAO?

Due to CKB's unique flexibility, it also comes with some gotchas to be aware of. Otherwise there might be risk locking your cell forever with no way to unlock them. Here, we try our best to document the gotchas we know:

  • Nervos DAO only supports absolute epoch number as since value when withdrawing from Nervos DAO. So if you are using a lock that supports lock period, such as the system included multi-sign script, please make sure to ONLY use absolute epoch number as lock period. Otherwise the locked Nervos DAO cell cannot be spent.
- + \ No newline at end of file diff --git a/docs/essays/integrity-check/index.html b/docs/essays/integrity-check/index.html index be3652065..43da6b78d 100644 --- a/docs/essays/integrity-check/index.html +++ b/docs/essays/integrity-check/index.html @@ -14,7 +14,7 @@ Integrity Check for CKB Release | Nervos CKB - + @@ -22,7 +22,7 @@

Integrity Check for CKB Release

All the binaries in CKB releases are signed via following PGP keys.

VersionPackageUnique IDOpenPGP KeyFingerprint
>= 0.13.0macOS, Linux, CentOSNervos Travis Builder bot@nervos.orgF4631C0A64B7 05B5 6078 1FC5 4047 7B82 4F37 F694 F463 1C0A
>= 0.14.0WindowsNervos Azure Builder bot@nervos.orgAD748F260849 A2D2 4CA7 CFFC FA80 BCD4 5EBA 64EC AD74 8F26

You can import the public keys from the keyserver network:

gpg --recv-keys 4F37F694F4631C0A 5EBA64ECAD748F26

Once you have already imported the public keys, please download both the archive and the corresponding .asc file to verify the signature. For example, to check the signature of the file ckb_v0.13.0_x86_64-apple-darwin.zip

gpg --verify ckb_v0.13.0_x86_64-apple-darwin.zip.asc ckb_v0.13.0_x86_64-apple-darwin.zip

Note: Please never use a GnuPG version just downloaded to check the integrity of the source — use an existing, trusted GnuPG installation, e.g., the one provided by your distribution.

If the output of the above command is similar to the following, it means that you do not have our public key or the signature was generated by someone else, so you should handle the file suspiciously.

gpg: Signature made Wed 05 Jun 2019 10:12:22 PM UTC using RSA key ID F4631C0A
gpg: Can't check signature: No public key

If you get this result:

gpg: Signature made Wed 05 Jun 2019 10:12:22 PM UTC using RSA key ID F4631C0A
gpg: Good signature from "Nervos Travis Builder <bot@nervos.org>"
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: 64B7 05B5 6078 1FC5 4047 7B82 4F37 F694 F463 1C0A

then you have a copy of our keys and the signatures are valid, but you have not marked the keys as trusted or the keys are a forgery. In this case, at the very least, you should compare the fingerprints that are shown above.

Ideally, you'll get result like:

gpg: Signature made Wed 05 Jun 2019 10:12:22 PM UTC using RSA key ID F4631C0A
gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2023-06-05
gpg: Good signature from "Nervos Travis Builder <bot@nervos.org>"
- + \ No newline at end of file diff --git a/docs/essays/introduction/index.html b/docs/essays/introduction/index.html index 5edd8669d..333e4a707 100644 --- a/docs/essays/introduction/index.html +++ b/docs/essays/introduction/index.html @@ -14,13 +14,13 @@ Introduction | Nervos CKB - +

Introduction

Essays provide a place for all developers to write independent articles. The articles here, don't need a unified theme. Each article might contain quite different topic, including:

  • How transaction verification works in CKB
  • How one can sign a proper CKB transaction
  • How molecule works
  • How one can debug a buggy CKB script
  • How polyjuice (Ethereum compatible layer) works on CKB.
  • FAQs about CKB
  • Some tips for CKB development

We welcome all developers to share their insights in the CKB platform here. No matter if you have some insights to share with us, or if you are just curious about some aspects of CKB and want to learn about it, don't hesitate to let us know!

- + \ No newline at end of file diff --git a/docs/essays/lifecycle/index.html b/docs/essays/lifecycle/index.html index 46e1df0c4..16d7ee6df 100644 --- a/docs/essays/lifecycle/index.html +++ b/docs/essays/lifecycle/index.html @@ -14,7 +14,7 @@ Transaction Validation Lifecycle | Nervos CKB - + @@ -24,7 +24,7 @@ self.as_slice().len() + molecule::NUMBER_SIZE // molecule::NUMBER_SIZE = size_of::<u32>() 4 }
  • inputs are not empty
    1. inputs().is_empty() || outputs().is_empty()
  • inputs are mature
    1. For each input and dep, if the referenced output transaction is a cellbase, it must have at least 4 epoch confirmations
  • capacity
    1. sum of inputs’ capacity must less than or equal to outputs’ capacity
  • duplicate_deps
    1. deps should not be duplicated
  • outputs_data_verifier
    1. number of ‘output data' fields must equal number of outputs
  • since
    1. ‘since’ value must follow the rules described in https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0017-tx-valid-since/0017-tx-valid-since.md
  • Then CKB VM will execute the transaction script and output the number of cycles consumed.

    Broadcast to the network

    If the verification is successful, the current node broadcasts the transaction (with cycles value) to all of its connected peer nodes.

    If verification fails, the transaction is not broadcasted anymore. The transaction flows through various “full nodes”, which repeat the verification process described in the previous step, and check that the cycles value matches the actual cycles consumed when the transaction is verified.

    Tx-pool (mempool)

    CKB uses a two-step process for transaction confirmation. Transactions will be divided into different status (pending and proposed) in the tx-pool. The status of transactions will change when a block is added to the blockchain. When the latest block changes, all transactions in the tx-pool will be re-scanned to ensure they are still valid.

    BlockAssembler will fetch proposals and transactions from the pending pool and proposed pool for block template.

    More information about this two-step transaction confirmation process can be found here.

    Tx-pool Two-Step Transaction Confirmation

    Since CKB v0.101, the tx-pool will not run the two-step transaction confirmation mechanism for non-miner nodes, i.e. nodes that are not configured with block assembler, and the status of the transaction will not be displayed when the transaction is fetched via rpc.

    - + \ No newline at end of file diff --git a/docs/essays/mint-sudt-via-contract/index.html b/docs/essays/mint-sudt-via-contract/index.html index f249024dc..a4efe831a 100644 --- a/docs/essays/mint-sudt-via-contract/index.html +++ b/docs/essays/mint-sudt-via-contract/index.html @@ -14,7 +14,7 @@ Mint SUDT via Contract | Nervos CKB - + @@ -26,7 +26,7 @@ When someone relays a spv proof which indicates he locks some token into the bridge contract on ETH, we mint the mirror token(we can name it cETH) on CKB.

    We will need 3 scripts here:

    • A eth-bridge-typescript to handle the spv proof verification logic.
    • A eth-bridge-lockscript to be used as SUDT typescript args and delegate the verify logic to eth-bridge typescript.
    • A SUDT typescript which represents cETH.

    The transaction structure which mints cETH is like below:

    Inputs:
    eth-bridge-cell:
    Type:
    code: eth-bridge-typescript
    args: id
    Lock:
    code: eth-bridge-lockscript
    args: eth-bridge-typescript-code-hash
    Data:
    eth_light_client_data
    records: [(block_hash, tx_index)]
    provide-capacity-cell
    Type: None
    Lock: <User Lockscript>
    Outputs:
    eth-bridge-cell:
    Type:
    code: eth-bridge-typescript
    args: id
    Lock:
    code: eth-bridge-lockscript
    args: eth-bridge-typescript-code-hash
    Data:
    eth_light_client_data
    records: [(block_hash, tx_index)]
    cETH-token-cell:
    Type:
    code: SUDT-typescript
    args: eth-bridge-lockscript-hash
    Lock:
    <User Lockscript>
    Data: amount
    Witnesses:
    0: eth-spv-proof
    1: signature to unlock provide-capacity-cell

    The scripts verify logics below:

    • eth-bridge-typescript
      • ensure the spv proof in associated witness is valid
      • ensure the handled spv proof is recorded in the cell data to avoid using a single proof to mint cETH multiple times.
      • ensure the ETH amount locked on Ethereum equals the amount of cETH we mint
    • eth-bridge-lockscript
      • ensure the associated eth-bridge-typescript represents in outputs, then we know the typescript script will be run in the transaction, it makes the logic delegation work

    But we encountered a new problem. We need the eth-bridge-typescript hash as the eth-bridge-lockscript args, then the eth-bridge-lockscript hash as SUDT-typescript args, but we need to know the cETH token script to check the token amount in eth-bridge-typescript. It we locate cETH token typescript by it's script hash, there will be a cycle dependency.

    We can use load_lockscript_hash in eth-bridge-typescript and then check the entire script (which includes code_hash, args and type) part by part instead of cETH token script hash.

    The pseudocode is like below:

    let lockscript_hash = load_lockscript_hash(0, Source::Output);
    for script in load_output_typescripts {
    if script.args = lockscript_hash \
    && script.code_hash = SUDT_CODE_HASH \
    && script.type = 0 {
    // This is a cETH token cell
    }
    }

    You can check the complete demo here. The test file shows how to construct a mint transaction using this pattern.

    - + \ No newline at end of file diff --git a/docs/essays/polyjuice/index.html b/docs/essays/polyjuice/index.html index 24f592638..eb1a16326 100644 --- a/docs/essays/polyjuice/index.html +++ b/docs/essays/polyjuice/index.html @@ -14,7 +14,7 @@ Technical Bits on Polyjuice | Nervos CKB - + @@ -22,8 +22,8 @@

    Technical Bits on Polyjuice

    Polyjuice is an Ethereum compatible layer and has implemented most of the functions of Ethereum on CKB, including running an EVM contract on CKB-VM. We believe that we have achieved full-featured compatibility with the implementation of EVM,which is also the power of CKB-VM.By polyjuice we want to showcase that it is perfectly possible to use account model on Nervos CKB. The flexibility here actually enables countless opportunities.

    Basic Concepts

    Account

    There are two kinds of accounts, contract account, and EoA account.

    Contract Account

    The contract account in Polyjuice is a cell constrained by Polyjuice type script. The type script args is a type_id value so that the type script is unique. The first 32 bytes of the cell data is the storage root (sparse-merkle-tree) of the contract. The second 32 bytes of the cell data is the code_hash (blake2b(code)) of the contract. Since we want everyone to use the contract, we default the use of an always success lock script. We can also use any lock script for access control or other purposes.

    EoA Account

    The EoA account in Polyjuice is all live cells locked by default secp256k1 sighash lock script. The id of the account is the lock script args.

    Contract

    A contract in Polyjuice is mostly the same as an ethereum contract. You can write your contract in Solidity, Vyper, or Assembly, then compile to EVM byte code. There are some minor differences. Since it's impossible to read block information from the current block, we instead read block information from the most recent block. The most recent means the latest block of blocks includes the transaction inputs:

    max(block_number(inputs))

    It will effect following op codes:

    • BLOCKHASH
    • COINBASE
    • TIMESTAMP
    • NUMBER
    • DIFFICULTY
    • GASLIMIT

    The DIFFICULTY value is the difficulty of Nervos CKB chain. The GASLIMIT here is a constant value, which equals the max value of int64_t (9223372036854775807). The transaction cost is determined by its size and cycles, so gas limit is meaningless in Polyjuice.

    The COINBASE return value and SELFDESTRUCT beneficiary address are the first 20 bytes of lock script hash, which is:

    blake2b(lock_script)[0..20]

    Program

    A program is a CREATE or CALL with parameters. Since polyjuice supports contract call contract, a polyjuice transaction can contain multiple programs, which will be serialized and put into witness.

    Generator

    Polyjuice generator can generate a Polyjuice transaction through JSONRPC API as below:

    fn create(sender: H160, code: Bytes) -> TransactionReceipt;
    fn call(sender: H160, contract_address: H160, input: Bytes) -> TransactionReceipt;

    Validator

    Polyjuice validator is the type script that verifies the transformation of contract cells.

    Indexer

    Indexer is a Polyjuice module for indexing every Polyjuice transaction in CKB block. The contract metadata, alteration, and all the logs emitted from the Polyjuice transaction will be saved. Also, all live cells will be indexed for running the generator (build Polyjuice transaction).

    Design Details

    How to organize cells in a CKB transaction?

    If the picture is not clear, please click: Organize cells in a CKB transaction

    The CKB transaction generation process

    If the picture is not clear, please click: CKB transaction generation process

    The CKB transaction validation process

    If the picture is not clear, please click: -CKB transaction validation process

    Communicate through ckb-vm syscalls

    In Generator and Indexer, we use syscalls to handle the event emitted from the program execution process. The syscalls we currently used are shown below:

    • 2177 is for ckb_debug, useful when you want to debug the generator.
    • 3075 is for returning the EVM result.
    • 3076 is for logging.
    • 3077 is for saving SELFDESTRUCT beneficiary address.
    • 3078 is for handle CALL and CREATE opcodes.
    • 3079 is for returning code size of a contract to EVM.
    • 3080 is for returning a coded slice of a contract to EVM.

    Implementation Details

    How to handle contract creation?

    A CREATE from a sender (EoA account) or contract will lead to contract creation. In generator, the created cell will be assigned a type_id type script, and the contract code hash will be saved in the data field next to the account storage root hash. In validator, type script will check the contract code hash match the code_hash in the data field.

    How to handle contract destruction?

    Contract destruction only happens when a SELFDESTRUCT opcode is executed. In the generator, the destructed contract cell is consumed as input, then put an output cell as the beneficiary cell, and the beneficiary address is the corresponding secp256k1 sighash lock script.

    How to generate a contract call contract CKB transaction?

    When CALL or CREATE opcode is invoked in EVM, we call it a contract call contract transaction. When invoking CALL opcode, generator load contract code and latest storage from the database or saved state (the contract has already been loaded from database) by destination and execute it. When CREATE opcode executed after EVM started, the generator will put an output cell just like how contract creation works.

    How to validate contract call contract CKB transaction?

    The first contract created or called by EoA account we call it entrance contract, other contracts if there is any, we call them normal contracts. Only one program is allowed in the entrance contract, and all its calls to normal contracts' programs must match the order and count. All normal contracts' calls to sub normal contracts' programs must check they match the request. Since multiple contracts may call one contract, the count can not be checked by a normal contract. Normal contracts only check their own programs, and the entrance contract will check all programs in current CKB transaction that are being called with the restricted sequence.

    How to verify the contract sender (EoA account)?

    Since EVM execution will use the sender information, we require the sender to sign the Polyjuice transaction and put the signature into witness. The sign content must include two parts:

    1. transaction hash
    2. all contracts' related witnesses

    The contract-related witness is serialized as part of the WitnessArgs molecule structure, and the information is located in input_type (contract call/destruction) field or output_type (contract creation) field.

    How to handle logs?

    In validator, the logs are just being ignored. When the generator generates the Polyjuice transaction, the logs are saved and returned as part of the transaction receipt. When the Indexer processes the Polyjuice transaction, the logs are saved to the database for users to query.

    In generator and Indexer the logs are trigged by LOG opcode, then:

    1. callback function emit_log is called
    2. emit_log invoke a log syscall with topics and data as arguments
    3. Rust syscall handler function is called, the arguments been extracted and saved
    - +CKB transaction validation process

    Communicate through ckb-vm syscalls

    In Generator and Indexer, we use syscalls to handle the event emitted from the program execution process. The syscalls we currently used are shown below:

    • 2177 is for ckb_debug, useful when you want to debug the generator.
    • 3075 is for returning the EVM result.
    • 3076 is for logging.
    • 3077 is for saving SELFDESTRUCT beneficiary address.
    • 3078 is for handle CALL and CREATE opcodes.
    • 3079 is for returning code size of a contract to EVM.
    • 3080 is for returning a coded slice of a contract to EVM.

    Implementation Details

    How to handle contract creation?

    A CREATE from a sender (EoA account) or contract will lead to contract creation. In generator, the created cell will be assigned a type_id type script, and the contract code hash will be saved in the data field next to the account storage root hash. In validator, type script will check the contract code hash match the code_hash in the data field.

    How to handle contract destruction?

    Contract destruction only happens when a SELFDESTRUCT opcode is executed. In the generator, the destructed contract cell is consumed as input, then put an output cell as the beneficiary cell, and the beneficiary address is the corresponding secp256k1 sighash lock script.

    How to generate a contract call contract CKB transaction?

    When CALL or CREATE opcode is invoked in EVM, we call it a contract call contract transaction. When invoking CALL opcode, generator load contract code and latest storage from the database or saved state (the contract has already been loaded from database) by destination and execute it. When CREATE opcode executed after EVM started, the generator will put an output cell just like how contract creation works.

    How to validate contract call contract CKB transaction?

    The first contract created or called by EoA account we call it entrance contract, other contracts if there is any, we call them normal contracts. Only one program is allowed in the entrance contract, and all its calls to normal contracts' programs must match the order and count. All normal contracts' calls to sub normal contracts' programs must check they match the request. Since multiple contracts may call one contract, the count can not be checked by a normal contract. Normal contracts only check their own programs, and the entrance contract will check all programs in current CKB transaction that are being called with the restricted sequence.

    How to verify the contract sender (EoA account)?

    Since EVM execution will use the sender information, we require the sender to sign the Polyjuice transaction and put the signature into witness. The sign content must include two parts:

    1. transaction hash
    2. all contracts' related witnesses

    The contract-related witness is serialized as part of the WitnessArgs molecule structure, and the information is located in input_type (contract call/destruction) field or output_type (contract creation) field.

    How to handle logs?

    In validator, the logs are just being ignored. When the generator generates the Polyjuice transaction, the logs are saved and returned as part of the transaction receipt. When the Indexer processes the Polyjuice transaction, the logs are saved to the database for users to query.

    In generator and Indexer the logs are triggered by LOG opcode, then:

    1. callback function emit_log is called
    2. emit_log invoke a log syscall with topics and data as arguments
    3. Rust syscall handler function is called, the arguments been extracted and saved
    + \ No newline at end of file diff --git a/docs/essays/pprof/index.html b/docs/essays/pprof/index.html index 13b558a45..1bd5ff71d 100644 --- a/docs/essays/pprof/index.html +++ b/docs/essays/pprof/index.html @@ -14,13 +14,13 @@ Tips for Profiling CKB Script | Nervos CKB - +

    Tips for Profiling CKB Script

    Before starting, make sure you have understood the concept of cycles.

    In the development phase of dapps, it is a wide range of needs to estimate how many cycles our dapp will consume.

    ckb-vm-pprof is a tool for visualization and analysis of profiling data. It can run a script off-chain and then collect the runtime data. According to your preference, It can generate both text and graphical reports.

    Get ckb-vm-pprof

    $ git clone https://github.com/nervosnetwork/ckb-vm-pprof
    $ cd ckb-vm-pprof
    $ cargo build --release

    The executable file is located at ./target/release/ckb-vm-pprof, you can copy it to any $PATH you like.

    Basic usage

    Suppose the program to be tested is:

    int fib(int n) {
    if (n == 0 || n == 1) {
    return n;
    } else {
    return fib(n-1) + fib(n-2);
    }
    }

    int main() {
    if (fib(10) != 55) {
    return 1;
    }
    return 0;
    }

    The Fibonacci function is used in the example because it is not only simple enough, but also a recursive function.

    Build with -g option

    -g option, described in the gcc documentation as:

    -g
    Produce debugging information in the operating system’s native format (stabs, COFF, XCOFF, or DWARF). GDB can work with this debugging information.

    On most systems that use stabs format, -g enables use of extra debugging information that only GDB can use; this extra information makes debugging work better in GDB but probably makes other debuggers crash or refuse to read the program. If you want to control for certain whether to generate the extra information, use -gstabs+, -gstabs, -gxcoff+, -gxcoff, or -gvms (see below).

    It is necessary to bring it when compiling, so the compilation command is:

    $ riscv64-unknown-elf-gcc -g -o fib fib.c

    Install visualization package

    If you only need a text report, you can ignore this step.

    $ cargo install inferno

    Inferno is a port of parts of the flamegraph toolkit to Rust, with the aim of improving the performance of the original flamegraph tools.

    Get reports

    We just need to use ckb-vm-pprof to run the binary fib:

    $ ckb-vm-pprof --bin fib > flamegraph.txt

    $ cat flamegraph.txt
    ??:?? 938
    ??:??; /src/ckb-vm-pprof/res/fib.c:main 24
    ??:??; /src/ckb-vm-pprof/res/fib.c:main; /src/ckb-vm-pprof/res/fib.c:fib 7311

    The basic format of the text report is Function0; Function1; ... FunctionN Cycles, that is, the call stack and the final cycles. ??:?? means that some codes that does not belong to any user defined function(usually generated by the compiler).

    Generate graphics for easy reading:

    $ cat flamegraph.txt | inferno-flamegraph > fib.svg

    fib.svg

    Please note that the function with too small proportion will not be displayed on the flamegraph by default.

    - + \ No newline at end of file diff --git a/docs/essays/pw-lock/index.html b/docs/essays/pw-lock/index.html index 339498ab1..80b25cab9 100644 --- a/docs/essays/pw-lock/index.html +++ b/docs/essays/pw-lock/index.html @@ -14,13 +14,13 @@ Introduction of PW-lock | Nervos CKB - +

    Introduction of PW-lock

    Overview

    PW-lock, developed by the lay2 Team, is a lock script which can make use of other blockchain wallets as CKB wallets. PW-lock is based on the concept of implementing the signature verification algorithms of other chains (e.g. ETH/TRON/EOS/BTC) so as to reuse others' facilities. Also, PW-lock is a lock with ACP logic.

    Current PW-lock supports the Ethereum EIP-191 signature verification standard. It is possible to communicate with MetaMask, an Ethereum wallet, through the RPC personal_sign, and sign the hash_all message, then verify the transaction in the PW-lock script before unlocking.

    Quick Start

    https://github.com/lay2dev/pw-lock.git
    cd pw-lock
    git submodule init
    git submodule update
    make install-tools
    make all-via-docker
    cargo test --all

    PW-lock Basic Structure

    - pw-lock-script:
    - code_hash: 32 bytes - pw-lock script code hash
    - hash_type: 1 byte - pw-lock script hash_type
    - args: 20 bytes - public key hash. e.g. ETH address
    - witness(current version):
    - lock: 65 bytes - secp256k1 signature_data

    Offchain

    The lay2 team has developed the PW-core, a front-end JS SDK based on Typescript, to interwork with PW-lock. Some additional supports may be required if working in a non-JavaScript environment.

    In addition to the ACP unlock method, PW-lock also supports the similar unlock of the CKB secp256k1 lock P2PKH signature verification. The difference is that the current version of pw-lock uses a slightly different hash algorithm to that of secp256k1_blake160.

    // pw-lock
    Keccak(Blake2b(Tx) | witness)

    // secp256k1-lock
    Blake2b(Blake2b(Tx) | witness)

    Features In Development

    Add support for chains other than ETH, such as EOS, TRON, BITCOIN, DOGECOIN, etc. in the upcoming pw-lock.

    Reference

    - + \ No newline at end of file diff --git a/docs/essays/rfcs/index.html b/docs/essays/rfcs/index.html index ca05b531a..ea80b1306 100644 --- a/docs/essays/rfcs/index.html +++ b/docs/essays/rfcs/index.html @@ -14,13 +14,13 @@ A Tour of RFCs | Nervos CKB - +

    A Tour of RFCs

    The Nervos Network is made up of a number of protocols and innovations. It's important to have clear documentation and technical specifications on key protocol design and implementations - for which we utilize an RFC (request for comment) process which is intended to provide an open and community driven path for new protocols, improvements and best practices.

    This tour provides short introduction on our RFCs and links, hope it will be helpful for you to round out your journey to Nervos Network. There are two categories of RFCs:

    • Informational - Anything related to Nervos network.

    • Standards Track - RFC that is intended to be standard followed by protocols, clients and applications in Nervos Network.

    Informational

    The Nervos Network Positioning Paper

    This document provides a high-level walkthrough of all parts of the Nervos Network, with a focus on how they work together to support the overall vision of the network.

    Nervos CKB: A Common Knowledge Base for Crypto-Economy

    This is Nervos CKB whitepaper, provides an overview of the Nervos Common Knowledge Base (CKB), a public permissionless blockchain and layer 1 of Nervos.

    CKB-VM

    This RFC introduces CKB-VM (CKB-Virtual Machine) which is a RISC-V instruction set based VM for executing smart contracts on Nervos CKB, written in Rust. There is a user defined token(UDT) issuing process used as an example to demenstrate the implementation of CKB-VM.

    Privileged architecture support for CKB VM

    This RFC introduces privileged architecture support for CKB VM. While CKB VM doesn't require a privileged model since it only runs one contract at a time, privileged model can help bring MMU support.

    Crypto-Economics of the Nervos Common Knowledge Base

    This RFC introduces the crypto-economics of Nervos CKB. Nervos CKB is the base layer of the overall Nervos Network which is a preservation focused, "Store of Assets" blockchain. Economically, it's designed to provide sustainable security and decentralization.

    Data Structures

    This RFC explains all the basic data structures used in CKB, includes Cell, Script, Transaction and Block.

    CKB Consensus Protocol

    This is Nervos CKB consensue paper. The CKB consensus protocol is a variant of NC that raises its performance limit and selfish mining resistance while keeping its merits.

    CKB Transaction Structure

    This RFC is about an essential data structure in CKB, the transaction, contains two parts, the first one covers the core transaction features and the second one introduces some extensions.

    Standards Track

    CKB Block Synchronization Protocol

    Block synchronization must be performed in stages with Bitcoin Headers First style. Block is downloaded in parts in each stage and is validated using the obtained parts.

    Merkle Tree for Static Data

    CKB uses Complete Binary Merkle Tree(CBMT) to generate Merkle Root and Merkle Proof for a static list of items.

    P2P Scoring System And Network Security

    This RFC describes the scoring system of CKB P2P Networking layer and several networking security strategies based on it.

    Serialization

    This RFC introduces two major serialization formats, Molecule and JSON, used in CKB.

    VM Syscalls

    This RFC describes all the RISC-V VM syscalls implemented in CKB so far.CKB VM syscalls are used to implement communications between the RISC-V based CKB VM, and the main CKB process, allowing scripts running in the VM to read current transaction information as well as general blockchain information from CKB.

    Eaglesong (Proof-of-Work Function for Nervos CKB)

    This RFC specifies the Eaglesong hash function as it is to be used in the context of Nervos CKB proof-of-work.

    Transaction Filter

    Transaction filter protocol allows peers to reduce the amount of transaction data they send which is to allow low-capacity peers to maintain a high-security assurance about the up to date state of some particular transactions of the chain or verify the execution of transactions.

    Node Discovery

    This RFC introduces the CKB Node Discovery.It mainly refers to Satoshi Client Node Discovery. The differences between them are summarized below:

    • The node version number is included in the GetNodes message.
    • The Nodes message is used to periodically broadcast all nodes currently connected.
    • We use multiaddr as the format of node addresses (It MUST NOT include /p2p/ segment otherwise it's considered as misbehavior and a low score SHOULD be given.)

    Block Template

    This RFC describes the decentralized CKB mining protocol which is to improve the security of the CKB network by making blocks decentralized.

    VM Cycle Limits

    This RFC describes cycle limits used to regulate VM scripts.CKB VM is a flexible VM that is free to implement many control flow constructs. We need to enforce certain rules in CKB VM to prevent malicious scripts, such as a script with infinite loops.

    Transaction valid since

    This RFC introduces a new consensus rule to prevent a cell to be spent before a certain block timestamp or a block number by adding a new u64 type field: since in the transaction input.

    CKB Address Format

    This RFC introduces how to implement CKB Address Format which is an application level cell lock script display recommendation.CKB address packages lock script into a single line, verifiable, and human read friendly format.

    Deposit and Withdraw in Nervos DAO

    This RFC describes deposit and withdraw transaction in Nervos DAO. Nervos DAO is a smart contract and one function of Nervos DAO is to provide an dilution counter-measure for CKByte holders. Please pay attention to Common Gotchas which including common and very important points you should be aware to use Nervos DAO well without losing CKBs.

    - + \ No newline at end of file diff --git a/docs/essays/rules/index.html b/docs/essays/rules/index.html index 4c5e5f2df..2cdecdfcb 100644 --- a/docs/essays/rules/index.html +++ b/docs/essays/rules/index.html @@ -14,13 +14,13 @@ CKB VM Verification Rules | Nervos CKB - +

    CKB VM Verification Rules

    When writing a program, it is important to determine the operating environment and runtime behavior, so that the execution structure of the program is in line with the program’s intended behavior. For example: the impact of GIL (Global Interpreter Lock) in Python, the expected execution time of hardware instructions and pipeline planning, etc.

    We all know that CKB VM is a virtual environment based on the RISC-V instruction set. In addition to this, developers should also know the context of the VM during CKB verification, including some syscalls provided, etc. This article will provide more information about the operation of CKB VM.

    Environment

    In CKB, each transaction is executed separately, that is, each transaction runs in its own separate VM environment. Though parallel verification of multiple transactions is performed (by the host), there is no multi-threaded execution environment inside of the VM.

    Execution unit

    When each individual transaction is verified, the scripts will first be separated into groups and then executed sequentially in units of script groups. Each group is created by grouping together transactions that have the same script hash.

    Note that the lock scripts of transaction outputs are not executed during transaction verification.

    No matter which script group is being executed, the entirety of transaction data can be accessed by scripts included in that transaction during execution.

    An advantage of this design is the group records the index of the cell(s) which belong to the current group. This is equivalent to combining multiple verifications that may exist into one verification. This reduces verification resource consumption and provides a public environment for the data set of the transaction. But this requires the developer to be aware when writing the script that it needs to consider the case of validating multiple cells.

    This is described here:

    `class ScriptGroup:
    def __init__(self, script):
    self.script = script
    self.input_indices = []
    self.output_indices = []

    def split_group(tx):
    lock_groups: Dict[Hash, ScriptGroup] = dict()
    type_groups: Dict[Hash, ScriptGroup] = dict()
    for index, input in enumerate(tx.inputs):
    if lock_groups.get(hash(input.lock)):
    lock_groups.get(hash(input.lock)).input_indices.append(index)
    else:
    script_group = ScriptGroup(input.lock)
    script_group.input_indices.append(index)
    lock_groups[hash(input.lock)] = script_group
    if input.type:
    if type_groups.get(hash(input.type)):
    type_groups.get(hash(input.type)).input_indices.append(index)
    else:
    script_group = ScriptGroup(input.type)
    script_group.input_indices.append(index)
    type_groups[hash(input.type)] = script_group
    for index, output in enumerate(tx.outputs):
    if output.type:
    if type_groups.get(hash(input.type)):
    type_groups.get(hash(input.type)).output_indices.append(index)
    else:
    script_group = ScriptGroup(input.type)
    script_group.output_indices.append(index)
    type_groups[hash(input.type)] = script_group
    return list(lock_groups.values()) + list(type_groups.values())

    def run():
    for group in split_group(tx):
    if vm_run(group) != 0:
    return error()
    `

    When each script group is executed, the execution cost of the scripts is recorded and the sum of all resource consumption is compared with the max_block_cycles allowed upper limit.

    Suppose there is a transaction as follows:

    `Transaction {
    input: [cell_1 {lock: A, type: B}, cell _2 {lock: A, type: B}, cell_3 {lock: C, type: None}]
    output: [cell_4 {lock: D, type: B}, cell_5 {lock: C, type: B}, cell_6 {lock: G, type: None}, cell_7(lock: A, type: F)]
    }`

    it will be grouped as such:

    `[
    group(A, input:[0, 1], output:[]),
    group(C, input:[2], output:[]),
    group(B, input:[0, 1], output:[0, 1]),
    group(F, input:[], output:[3])
    ]`

    The syscall of the VM can load these corresponding cells through group(input/output index) to complete one-time verification.

    CKB will execute all script groups, which are then verified based on return value. This follows the convention of process exit status in Unix-like systems: a return value of zero is a verification pass, while other return values are verification exceptions.

    Note that when the script is executed, the script itself does not know if it is a type or lock script. The script will need to figure this out itself, by checking args or witness data.

    Special rules

    Most of the contracts are verified as above, except for one type of contract, which is the TypeId contract. This contract employs special rules, written directly in the script code, and does not start the VM. For more information, see the code here and a tutorial about creation of TypeId contracts here.

    Sycall RFC

    Syscall system script (C code)

    - + \ No newline at end of file diff --git a/docs/essays/tx-confirmation/index.html b/docs/essays/tx-confirmation/index.html index 635a6475d..65343bdef 100644 --- a/docs/essays/tx-confirmation/index.html +++ b/docs/essays/tx-confirmation/index.html @@ -14,13 +14,13 @@ The Back-of-Envelope Calculation of the Transaction Confirmation Number | Nervos CKB - +

    The Back-of-Envelope Calculation of the Transaction Confirmation Number

    Think of the chain quality attack as a gambler's ruin problem. The attacker has an infinite number of coins, but the honest miners have σ\sigma, which is the transaction confirmation number. In each round, one player wins a coin, and the other loses a coin. The honest miner loses if there is no coin in his hands. The attacker never gives up—note that this assumption requires that the attacker controls less than a third of the total mining power.

    Now analysis of the gambler's ruin tells us the probability that the attacker wins the game is

    P(attacker wins)=(p1p)σ,{\rm P(attacker\ wins)}=(\frac{p}{1-p})^\sigma,

    where pp is the probability that the attacker wins a coin. If we consider the attacker as a selfish miner with perfect network propagation advantage, we have

    p=α+o1αo,p=\frac{\alpha+o}{1-\alpha-o} ,

    where α\alpha is the attacker's mining power share, oo is the proportion of orphaned blocks among all the blocks. See this paper for the rationale behind the above equation. Note that this orphan rate definition is slightly different from the orphan rate in the NC-Max paper. Now we have

    P(attacker wins)=(α+o12α2o)σ{\rm P(attacker\ wins)}=(\frac{\alpha+o}{1-2\alpha-2o})^\sigma

    If we assume o=0o=0 and σ=6\sigma=6 in Bitcoin, α=0.25\alpha=0.25 , to get the same probability that the attacker wins the game, we need to have

    (0.250.5)6=(0.25+o0.52o)σ,(\frac{0.25}{0.5})^6=(\frac{0.25+o}{0.5-2o})^\sigma ,

    so

    σ=log0.25+o0.52o0.015625.\sigma=\log_{\frac{0.25+o}{0.5-2o}}0.015625 .

    In Nervos CKB, when o=5%o=5\%, σ=14.4\sigma=14.4; when o=2.5%o=2.5\%, σ=8.4\sigma=8.4.

    If we assume, similar to Bitcoin, o=0o=0, σ=6\sigma=6, and α=0.3\alpha=0.3, to achieve the same level of security in Nervos CKB, when o=2.5%o=2.5\%, we have σ=23.29\sigma=23.29.

    If we assume, similar to Ethereum, o=6%o=6\%, σ=12\sigma=12, and α=0.25\alpha=0.25, to achieve the same level of security in Nervos CKB, when o=0.025%o=0.025\%, we have σ=4.96\sigma=4.96.

    In reality, oo can be estimated as 0=u200/(200+u200)0=u{200}/(200+u{200}), where u200u_{200} is the number of uncle blocks embedded in the last 200 main chain blocks. By definition σ\sigma cannot be smaller than 6; when σ>30\sigma>30, use 30 as an upper bound.

    - + \ No newline at end of file diff --git a/docs/essays/tx-pool/index.html b/docs/essays/tx-pool/index.html index 130a93506..6b7b836d5 100644 --- a/docs/essays/tx-pool/index.html +++ b/docs/essays/tx-pool/index.html @@ -14,13 +14,13 @@ Transaction Pool | Nervos CKB - +

    Transaction Pool

    Transaction Chaining

    In CKB, transactions are organized in chains, whereby one transaction spends or dep references the outputs of the previous transaction (known as the parent) and creates outputs for the subsequent transaction (known as the child).

    Orphan Transaction

    When a chain of transactions is transmitted across the network, they don’t always arrive in order. Sometimes, the child arrives before the parent. In that case, the nodes that see the child first can see the parent transaction it refers to, which is not yet known. Rather than rejecting the child, they put it in a temporary pool and await the arrival of its parent before propagating it to every other node. The pool of transactions without parents is known as the orphan transaction pool. Once the parent arrives, any orphans that reference the Cell created by the parents are released from the pool, revalidated recursively, then the entire chain of transactions can be included in the transaction pool, ready to be mined in a block.

    Two limits are set on the number of orphan transactions stored in memory, to prevent a denial-of-service attack against CKB nodes. They are defined as DEFAULT_MAX_ORPHAN_TRANSACTIONS and ORPHAN_TX_EXPIRE_TIME in the source code of the CKB client. If the number of orphan transactions in the pool exceeds DEFAULT_MAX_ORPHAN_TRANSACTIONS, one or more randomly selected orphan transactions are evicted, until the pool size is reduced within the limits. If the time of the orphan transactions remaining in the pool exceeds ORPHAN_TX_EXPIRE_TIME, the orphans will also be cleared.

    Transaction Weight

    Transaction weight is a measurement of the size and the cycles of a transaction. The calculation is as follows:

    const BYTES_PER_CYCLES: f64 = 0.000_170_571_4_f64;

    max(size, (cycles * BYTES_PER_CYCLES))

    Miners select transactions to fill the limited block space that awards the highest fee. Because of the two different limits, serialized size and consumed cycles, the selection algorithm is a multi-dimensional knapsack problem (MDKP). By introducing transaction weight, MDKP is reduced to a typical knapsack problem.

    For more details on max block size and cycles, see Consensus Parameters.

    Fee Rate

    Fee rate is the total transaction fees divided by the transaction weight.

    Transaction Prioritization

    When CKB generates a block template to package transactions, it sorts the transactions according to certain rules to ensure that:

    • Packaged transactions are topologically sorted, meaning that any parent of a transaction is also included. They must appear somewhere in the list before the transaction.
    • Packaged transactions should not conflict.

    On top of that, packages are designed for incentive-compatibility. Packaged transactions are not prioritized in terms of individual transactions, but rather in terms of transaction chains.

    Let's use an example to simply show the selection process when packaging a transaction. As illustrated below, there are two transaction chains: A and B.

    The transaction information in Chain A is as follows:

    • Ta1 fee: 10, weight: 10
    • Ta2 fee: 20, weight: 5
    • Ta3 fee: 10, weight: 10

    The transaction information in Chain B is as follows:

    • Tb1 fee: 15, weight: 10
    • Tb2 fee: 15, weight: 10
    • Tb3 fee: 15, weight: 10

    At this point we can obtain the fee rate of A as 1.6 (10 + 20 + 10) / (10 + 5 + 10) and that of B as 1.5 (15 + 15 + 15) / (10 + 10 + 10). This gives priority to the first transaction in Chain A, Ta1, even though the fee rate of Ta1 is lower than Tb1.

    After picking out Ta1, the fee rate of Chain A changes, and at this point we no longer count Ta1 in A. The overall fee rate of A changes to 2 (20 + 10) / (5 + 10). By the same reasoning, it can be shown that the next candidate is Ta2.

    Next, after Ta1 and Ta2 are picked out, A's fee rate changes to 1 (10 / 10), exceeded by B's fee rate. So the next candidate is not Ta3 but Tb1.

    The above is a brief description of the process of selecting a transaction for the block_template. The specific implementation of the algorithm also involves several other factors, such as size_limit, cycles_limit.

    Child-Pays-For-Parent (CPFP)

    In the case of a transaction sent with a small fee, it might be necessary to speed up the confirmation time for it to be considered settled. At this point, there is no way to directly increase the fee of the transaction itself. Instead, it is possible to create a new transaction that takes the unconfirmed transaction as its input, and spend it at a higher fee. Miners who want to benefit from this second, more profitable transaction will also need to confirm the first transaction. This is known as child-pays-for-parent (CPFP).

    - + \ No newline at end of file diff --git a/docs/essays/upgradability/index.html b/docs/essays/upgradability/index.html index 4d9dcc7a5..f9ab19518 100644 --- a/docs/essays/upgradability/index.html +++ b/docs/essays/upgradability/index.html @@ -14,7 +14,7 @@ Upgradable CKB Contracts—Why And How | Nervos CKB - + @@ -24,7 +24,7 @@ b. The index of the first output cell using the current type script;
  • Hash the two pieces of information gathered in 3 together, if the resulting hash matches args part in current type script structure, return with success. Otherwise, abort with a failure.
  • A C implementation and a Rust one are both available for this workflow.

    Attackers will be prevented from several different directions:

    1. If an attacker tries to create a cell with the exactly same type script, there will be two cases: a. A valid transaction will have different OutPoint data in the first input, or different output cell index from when we first created this cell; b. If the user tries to duplicate type script args as the first transaction input, CKB will signal a double-spent error;
    2. When the attacker tries to use a different type script args, it will be a different type script structure by definition.

    This way, we can ensure a cell will have unique type script across all live cells in CKB. Considering the fact that each type script structure can also be hashed, a cell in CKB can thus have a unique hash, or unique ID.

    Resolving Contracts in CKB Transaction

    The above newly designed smart contract will act as the core for building upgradable smart contracts. What's still missing here, is a clever use of CKB's contract resolving process:

    • CKB first extracts code hash, and hash type value from the lock/type script structure to run. To avoid ambiguity, we will denote code hash gathered here as running code hash, and hash type as running hash type.
    • For each dep cell in the current transaction, a test hash value will be calculated. Depending on the value of running hash type, there will be different ways to calculate test hash:
      • If running hash type is type, test hash will be the hash of type script data structure from the dep cell;
      • Otherwise, test hash will be the hash of cell data part from the dep cell;
    • CKB then looks for a dep cell whose test hash matches running code hash. In the absence of such a cell, CKB results in a validation error.
    • CKB uses the cell data from the located dep cell as the smart contract to run.

    Upgradability of smart contract has to do with ways to reference a changeable cell containing different smart contracts. In the upgrade process, the OutPoint structure for a cell will change (updating a cell is essentially destroying the old cell, then creating a new one), the cell data will also change (since we will need to store the fixed smart contract). Then what property can stay unchanged? In CKB's universe, lock and type script can definitely stay the same when updating a cell. Since lock script is typically used to represent ownership, we can perfectly use type script here to reference an upgradable smart contract.

    Putting Everything Together

    There's still one problem unsolved, a potential attack remains. Consider this:

    • A lock script L1 is stored in a cell C1 with type script T1;
    • Alice guards her cells via a lock script L1 using hash type as type. By definition, she fills her script structure's code hash field with the hash of type script T1;
    • Bob creates a different cell C2 with the always-success lock script L2, and also use the same type script T1;
    • Now Bob can use C2 as a dep cell to unlock Alice's cell. CKB won't be able to distinguish that Alice wants to use C1, while Bob provides C2. Both C1 and C2 use T1 as type script.

    That teaches us a very important lesson: if you build a lock/type script and want people to leverage the upgradability property, you have to make sure to use a cell with an unique and unforgeable type script in CKB universe.

    Luckily, we just solved this problem! In the above we just developed a smart contract ensuring type script uniqueness in CKB universe. Putting together, upgradable smart contracts in CKB can be archived by combining the very smart contract developed above, with CKB's ability to resolve contracts via type scripts.

    Trust Issue

    We do want to mention that this design is not without its drawbacks. You should really understand how it works and the tradeoffs involved before using it. This section tries to discuss some known considerations related to this feature.

    Determinism Property A

    Type ID does provide a solution to challenges with regards to Determinism Property A: when a bug is discovered, it's possible to fix the smart contracts without affecting existing cells using the same smart contracts. But it does require certain considerations.

    Ownership

    With a type ID solution, people might be able to steal your coin by hacking the cell containing smart contracts you use. Since typical cells are guarded by one or more signatures, some human errors could cause major problems. Fundamentally, it's a tradeoff situation:

    1. For those truly paranoid, they might want to stick to the old way of referencing a script via its own hash, not the type script hash of the containing cell. The "code is law" principle is fully enforced here. You will know exactly what can be used to unlock your cell, and it won't change anytime in the future.
    2. For people willing to sacrifice a little bit, they can gain the ability to upgrade existing smart contracts for different benefits. But please do make sure to fully understand the lock script of the cell containing the script you use.

    For example, if you look at the deployed system scripts in CKB's mainnet, they all use type ID setup, but have all their lock scripts’ code hash set to zeros, meaning that no one gets to change the lock script easily via a signature. We want to make sure that there's a need to change the default lock script, which will be realized via a fork agreed upon by the whole community. After all, IMHO, it really is the whole Nervos community that owns CKB :P

    There are some initial ideas that you can use to guard the script contained in a cell. For example, in addition to type ID logic, the type script can also contains other logics to validate the actual script contained in its cell. For example, formal analysis methods might be used, or certain test cases can be provided in which the type script runs the actual script against. Only when the analysis or the test cases pass, will one be able to change script contained in a cell. Though I must say, these are just some preliminary ideas, much research and development work needs to be done to make this a reality.

    Availability

    A different issue with type ID, is the availability of the script. When you have a cell using a script with hash type set as data, you are not worried someone might destroy the used script, you can always redeploy the script on-chain then unlock your cell.

    But with a type ID solution, if something bad happens, and the cell with matching type script hash is destroyed, your cell will be locked forever, since you might never be able to build a cell with the same type script hash. There are some methods you can use, such as restricting the ability to destroy a cell with a type ID script, but they all just mitigate the problem, not completely solving it.

    Determinism Property B

    We do want to mention that type ID does not provide a solution to property B. When you have a signed transaction, the behavior of this transaction won't be changed with the upgrade of one smart contract.

    Though there is way that the type ID solution might affect an already signed transaction: If a transaction uses a script from a cell that gets updated, the cell referenced in the original OutPoint is already spent and the transaction will become invalid. But it could be argued that with the old referencing solution, this problem might also occur.

    Conclusion

    The above design of upgradable smart contracts has already seen wide usage in mainnet CKB now. Feel free to let us know your thoughts on this feature :)

    - + \ No newline at end of file diff --git a/docs/essays/workflow/index.html b/docs/essays/workflow/index.html index c4ac2488f..3ada64570 100644 --- a/docs/essays/workflow/index.html +++ b/docs/essays/workflow/index.html @@ -14,13 +14,13 @@ The General Workflow for Constructing a Transaction | Nervos CKB - +

    The General Workflow for Constructing a Transaction

    This document will explain how to build a verifiable transaction on CKB in the simplest and most common way possible. It doesn't involve constructing validation scripts, contracts, etc.

    On CKB, any transaction must have at least one input and one output. To construct a transaction, the first thing that is needed is a way to effectively locate an input and this process is referred to as “cell collect”.

    Cell Collect

    It is important to first understood that CKB’s cell model is very similar to the UTXO model, which means that without any pre-caching it is not possible to know the current state of any address. The information that makes up the current state of an address may be scattered across different cells in many corners of the blockchain and a cell collection method is a prerequisite to properly using CKB. The cell model of CKB is described in detail in Cell.

    Let’s take a look at how to collect cells, as there are two ways to do this:

    Using the CKB Indexer Service

    This section introduces a simple method which can identify limited information about a specified address (such as live_cell count, transaction count, total capacity). However, this method is based on the CKB node’s indexing function and is only suitable for simple usage (it also consumes resources of the CKB node).

    This method also is not capable of cell collection according to more detailed search criteria. For example, locating a contract cell is not possible with this method.

    Regardless of these shortcomings, let's start with this method to better understand how cell collection works. By default, this feature is turned off in the CKB node. To turn it on, manually change the configuration file as outlined below and restart the CKB node.

    Locate the following configuration in the ckb.toml file

    [rpc]
    ...
    # List of API modules: ["Net", "Pool", "Miner", "Chain", "Stats", "Subscription", "Indexer", "Experiment"]
    modules = ["Net", "Pool", "Miner", "Chain", "Stats", "Subscription", "Experiment"]

    In the configuration above, the indexing service is not started. To turn this feature on, add “Indexer” to the array.

    modules = ["Net", "Pool", "Miner", "Chain", "Stats", "Subscription", "Experiment", "Indexer"]

    After restarting the CKB node with ckb run -C <path>, register the address you want to index through the RPC method [index_lock_hash](https://github.com/nervosnetwork/ckb/blob/master/rpc/README.md#index_lock_hash).

    Note that the index_from parameter controls the point that indexing starts from: a null value begins indexing from the current chain tip (current latest block), while a value of 0 begins indexing from the genesis block.

    Wait for the index service to be rebuilt, then use the RPC interface of the indexing service to view the live_cell/transaction/capacity values of the corresponding address. You may refer to the JSON-RPC.

    To turn the indexing service off, follow this process: unregister the watch list through RPC, shut down the service and remove the “Indexer” value from the array in the ckb.toml file.

    Creating Your Own Cell Collection Service

    What are the advantages to creating your own cell collection service?

    We all know that a transaction includes the creation and destruction of cells (this is the simplest definition of a CKB transaction). However, due to flexibility of the cell model, any kind of meaningful data can be stored in cell data fields and various types of contracts can be expressed through type scripts. As a result, each user or use case may have different requirements for cell collection.

    There are many questions to explore, each may have a different answer depending on use case:

    • What is the order of cell consumption? first-in-first-out, size order, best fit model, etc.
    • What kind of cell can be consumed? a specific type or any kind?
    • Does any cell data or cell type require special treatment?
    • Is any filtering/confirmation required after cells are selected?

    The indexing service that comes with the CKB node does not address these requirements and cannot be configured to include additional requirements that may be needed in the future. The most effective approach to cell collection is to build the functionality yourself.

    How to build cell collection

    As a new block is added to the chain, the cells used as inputs to the block must be removed from the live cell set and the outputs created by the block must be added into the live cell set.

    We know that short forks are always possible in PoW blockchains. When a fork negates the effects of a previously accepted block, the input and output changes from that block must be rolled back. A cache design may help to speed up synchronization, for example, caching the last n blocks in the chain and removing the live cells consumed in these blocks.

    Constructing a Transaction

    Now that we have covered cell collection, we can start the process of constructing a transaction. There are a series of concepts that need to be explained, including the construction of witnesses, the calculation of transaction fees and the use of some small tricks. Refer to RFC0022 - Transaction Structure for more detailed information.

    All types are serialized based on the molecule serialization system, the core struct is:

    table RawTransaction {
    version: Uint32,
    cell_deps: CellDepVec,
    header_deps: Byte32Vec,
    inputs: CellInputVec,
    outputs: CellOutputVec,
    outputs_data: BytesVec,
    }

    table Transaction {
    raw: RawTransaction,
    witnesses: BytesVec,
    }

    cell_deps and inputs are a series of pointers to live cells on the chain. The difference is that cell_deps are a reference (read-only) and inputs are consumed in the transaction. The index struct for these transaction inputs is:

    struct OutPoint {
    tx_hash: Byte32,
    index: Uint32,
    }

    struct CellDep {
    out_point: OutPoint,
    dep_type: byte,
    }

    tx_hash and index are used to locate cells (a reference to the transaction that created them and the index number the cell appeared in the outputs). The cell_dep has an extra dep_type field, which is used to express whether the data in the cell is code or dep_group. Code stored in multiple cells can be combined using the dep_group functionality.

    For dep_type:

    • Use value of 0 to indicate code, meaning that the cell data can be used directly

    • Use value of 1 to indicate a dep group, which means that the data in this cell is a redirect field (recursion is not allowed here). The referred dep group data uses vector OutPointVec <OutPoint> to list all needed outpoints.

    An example of dep_group usage: the default lock cell uses dep group functionality to divide the secp256k1 library into two cells to store the multiplication table and code. This is needed because block size is limited, if total dep data is too large to fit in one block, it can be stored in multiple cells (added in separate transactions confirmed in separate blocks) and later can be loaded together at runtime through the dep_group functionality.

    outputs and outputs_data are two one-to-one lists. There is only capacity and type/lock script in the output. The output data is placed in the outputs_data corresponding to the index.

    The header_dep is a list of past block header hashes. Header data referenced in this list can be accessed by CKB scripts during execution.

    Now that the basics of the transaction structure have been explained, let's explore a slightly more complicated structure.

    script

    table Script {
    code_hash: Byte32,
    hash_type: byte,
    args: Bytes,
    }

    code_hash and hash_type are used to specify a lock cell, args are the parameters required by the lock script. The hash_type field has two possible values:

    • when it is "data" represented by 0, code_hash means lock cell's data hash
    • when it is "type" represented by 1, code_hash means lock cell's type script hash

    It is very easy to understand what will happen when a hash_type value of “code” is used, but what about a value of “type”? What does this mean for contract developers?

    When a value of “type” is used, the value that is specified is a cell type script hash. The default lock script of CKB is indexed by type. The dep cells of the transaction will be examined for a cell that has this value as its type script, and the data in that cell will be used as the code for type script execution.

    To see how this functionality can be used, we can take a look at the implementation of TypeID, which is used to refer to a cell by reference. You can see that the type script of the second output of the genesis block is a TypeID script. If your published library also binds this TypeID script, it will generate a unique id(code hash) for indexing the data. You can then update the content of this library without changing the typeid. Any contract that references this library (by the unique type script value) will still work even if the library is changed. This is a solution to update on-chain libraries.

    witness

    Now that all RawTransaction fields have been set, let's take a look at the witnesses field. This field ensures that the transaction cannot tamper with other transactions, and this field also allows inclusion of temporary variables that may be needed by the contract. It consists of a series of witnesses:

    table WitnessArgs {
    lock: BytesOpt, // Lock args
    input_type: BytesOpt, // Type args for input
    output_type: BytesOpt, // Type args for output
    }

    An input requires a witness for verification. However, including a witness for every input would be inefficient if multiple inputs used the same lockscript. When each individual transaction is verified, scripts will first be separated into groups (transactions with the same script hash will be grouped together) and then executed sequentially in units of script groups.

    This is equivalent to combining multiple script verifications into a single execution, reducing resource consumption and the size of witness data. This does however require the developer to be aware when writing the script that it should consider the case of validating multiple cells in this way.

    The witness is a signature on the blake2b-hash of the entire transaction, including tx_hash, length, and a zero-ed out placeholder for witness data (once the signature is generated it will be placed in this field). The specific signing process and the convention regading how the witnesses for different script groups are arranged can be found in this wiki.

    Format and Fee

    Through the above process, we have obtained a complete Transaction structure. At this time, to derive the absolute minimum fee that will be accepted by miners, we will need to do some backtesting (based on actual cycles consumed) and modification of the existing transaction.

    How to Estimate a Transaction Fee?

    The transaction fee is the sum of the size of the serialized transaction (molecule) and the sum of actual cycles consumed by executed instructions. The size unit is 1,000 shannons / KB (kilobyte) by default (shannon is 1/100,000,000 of CKByte).

    However, miners can modify this default unit. If you need to see the real-time transaction fee estimate, you can view it through RPC using estimate_fee_rate.

    If you want to use the lowest fee possible, you can continuously adjust the difference between the transaction’s input capacity and output capacity and regenerate the transaction until you are satisfied (using a binary search).

    - + \ No newline at end of file diff --git a/docs/integrate/introduction/index.html b/docs/integrate/introduction/index.html index d4a823750..efa23875d 100644 --- a/docs/integrate/introduction/index.html +++ b/docs/integrate/introduction/index.html @@ -14,7 +14,7 @@ Nervos CKB Mainnet - Integration Guide | Nervos CKB - + @@ -22,7 +22,7 @@

    Nervos CKB Mainnet - Integration Guide

    Connecting to the CKB network is extremely easy and only requires running one node on a machine. Once you've connected to the CKB network, you can use the RPC interface to interacting with the node.

    About Nervos CKB

    CKB is the layer 1 of Nervos Network, a public/permissionless blockchain. CKB uses Proof of Work and improved Nakamoto consensus to achieve maximized performance on average hardware and internet conditions without sacrificing decentralization and security, which are the core values of blockchain.

    Run A CKB Node

    You’ll need to deploy nodes to connect with the CKB network, read data from the blockchain, and broadcast transactions onto the CKB network. For more information, please see Run CKB With The Latest Release or Run CKB With Docker. You may also need an indexer to index live cells and transactions, and then you can try CKB Indexer. If you are looking for a one-stop solution that includes both node and indexer, you can try Perkins' Tent.

    Server Requirements

    • OS: Ubuntu 18.04 LTS x86_64 (recommended)
    • Processor: Mainstream CPU 4c
    • RAM: 4G
    • Storage: 100G SSD

    A Checklist for Integration

    Before starting your integration, we recommend reading CKB Transaction Structure RFC to familiarize yourself with an essential data structure in CKB. Some common issues and corresponding example solutions (using CKB SDK Java) are listed below.

    Generating and Parsing Address

    CKB Address Format is an application-level recommendation for cell lock script display. The lock script consists of three key parameters, including code_hash, hash_type, and args. CKB address packages lock script into a single line, verifiable, and human read friendly format.

    Transferring CKB

    The transmission of CKB between addresses is divided into three steps, constructing, signing, and submitting the transaction. You can use the following example to understand how to transfer CKB between addresses SingleSigWithCkbIndexerTxExample and TransferAllBalanceWithCkbIndexerExample. If you want to know the signing process, you can check How to sign the transaction. For the calculation of transaction fees, please see the Transaction Fee.

    For withdrawal, need to support both transfers to Short Payload Format Address and transfers to Full Payload Format.

    Retrieving data from node

    You can make a JSON-RPC request to your CKB node with the SDK. There are some CKB SDK Java examples: JSON-RPC Example. Commonly used RPC interfaces are

    How to manage cells(like UTXO set)

    Cell management mainly affects cell collection and address balance display. There are many ways to manage cells; Here are two typical example solutions.

    • Recommended: use CKB indexer to collect cells and display balance. Recommend using built-in version available since v0.106.0, standalone version is also available.
      • get_cells_capacity Returns the live cells total capacity by the lock or type script. You can use this RPC to display address balance.
    • Use your UTXO management framework to combine CKB JSON-RPC protocols to scan the entire CKB blockchain.

    CKB built-in indexer

    CKB

    Since v0.106.0, CKB has integrated the functions in previous standalone ckb-indexers. Users of v0.106.0 nodes or above have no need to start ckb-indexer service separately. Ckb-indexer-related RPC is included in the current RPC as a module. Users don't have to configure the indexer port separately.

    There are three ways to enable CKB built-in indexer:

    • Add the parameter --indexer to the command line to start CKB
    ckb run -C <path> --indexer
    • Add Indexer module in the RPC section of CKB config file. CKB built-in indexer will be enabled along with the node.
    [rpc]
    modules = [..., "Indexer"]
    • Add indexer_v2 section to the config file to configure the indexer. Since the indexer section was deprecated in the configuration file once before, the v2 suffix is added to avoid conflicts and to be compatible with older config files. Once the indexer section is configured, the CKB built-in indexer will be enabled along with the node.
    [indexer_v2]
    index_tx_pool = false

    These three methods do not mutually conflict. Users can choose based on their preferences. The third method supports advanced indexer configuration.

    Below listed the items to be configured:

    ItemsDescription
    store = <PATH>Indexer db directory. Configured as data/indexer/store by default.
    secondary_path = <PATH>Indexer directory for node data synchronization. Configured as data/indexer/secondary_path by default.
    poll_interval = 2Indexer data synchronization interval. Measured in second, 2s by default. Mainly used for testing. We recommended not to modify.
    index_tx_pool = boolWhether to create index for the unconfirmed transactions in tx_pool.
    db_background_jobs = 6Number of indexer db background job. 6 by default. We recommended not to modify.
    db_keep_log_file_num = 1Number of indexer db debug logs. 1 by default.

    Block_filter and cell_filter provide options to customize index rules via a simple Rhai script. Configured as below:

    block_filter = "block.header.number.to_uint() > "1000000".to_uint()"
    cell_filter = 'let script = output.lock; script.code_hash == "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8" && script.hash_type == "type" && script.args == "0xa897829e60ee4e3fb0e4abe65549ec4a5ddafad7"'

    Also note that the difference between the RPC of CKB built-in indexer and the RPC of the previous standalone ckb-indexer:

    • get_tip RPC in ckb-indexer is renamed to get_indexer_tip to avoid ambiguity.
    • get_indexer_info RPC is removed.

    Ckb-cli

    Ckb-cli requires v1.2.0 or higher to support CKB built-in indexer.

    Specifying ckb-indexer-url is no longer necessary.

    Ckb-sdk

    Go SDK

    Importing Go SDK is no longer necessary.

    All previous method calls are switched from indexerClient to CKB client as follows:

    //import [github.com/nervosnetwork/ckb-sdk-go/indexer](http://github.com/nervosnetwork/ckb-sdk-go/indexer)
    import github.com/nervosnetwork/ckb-sdk-go/rpc

    ///BEFORE
    //!!NOTE: OLD ONE, this is deprated!
    //indexerClient, err := indexer.Dial("http://127.0.0.1:8114")
    //indexerClient.GetCells....

    ///AFTER
    //!!NOTE: USE THIS INSTEAD
    var client, _ = rpc.Dial("https://testnet.ckb.dev")
    //client.GetCells(...)

    Lumos

    Lumos needs v0.19.0 to adapt to CKB build-in indexer.

    import { Indexer } from '@ckb-lumos/lumos';

    // before
    // const indexer = new Indexer(
    // "https://testnet.ckb.dev/indexer",
    // "https://testnet.ckb.dev/rpc",
    // );

    // after
    const indexer = new Indexer("https://testnet.ckb.dev/rpc");

    Confirmation count suggestion

    Since Nervos CKB network is secured by ASIC PoW miners with extreme hash rate now, it could achieve the same or better security threshold than Ethereum at 24 block confirmations.

    This essay demonstrates how the transaction confirmation number is calculated.

    Testing

    Once you’ve fully integrated with the CKB network, please test on the testnet and mainnet.

    Q&A

    When you integrate CKB into your system, you may face some challenges. Here is a Q&A that may help you.

    - + \ No newline at end of file diff --git a/docs/integrate/qa/index.html b/docs/integrate/qa/index.html index cb5ba8fad..08c9cca4b 100644 --- a/docs/integrate/qa/index.html +++ b/docs/integrate/qa/index.html @@ -14,15 +14,15 @@ Q&A | For Wallets/Exchanges/Mining Pools | Nervos CKB - +

    Q&A | For Wallets/Exchanges/Mining Pools

    External wallets, exchanges and mining pools typically face unique and different challenges when they integrate CKB into their system. This page will provide Q&A for wallets, exchanges and mining pools to integrate CKB. We are woking on detailed guides and helpful tips now, please be patient for a while.

    The following three questions are related to transaction processing, you may refer to Transaction for more details.

    Q:How do we use the two fields code_hash and hash_type in the lock script of output cells ?

    A: When the output cells are unlocked, CKB-VM should load the corresponding contracts by using code_hash and hash_type.It is recommended to refer to Script for more details.

    • code_hash: A hash denoting which script in the transaction to execute. For space consideration, the actual script code is kept in the cell data part of a live cell on CKB. The current transaction should reference the live cell using a cell dep so as to locate and execute the script.
    • hash_type: The interpretation of code_hash when looking for script code to run from cell deps.
      • If hash_type contains data, code_hash should match the blake2b hash of data(which is also the actual script code) in a dep cell;
      • If hash_type contains type, code_hash should instead match the blake2b hash of type script contained by a a dep cell. Note CKB will throw a validation error when a) we are locating a script code using type as hash_type; and b) more than one cell referenced by cell deps contains the specified hash of type script.

    Q:Can we hardcode the code_hash , hash_type and the corresponding cell_dep of two scripts? Are they the same on Testnet as on Mainnet?

    A: code_hash and hash_type can be hardcoded and they are the same on Testnet as on Mainnet. cell_dep is not the same on the Testnet as on Manniet. But they are all get from the fixed position of the genesis block. The single signature is from the second transaction of the genesis block and the multisignature is from the second output cell, once the genesis block is confirmed, the value is fixed

    Q: How do we use Type in the outputs?

    A: Type can be used in many ways, such as UDT(User Defined Token). We already have an RFC: Simple UDT Draft Spec you may refer it for more details, but currently there isn’t a standard equivalent of ERC20 in Ethereum community, will have to wait until the community has developed a best practice. For wallets or exchanges, you may handle the transactions with Type = null If the standard is generated, you also need filter transactions by whitelist and leave transactions with Type = null in the future.

    Q: What is the relationship between the short address, long address and lock script?

    A: The long address and lock Script correspond one to one. All long addresses can be converted into a lock script and vice versa. All short addresses can be converted into long addresses, but the reverse is not necessarily true. CKB have provided single signature transfer and multisignature transfer scripts by default. Also you may refer to RFC:CKB Address Format for more details.

    Q: Are there some test cases for address resolution and generation in other programming languages?

    A: Yes, you may refer to the test cases of ckb-sdk-java: https://github.com/nervosnetwork/ckb-sdk-java/blob/develop/ckb/src/test/java/utils/AddressParserTest.java -https://github.com/nervosnetwork/ckb-sdk-java/blob/develop/ckb/src/test/java/utils/AddressGeneratorTest.java

    Q: Why is it that the minimum transfer amount cannot be less than 61 CKB?

    A: A cell is used to represent a balance on-chain, and one must hold 1 CKB for every 1 byte of space that the cell occupies. The data in every cell is broken down into four fields: capacity, lock script, type script, and data. Capacity and lock script are required, and type script and data are optional. For more detailed information about the structure of a cell, refer to the cell reference page.

    The most common basic cell is one that represent a CKB balance. Often this will use the default lock script, which is used for short CKB addresses supported by most wallets. A basic cell like this does not require a type script or any additional data. The fields of this cell are as follows:

    • The capacity field is used to hold the number of CKB balance in the cell. This is a u64, which takes 8 bytes.
    • The lock script field is Script type. This inclues a code_hash that is 32 bytes, a hash_type that is 1 byte, and an args field that is 20 bytes.
    • The type script field is optional and is not used for this cell.
    • The data field is optional and is not used for this cell.

    When you add these up, you get 61 bytes: 8 + 32 + 1 + 20 + 0 + 0 = 61.

    This is why the minimum transfer is 61 CKB, because 61 bytes are required to represent this information on-chain.

    While 61 CKB is the minimum, in many cases it is recommended that 62 CKB be sent as the minimum. This is because 61 CKB is the absolute minimum that is required for the cell to exist, and if there are no extra available, then transaction fees cannot be paid from this cell, if needed.

    Q: If I have 100 CKB in my address and transfer 61 CKB, the balance remaining (39 CKB) isn’t enough to create a change cell. How should I handle this?

    A: There are several ways that this can be handled.

    The most simple method is to inform users that they have an insufficient balance, and prompt them to add more CKB as needed. This requires only basic processing logic to be implemented.

    A second option is to tranfer the entire balance of 100 CKB (minus tx fees) so that there is nothing left. If the balance is exactly 0 CKB, then the cell can be consumed and removed from the state completely. This works well if the user wants to withdraw their total balance.

    A third option is to use a more specialized lock script that supports the "Anyone Can Pay" (ACP) protocol. When both the sender and receiver are setup to use ACP, a balance of any size can be transferred between two parties without the sender having to include any CKB for the cell itself. For more information on ACP, please see the Anyone Can Pay RFC.

    Q: Can output_data be used as exchange entry certificate?

    A: CKB Programming model is a generalized version of the UTXO model.It is recommended to generate different account addresses for each user instead of sharing one address and distinguish them by memo.

    Q: Are there APIs similar to Bitcoin Wallet’s APIs to manage CKB?

    A: If you already have UTXO management framework for Bitcoin, you may continue to use it and scan every block of CKB blockchain.If you don’t, you may refer to Cell and use the tools to index or query.

    Q: Which APIs need to be invoked if I want to get transaction lists, transaction balance, initiate transactions and etc.

    A: You may refer to our JSON RPC document.

    - +https://github.com/nervosnetwork/ckb-sdk-java/blob/develop/ckb/src/test/java/utils/AddressGeneratorTest.java

    Q: Why is it that the minimum transfer amount cannot be less than 61 CKB?

    A: A cell is used to represent a balance on-chain, and one must hold 1 CKB for every 1 byte of space that the cell occupies. The data in every cell is broken down into four fields: capacity, lock script, type script, and data. Capacity and lock script are required, and type script and data are optional. For more detailed information about the structure of a cell, refer to the cell reference page.

    The most common basic cell is one that represent a CKB balance. Often this will use the default lock script, which is used for short CKB addresses supported by most wallets. A basic cell like this does not require a type script or any additional data. The fields of this cell are as follows:

    • The capacity field is used to hold the number of CKB balance in the cell. This is a u64, which takes 8 bytes.
    • The lock script field is Script type. This includes a code_hash that is 32 bytes, a hash_type that is 1 byte, and an args field that is 20 bytes.
    • The type script field is optional and is not used for this cell.
    • The data field is optional and is not used for this cell.

    When you add these up, you get 61 bytes: 8 + 32 + 1 + 20 + 0 + 0 = 61.

    This is why the minimum transfer is 61 CKB, because 61 bytes are required to represent this information on-chain.

    While 61 CKB is the minimum, in many cases it is recommended that 62 CKB be sent as the minimum. This is because 61 CKB is the absolute minimum that is required for the cell to exist, and if there are no extra available, then transaction fees cannot be paid from this cell, if needed.

    Q: If I have 100 CKB in my address and transfer 61 CKB, the balance remaining (39 CKB) isn’t enough to create a change cell. How should I handle this?

    A: There are several ways that this can be handled.

    The most simple method is to inform users that they have an insufficient balance, and prompt them to add more CKB as needed. This requires only basic processing logic to be implemented.

    A second option is to transfer the entire balance of 100 CKB (minus tx fees) so that there is nothing left. If the balance is exactly 0 CKB, then the cell can be consumed and removed from the state completely. This works well if the user wants to withdraw their total balance.

    A third option is to use a more specialized lock script that supports the "Anyone Can Pay" (ACP) protocol. When both the sender and receiver are setup to use ACP, a balance of any size can be transferred between two parties without the sender having to include any CKB for the cell itself. For more information on ACP, please see the Anyone Can Pay RFC.

    Q: Can output_data be used as exchange entry certificate?

    A: CKB Programming model is a generalized version of the UTXO model.It is recommended to generate different account addresses for each user instead of sharing one address and distinguish them by memo.

    Q: Are there APIs similar to Bitcoin Wallet’s APIs to manage CKB?

    A: If you already have UTXO management framework for Bitcoin, you may continue to use it and scan every block of CKB blockchain.If you don’t, you may refer to Cell and use the tools to index or query.

    Q: Which APIs need to be invoked if I want to get transaction lists, transaction balance, initiate transactions and etc.

    A: You may refer to our JSON RPC document.

    + \ No newline at end of file diff --git a/docs/integrate/sdk/index.html b/docs/integrate/sdk/index.html index e6e052bb3..d993c287e 100644 --- a/docs/integrate/sdk/index.html +++ b/docs/integrate/sdk/index.html @@ -14,14 +14,14 @@ Nervos CKB SDK | Nervos CKB - +

    Nervos CKB SDK

    ckb-sdk is a collection of libraries which allow you to interact with a local or remote CKB node by using JSON-RPC. You should get familiar with ckb transaction structure and JSON-RPC before using it. Now ckb-sdk is implemented by the following programming languages: JavaScript/TypeScript,Ruby,Swift,Java and Go.

    • Lumos
      • Lumos is a JavaScript/TypeScript framework designed to make backend Dapp development on Nervos CKB easier. Visit the Lumos Tutorial Page for more instructions and step-by-step guidance.
    • ckb-sdk-ruby
      • ckb-sdk-ruby is an SDK implemented in Ruby and provides APIs for developers to send requests to the CKB blockchain. CKB-Explorer and Testnet Faucet utilize ckb-sdk-ruby.
    • ckb-sdk-java
      • ckb-sdk-java is an SDK implemented in Java and provides APIs for developers to send requests to the CKB blockchain.
    • ckb-sdk-swift
      • ckb-sdk-swift is an SDK implemented in Swift and provides APIs for developers to send requests to the CKB blockchain.
    • ckb-sdk-go
      • ckb-sdk-go is an SDK implemented in Golang.
    • ckb-sdk-rust
      • ckb-sdk-rust is an SDK implemented in Rust.
    - + \ No newline at end of file diff --git a/docs/labs/capsule-dynamic-loading-tutorial/index.html b/docs/labs/capsule-dynamic-loading-tutorial/index.html index ab502d9d5..8745c5c75 100644 --- a/docs/labs/capsule-dynamic-loading-tutorial/index.html +++ b/docs/labs/capsule-dynamic-loading-tutorial/index.html @@ -14,14 +14,14 @@ Dynamic loading in Capsule | Nervos CKB - +

    Dynamic loading in Capsule

    Introduction

    Many contracts have a demand for cryptography primitives. In contracts written in Rust, we can easily integrate a cryptography library by adding it as a dependency. But it is not efficient; first, it increases the binary size of the contract; we need to spend more coins to deploy the contract. Second, each contract may include duplicated libraries; it is a waste of the on-chain space.

    We introduce the dynamic loading mechanism to solve this problem:

    • A shared library can be loaded in different programming languages
    • Using dynamic loading can significantly reduce the contract binary size.
    • Using shared libraries increases the utility of the on-chain space.

    Starting from the v0.6 version, ckb-std introduces the dynamic loading module, which provides a high-level interface to dynamically loading libraries from on-chain cells.

    In this tutorial, we build an example shared library in C, and try to dynamically load the shared library from a contract written in Rust.

    If you run into an issue on this tutorial you can create a new issue or contact us on Nervos talk or Discord.

    Setup the develop environment

    Install Capsule

    Prerequisites

    The following must be installed and available to use Capsule.

    • Cargo and Rust - Capsule uses cargo to generate Rust contracts and run tests. Install Rust
    • Docker - Capsule uses docker container to reproducible build contracts. It's also used by cross. https://docs.docker.com/get-docker/
    • cross-rs - Capsule uses cross to build rust contracts. Install with
    # Do this after you installed cargo
    cargo install cross --git https://github.com/cross-rs/cross

    Note: The current user must have permission to manage Docker instances. For more information, see Manage Docker as a non-root user.

    Now you can proceed to install Capsule. It is recommended to download the binary here.

    Or you can install Capsule from it's source:

    cargo install capsule --git https://github.com/nervosnetwork/capsule.git --tag v0.1.3

    Then check if it works with the following command:

    capsule check
    (click here to view response)
    ------------------------------
    cargo installed
    docker installed
    cross-util installed
    ckb-cli installed v1.4.0 (required v1.2.0)
    ------------------------------

    Create a project

    capsule new dynamic-loading-demo
    (click here to view response)
    New project "dynamic-loading-demo"
    Created file "capsule.toml"
    Created file "deployment.toml"
    Created file "README.md"
    Created file "Cargo.toml"
    Created file ".gitignore"
    Created "/home/jjy/workspace/dynamic-loading-demo"
    Created binary (application) `dynamic-loading-demo` package
    Created contract "dynamic-loading-demo"
    Created tests
    Created library `tests` package
    Done

    Make a shared library

    We create a directory to put our C code.

    cd dynamic-loading-demo
    mkdir shared-lib

    We define two functions in our shared library. The visibility attribute tells the compiler to export the following symbol to the shared library.

    // shared-lib/shared-lib.c

    typedef unsigned long size_t;

    __attribute__((visibility("default"))) int
    plus_42(size_t num) {
    return 42 + num;
    }

    __attribute__((visibility("default"))) char *
    foo() {
    return "foo";
    }

    We need the RISC-V gnu toolchain to compile the source. Fortunately, we can set up the compiling environment with Docker:

    Create the share-lib/Makefile

    TARGET := riscv64-unknown-linux-gnu
    CC := $(TARGET)-gcc
    LD := $(TARGET)-gcc
    OBJCOPY := $(TARGET)-objcopy
    CFLAGS := -fPIC -O3 -nostdinc -nostdlib -nostartfiles -fvisibility=hidden -I deps/ckb-c-stdlib -I deps/ckb-c-stdlib/libc -I deps -I deps/molecule -I c -I build -I deps/secp256k1/src -I deps/secp256k1 -Wall -Werror -Wno-nonnull -Wno-nonnull-compare -Wno-unused-function -g
    LDFLAGS := -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-sections

    # docker pull nervos/ckb-riscv-gnu-toolchain:gnu-bionic-20191012
    BUILDER_DOCKER := nervos/ckb-riscv-gnu-toolchain@sha256:aae8a3f79705f67d505d1f1d5ddc694a4fd537ed1c7e9622420a470d59ba2ec3

    all-via-docker:
    docker run --rm -v `pwd`:/code ${BUILDER_DOCKER} bash -c "cd /code && make shared-lib.so"

    shared-lib.so: shared-lib.c
    $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $<
    $(OBJCOPY) --only-keep-debug $@ $@.debug
    $(OBJCOPY) --strip-debug --strip-all $@

    Run make all-via-docker to compile the shared-lib.so.

    Dynamic loading

    We use CKBDLContext::load to load a library. To use this function, we need to know the data_hash of the target shared library.

    Create a build.rs file:

    touch contracts/dynamic-loading-demo/build.rs

    The build.rs (aka build scripts) execute on the building stage, see details , in build.rs we compute the data_hash of shared.so and put the result into a constant variable.

    Add blake2b crate as build dependencies.

    [build-dependencies]
    blake2b-rs = "0.1.5"

    Write the constant CODE_HASH_SHARED_LIB to file code_hashes.rs.

    pub use blake2b_rs::{Blake2b, Blake2bBuilder};

    use std::{
    fs::File,
    io::{BufWriter, Read, Write},
    path::Path,
    };

    const BUF_SIZE: usize = 8 * 1024;
    const CKB_HASH_PERSONALIZATION: &[u8] = b"ckb-default-hash";

    fn main() {
    let out_path = Path::new("src").join("code_hashes.rs");
    let mut out_file = BufWriter::new(File::create(&out_path).expect("create code_hashes.rs"));

    let name = "shared-lib";
    let path = format!("../../shared-lib/{}.so", name);

    let mut buf = [0u8; BUF_SIZE];

    // build hash
    let mut blake2b = new_blake2b();
    let mut fd = File::open(&path).expect("open file");
    loop {
    let read_bytes = fd.read(&mut buf).expect("read file");
    if read_bytes > 0 {
    blake2b.update(&buf[..read_bytes]);
    } else {
    break;
    }
    }

    let mut hash = [0u8; 32];
    blake2b.finalize(&mut hash);

    write!(
    &mut out_file,
    "pub const {}: [u8; 32] = {:?};\n",
    format!("CODE_HASH_{}", name.to_uppercase().replace("-", "_")),
    hash
    )
    .expect("write to code_hashes.rs");
    }

    pub fn new_blake2b() -> Blake2b {
    Blake2bBuilder::new(32)
    .personal(CKB_HASH_PERSONALIZATION)
    .build()
    }

    Run capsule build, the file src/code_hashes.rs will be generated.

    We define the module code_hashes in the lib.rs. Then add the dynamic loading code to the main function.

    mod code_hashes;
    use code_hashes::CODE_HASH_SHARED_LIB;
    use ckb_std::dynamic_loading::{CKBDLContext, Symbol};

    //...

    // Create a DL context with 64K buffer.
    let mut context = CKBDLContext::<[u8; 64 * 1024]>::new();
    // Load library
    let lib = context.load(&CODE_HASH_SHARED_LIB).expect("load shared lib");

    // get symbols
    unsafe {
    type Plus42 = unsafe extern "C" fn(n: usize) -> usize;
    let plus_42: Symbol<Plus42> = lib.get(b"plus_42").expect("find plus_42");
    assert_eq!(plus_42(13), 13 + 42);

    type Foo = unsafe extern "C" fn() -> *const u8;
    let foo: Symbol<Foo> = lib.get(b"foo").expect("find foo");
    let ptr = foo();
    let mut buf = [0u8; 3];
    buf.as_mut_ptr().copy_from(ptr, buf.len());
    assert_eq!(&buf[..], b"foo");
    }

    Run capsule build to make sure the contract can be built without errors.

    Testing

    We need to deploy the shared-lib.so to a cell, then reference the cell in the testing transaction. Open tests/src/tests.rs.

    use std::fs::File;
    use std::io::Read;
    // ...
    // deploy shared library
    let shared_lib_bin = {
    let mut buf = Vec::new();
    File::open("../shared-lib/shared-lib.so")
    .unwrap()
    .read_to_end(&mut buf)
    .expect("read code");
    Bytes::from(buf)
    };
    let shared_lib_out_point = context.deploy_cell(shared_lib_bin);
    let shared_lib_dep = CellDep::new_builder().out_point(shared_lib_out_point).build();

    // ...
    // build transaction
    let tx = TransactionBuilder::default()
    .input(input)
    .outputs(outputs)
    .outputs_data(outputs_data.pack())
    .cell_dep(lock_script_dep)
    // reference to shared library cell
    .cell_dep(shared_lib_dep)
    .build();

    Run capsule test.

    (click here to view response)
    running 1 test
    consume cycles: 1808802
    test tests::test_basic ... ok

    test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

    Doc-tests tests

    running 0 tests

    test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

    Other resources

    - + \ No newline at end of file diff --git a/docs/labs/capsule-exec/index.html b/docs/labs/capsule-exec/index.html index 3e01fa8b5..a7a9ceaf9 100644 --- a/docs/labs/capsule-exec/index.html +++ b/docs/labs/capsule-exec/index.html @@ -14,13 +14,13 @@ Exec syscall in Capsule | Nervos CKB - +

    Exec syscall in Capsule

    Introduction

    Exec is a new syscall provided by ckb2021. To understand what exec syscall does, we recommend reading this article first. In short: Exec runs an executable file from specified cell data in the context of an already existing VM, replacing the previous executable. The used cycles do not change, but the code, registers, and memory of the VM are replaced by those of the new program, meaning control flow will never return to the main script.

    You can imagine exec as a router. When some conditions are met, the main script will completely hand over control to a certain sub-script.

                  ┌--> if State1 --> Exec(Sub-script1)
    Main script --+--> if State2 --> Exec(Sub-script2)
    └--> if State3 --> Exec(Sub-script3)

    Compared with Dynamic libraries, exec has the following significant advantages:

    • All sub-scripts are complete scripts. They can be used alone, or they can be called by exec.
    • Sub-scripts have a separate 4M memory space.
    • Allow passing in arguments.

    At the same time Exec has the following limitations:

    • Never return.
    • Hard to exchange data between scripts.

    When dynamic libraries and exec syscall both meet your needs, we recommend that you use exec instead of dynamic libraries.

    In this tutorial, we'll write two scripts in Rust, and exec one script into the other.

    Setup the develop environment

    This tutorial targets cpasule 0.9 and ckb-std 0.12.

    Install capsule

    The installation steps can refer to here.

    Create a project

    $ capsule new ckb-exec-demo
    (click here to view response)
    New project "ckb-exec-demo"
    Created file "capsule.toml"
    Created file "deployment.toml"
    Created file "README.md"
    Created file "Cargo.toml"
    Created file ".gitignore"
    Initialized empty Git repository in /tmp/ckb-exec-demo/.git/
    Created "/tmp/ckb-exec-demo"
    Created tests
    Created library `tests` package
    New contract "ckb-exec-demo"
    Created binary (application) `ckb-exec-demo` package
    Rewrite Cargo.toml
    Rewrite capsule.toml
    Done

    Let's create the second contract named echo.

    $ cd ckb-exec-demo
    $ capsule new-contract echo
    (click here to view response)
    New contract "echo"
    Created binary (application) `echo` package
    Rewrite Cargo.toml
    Rewrite capsule.toml
    Done

    If you are using an older version of capsule, you may need to update the ckb-std dependency manually:

    contracts/echo/Cargo.toml
    ckb-std = "0.12.1"

    Write echo sub-script

    Put the following code into contracts/echo/src/main.rs, replacing the existing program_entry function. As you can see, the script always returns 0 if argc is 0, which means that if the script is used as a alone lock script, anyone can unlock this cell. If echo used as a sub-script of exec, it will parse the first argument and use that as the exit code.

    fn program_entry() -> i8 {
    let argv = ckb_std::env::argv();
    // This script will always return 0 if used alone.
    if argv.len() == 0 {
    return 0;
    };

    // When calling the script by exec and passing in the arguments.
    let arg1 = argv[0].to_str().unwrap();
    let exit = arg1.parse::<i8>().unwrap();
    return exit;
    }

    Write exec demo script

    Put the following code into contracts/ckb-exec-demo/src/main.rs, replacing the existing program_entry function:

    use core::ffi::CStr;
    use ckb_std::{ckb_constants::Source, syscalls::exec};

    fn program_entry() -> i8 {
    let r = exec(
    0,
    Source::CellDep,
    0,
    0,
    &[&CStr::from_bytes_with_nul(b"42\0").unwrap()],
    );
    if r != 0 {
    return 10;
    }
    return 0;
    }

    This script does only one thing: When executing exec(...), CKB-VM will look for the first dep_cell, and execute the code in it.

    Testing

    We need to deploy the echo to a cell, then reference the cell in the testing transaction. Replace the content of tests/src/tests.rs:

    use super::*;
    use ckb_testtool::ckb_error::Error;
    use ckb_testtool::ckb_types::{bytes::Bytes, core::TransactionBuilder, packed::*, prelude::*};
    use ckb_testtool::context::Context;

    const MAX_CYCLES: u64 = 10_000_000;

    fn assert_script_error(err: Error, err_code: i8) {
    let error_string = err.to_string();
    assert!(
    error_string.contains(format!("error code {} ", err_code).as_str()),
    "error_string: {}, expected_error_code: {}",
    error_string,
    err_code
    );
    }

    #[test]
    fn test_success() {
    // deploy contract
    let mut context = Context::default();
    let contract_bin: Bytes = Loader::default().load_binary("ckb-exec-demo");
    let out_point = context.deploy_cell(contract_bin);

    let echo_bin: Bytes = Loader::default().load_binary("echo");
    let echo_out_point = context.deploy_cell(echo_bin);
    let echo_dep = CellDep::new_builder().out_point(echo_out_point).build();

    // prepare scripts
    let lock_script = context
    .build_script(&out_point, Default::default())
    .expect("script");

    // prepare cells
    let input_out_point = context.create_cell(
    CellOutput::new_builder()
    .capacity(1000u64.pack())
    .lock(lock_script.clone())
    .build(),
    Bytes::new(),
    );
    let input = CellInput::new_builder()
    .previous_output(input_out_point)
    .build();
    let outputs = vec![
    CellOutput::new_builder()
    .capacity(500u64.pack())
    .lock(lock_script.clone())
    .build(),
    CellOutput::new_builder()
    .capacity(500u64.pack())
    .lock(lock_script)
    .build(),
    ];

    let outputs_data = vec![Bytes::new(); 2];

    // build transaction
    let tx = TransactionBuilder::default()
    .input(input)
    .outputs(outputs)
    .outputs_data(outputs_data.pack())
    .cell_dep(echo_dep)
    .build();
    let tx = context.complete_tx(tx);

    // run
    let err = context.verify_tx(&tx, MAX_CYCLES).unwrap_err();
    assert_script_error(err, 42);
    }

    Run capsule test.

    (click here to view response)
    Finished test [unoptimized + debuginfo] target(s) in 1.71s
    Running unittests src/lib.rs (target/debug/deps/tests-c051885699f8b848)
    running 1 test
    test tests::test_success ... ok
    test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.52s

    Other resources

    In this article, we use the index to locate sub-scripts. If you want to use the script hash to locate, you can refer to our:

    - + \ No newline at end of file diff --git a/docs/labs/introduction/index.html b/docs/labs/introduction/index.html index d36641dee..95311324f 100644 --- a/docs/labs/introduction/index.html +++ b/docs/labs/introduction/index.html @@ -14,13 +14,13 @@ Introduction | Nervos CKB - +
    - + \ No newline at end of file diff --git a/docs/labs/lumos-nervosdao/index.html b/docs/labs/lumos-nervosdao/index.html index c79e25c31..ea6ba3850 100644 --- a/docs/labs/lumos-nervosdao/index.html +++ b/docs/labs/lumos-nervosdao/index.html @@ -14,13 +14,13 @@ Introduction to Lumos via NervosDAO | Nervos CKB - +
    -

    Introduction to Lumos via NervosDAO

    In the real world, one hardly sees a blockchain exposed and used directly by the ordinary users. Apps, websites or other services are built on top of blockchains to provide a seamless service. Based on this belief, we built lumos, a JavaScript/TypeScript framework, that aids dapp development on CKB. Lumos should be able to free you from most, if not all of the hassles for dealing with CKB, and let you focus on the specific logic in your dapp.

    In this tutorial, we will provide an introduction on lumos via a real example: Nervos DAO, while quite valuable on CKB, can be a real pain to integrate for many dapps. Here we will demonstrate that how lumos can be used to streamline Nervos DAO integration.

    Components

    Lumos is designed as a framework, meaning it is expected to be used in a intrinsic way: certain setup code will be needed when you first boot your application. Global states might also be kept in your application memory space for bookkeeping purposes. That being said, lumos is also organized into several components, some of which might be used in a non-intrinsic stateless fashion. In general, lumos consists of the following components:

    • indexer: a CKB cell indexer that fulfills Index-Query-Assemble pattern. For now, this package only contains RocksDB backed indexer. A separate pacakge contains SQL backed indexer using the same interface. Later, we might merge the 2 packages into one for consistency.
    • base: a base package containing common types and utilities that are used by most packages. If there is a CKB specific task you need to perform, you might want to look here first. Chances are they are already provided.
    • helpers: a helper package containing more utilities. The difference between helpers and base, is that base contains pure stateless functions, while helpers works in a more intrinsic way: it requires config-manager mentioned below to be setup.
    • common-scripts: integrations for known scripts on CKB. While we try our best to provide integrations for popular CKB scripts, people might be working on innovations everyday. As a result, we are also designing a set of APIs, so developers can freely integrate their own scripts into lumos for everyone to use. One integrated, common-scripts should be able to leverage those new scripts as well.
    • config-manager: a manager for dealing with differences between different chains, such as mainnet, testnet, or numerous dev chains. We abstract each chain into individual config file. Once loaded, config manager will be able to handle the chain specific logic, so you don't have to deal with this in your own code.
    • transaction-manager: a transaction manager for CKB. One problem with UTXO based blockchains, is that a certain amount of gap period exists between a transaction is accepted by a blockchain, and when it is actually committed on chain. During this gap, new cells created by the pending transaction will not be available. Transaction manager package takes care of this. It wraps an indexer instance, and makes sure cells created in pending transactions, are also exposed and available for assembling new transactions. This means you are no longer bounded to one transaction at a time, you can freely send series of transactions as you wish.

    Initial CKB Setup

    To ease the whole process so we don't have to wait too long to see the results, let's setup our own dev chain with tweaks:

    $ export TOP=$(pwd)
    # I'm testing this on a Linux machine, if you use other platforms, please adjust
    # this accordingly.
    $ curl -LO https://github.com/nervosnetwork/ckb/releases/download/v0.33.0/ckb_v0.33.0_x86_64-unknown-linux-gnu.tar.gz
    $ tar xzf ckb_v0.33.0_x86_64-unknown-linux-gnu.tar.gz
    $ export PATH=$PATH:$TOP/ckb_v0.33.0_x86_64-unknown-linux-gnu
    $ ckb -V
    ckb 0.33.0
    $ ckb init -C devnet -c dev
    $ ed devnet/specs/dev.toml <<EOF
    91d
    90a
    genesis_epoch_length = 10
    permanent_difficulty_in_dummy = true
    .
    wq
    EOF
    $ ed devnet/ckb-miner.toml <<EOF
    39s/5000/1000/
    wq
    EOF
    $ ed devnet/ckb.toml <<EOF
    143a
    [block_assembler]
    code_hash = "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8"
    # private key: 0x29159d8bb4b27704b168fc7fae70ffebf82164ce432b3f6b4c904a116a969f19
    args = "0xcbfbb9edb5838e2d61061c3fc69eaaa5fdbd3273"
    hash_type = "type"
    message = "0x"
    .
    wq
    EOF
    $ ckb run -C devnet

    Here we are making the following configuration:

    • Create a dev chain
    • Modify the chain config to skip difficulty adjustment, and set all epoch to contain 10 blocks
    • Modify miner config to generate a new block every second
    • Use a specific private key as the wallet used in miner. Please do not use this private key elsewhere!
    • Start a CKB node with the dev chain

    In a different terminal, we can also start the CKB miner:

    $ export TOP=$(pwd)
    $ export PATH=$PATH:$TOP/ckb_v0.33.0_x86_64-unknown-linux-gnu
    $ ckb miner -C devnet

    Node Skeleton

    Now with CKB ready, we can create the node skeleton used to run our JS code:

    $ mkdir nervosdao-skeleton
    $ cd nervosdao-skeleton
    $ yarn init
    $ yarn add @ckb-lumos/indexer@0.4.3 @ckb-lumos/common-scripts@0.4.3

    In this lab, we will run the operation needed from a node shell with async/await enabled:

    $ node --experimental-repl-await
    Welcome to Node.js v12.16.2.
    Type ".help" for more information.
    >

    But this is only for demonstration purposes. There's nothing stopping you from copying the same code into a file that is then executed by node.

    Config Manager Setup

    The first step in using lumos, is setting up config manager. Even though CKB has a unified programming model, different configurations would still be required for different chain instances, such as mainnet, testnet or dev chains. Config manager allows the node app to boot with a specific chain configuration, so other parts in lumos can consult config manager directly for information.

    If you are using a well known chain configuration, you can use LUMOS_CONFIG_NAME environment variable to setup config manager:

    $ LUMOS_CONFIG_NAME=LINA node --experimental-repl-await
    Welcome to Node.js v12.16.2.
    Type ".help" for more information.
    > const { initializeConfig, getConfig } = require("@ckb-lumos/config-manager");
    > initializeConfig();
    > getConfig();
    {
    PREFIX: 'ckb',
    SCRIPTS: {
    SECP256K1_BLAKE160: {
    CODE_HASH: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8',
    HASH_TYPE: 'type',
    TX_HASH: '0x71a7ba8fc96349fea0ed3a5c47992e3b4084b031a42264a018e0072e8172e46c',
    INDEX: '0x0',
    DEP_TYPE: 'dep_group',
    SHORT_ID: 0
    },
    SECP256K1_BLAKE160_MULTISIG: {
    CODE_HASH: '0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8',
    HASH_TYPE: 'type',
    TX_HASH: '0x71a7ba8fc96349fea0ed3a5c47992e3b4084b031a42264a018e0072e8172e46c',
    INDEX: '0x1',
    DEP_TYPE: 'dep_group',
    SHORT_ID: 1
    },
    DAO: {
    CODE_HASH: '0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e',
    HASH_TYPE: 'type',
    TX_HASH: '0xe2fb199810d49a4d8beec56718ba2593b665db9d52299a0f9e6e75416d73ff5c',
    INDEX: '0x2',
    DEP_TYPE: 'code'
    }
    }
    }

    Supported well known configurations include:

    • LINA: mainnet config;
    • AGGRON4: current testnet config. Note at certain time, we might reset testnet, in that case, lumos might be upgraded with new testnet configurations.

    However there might be cases, where you don't use a pre-defined configuration. For example, the dev chain we use here, does not have a pre-defined configuration. Lumos also supports setting up config manager via a local config file. You can use LUMOS_CONFIG_FILE environment variable to point to the config file. If neither config variable is set, lumos will try to read config file from config.json file in current directory.

    $ cat <<EOF > config.json
    {
    "PREFIX": "ckt",
    "SCRIPTS": {
    "SECP256K1_BLAKE160": {
    "CODE_HASH": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8",
    "HASH_TYPE": "type",
    "TX_HASH": "0xace5ea83c478bb866edf122ff862085789158f5cbff155b7bb5f13058555b708",
    "INDEX": "0x0",
    "DEP_TYPE": "dep_group",
    "SHORT_ID": 0
    },
    "SECP256K1_BLAKE160_MULTISIG": {
    "CODE_HASH": "0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8",
    "HASH_TYPE": "type",
    "TX_HASH": "0xace5ea83c478bb866edf122ff862085789158f5cbff155b7bb5f13058555b708",
    "INDEX": "0x1",
    "DEP_TYPE": "dep_group",
    "SHORT_ID": 1
    },
    "DAO": {
    "CODE_HASH": "0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e",
    "HASH_TYPE": "type",
    "TX_HASH": "0xa563884b3686078ec7e7677a5f86449b15cf2693f3c1241766c6996f206cc541",
    "INDEX": "0x2",
    "DEP_TYPE": "code"
    }
    }
    }
    EOF
    $ LUMOS_CONFIG_FILE="config.json" node --experimental-repl-await
    Welcome to Node.js v12.16.2.
    Type ".help" for more information.
    > const { initializeConfig, getConfig } = require("@ckb-lumos/config-manager");
    > initializeConfig();

    Now config manager is successfully setup, we can proceed to the next step.

    Booting Indexer

    Lumos is designed based on the Index-Query-Assemble pattern, meaning a dapp shall hava an indexer that keeps indexing new blocks in a format that is easier to query. This means any dapp built with lumos, should also have an indexer configured and running at all time:

    > const { Indexer } = require("@ckb-lumos/indexer");
    > const indexer = new Indexer("http://127.0.0.1:8114", "./indexed-data");
    > indexer.startForever();

    Here we are using the RocksDB backed indexer for simplicity. Lumos provides 2 indexer types:

    • RocksDB backed indexer
    • SQL backed indexer, supported SQL databases now include MySQL and PostgreSQL.

    If you want to test against the SQL indexer, some modifications to the above setup code might be required.

    You can check current indexed tip with the following code snippet:

    > await indexer.tip()
    {
    block_number: "0x29c",
    block_hash: "0x3e44b571c82a09117231baee1939d38440d71f56de8bc600ac32b1dead9be46d"
    }

    Please wait a while till lumos has caught up with the current chain tip. This should not take much time for a dev chain.

    Deposit

    To deposit to Nervos DAO, we need to first create a deposit transaction. You could of course go the hard way and create a transaction manually, but lumos has already provide a solution for simplifying transaction creation. Let's look at TransactionSkeleton and how it works in lumos first.

    Transaction Skeleton

    CKB provides great flexibility for dapp developers to build anything they want. But we all know that with great power comes great responsibility, a flexible programming model also significantly complicates transaction assembling. This includes but might not be limited to the following hurdles:

    • Different scripts used in transaction inputs will require separate message generation, and also separate signing steps.
    • Some cells might require special argument setup in witness, due to type script validation rules.
    • Coordination might be required, since both lock script and type script in a cell might require arguments in the same witness construct.

    Those problems will haunt you even when you are dealing with a single NervosDAO transaction. It is only gonna get more complicated, when we consider multiple cells containing different CKB scripts composed together. Looking into the future, we will definitely need a solution to this issue.

    TransactionSkeleton is the answer we propose in lumos. Each transaction skeleton corresponds to an action, and will be built into a single transaction that is ready to be submitted to CKB. Surrounding the idea of TransactionSkeleton, a series of conveniences are provided to aid transaction assembling:

    • A well designed component should automatically query and include cells to provide capacities required by the transaction.
    • Individual script logic should be managed and respected by the general transaction skeleton.
    • Scripts sharing the same behavior should be managed together in a unified interface. Developers can rely on abstractions instead of catering for every single detail.

    This still sounds quite complicated, let's walkthrough an example to see how we can leverage TransactionSkeleton.

    > // In practice, you might already have the address at your hand, here we just
    > // want to demonstrate how this works.
    > const script = {
    code_hash: "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8",
    hash_type: "type",
    args: "0xcbfbb9edb5838e2d61061c3fc69eaaa5fdbd3273"
    };
    > const {generateAddress, parseAddress, createTransactionFromSkeleton,
    sealTransaction, TransactionSkeleton } = require("@ckb-lumos/helpers");
    > const address = generateAddress(script);

    > // Now let's create the actual skeleton, and deposit CKBytes into the skeleton
    > let skeleton = TransactionSkeleton({ cellProvider: indexer });
    > const { secp256k1Blake160, dao } = require("@ckb-lumos/common-scripts");

    > // Using utility provided in common-scripts, let's deposit 1000 CKBytes into
    > // the skeleton. We will introduce common-scripts separately below. Here we are
    > // using the same address as from and to, but this does not have to be the case
    > // everywhere.
    > skeleton = await dao.deposit(skeleton, address, address, 100000000000n);

    > // createTransactionFromSkeleton is designed to build a final transaction, but
    > // there is nothing stopping you from using it to peek into the current skeleton.
    > console.log(JSON.stringify(createTransactionFromSkeleton(skeleton), null, 2));

    > // But this transaction is not yet complete, we still need 2 parts:
    > // * Transaction fee is not taken into consideration
    > // * The transaction is not signed yet
    > // Let's take a look at them separately.

    > // First, since we are using the default secp256k1-blake160 lock script, an
    > // existing module in common-scripts can be leveraged to incur transaction
    > // fee. Here we are using the same address to provide 1 CKByte as transaction
    > // fee.
    > skeleton = await secp256k1Blake160.payFee(skeleton, address, 100000000n);

    > // If you checked the transaction skeleton after incurring fees. You will
    > // notice that it only has one input. This might raise a question: if NervoDAO
    > // deposit consumes one input cell, transaction fee requires a different input
    > // cell, shouldn't there be 2 input cells with 3 output cells(a deposited cell,
    > // and 2 change cell)? The trick here, is that common-scripts is smart enough
    > // to figure out that the 2 actions here use the same address. Hence it just
    > // rewrite the change cell generated in the NervosDAO deposit action to pay
    > // enough transaction fee.
    > createTransactionFromSkeleton(skeleton).inputs.length;
    1

    > // Now the transaction is more or less complete, we can start generate messages
    > // used for signing.
    > skeleton = secp256k1Blake160.prepareSigningEntries(skeleton);
    > // This method actually loops through the skeleton, and create `signingEntries`
    > // that are using the default secp256k1-blake160 lock script:
    > skeleton.get("signingEntries").toArray();
    [
    {
    type: 'witness_args_lock',
    index: 0,
    message: '0x40811fd6ed74b9042f603dc7f2f577da7ebe0e05175d349dbb5c539b1111b83f'
    }
    ]

    Lumos, for now, does not handle message signing for the following reasons:

    • This is a serious matter that relates to the overall security of the dapp, we want to make sure we are doing this properly if/when we decide to do it.
    • Different dapps might have different requirements, some don't do signing at all, having signing built-in might render certain dapps hard to build.

    Using a secp256k1 tool, it's not hard to generate a signature here based on the private key listed above, and the message. And we can continue with this process:

    > const signatures = ["0x1cb952fd224d1d14d07af621587e91a65ccb051d55ed1371b3b66d4fe169cf7758173882e4c02587cb54054d2de287cbb1fdc2fc21d848d7b320ee8c5826479901"];
    > const tx = sealTransaction(skeleton, signatures);

    Now we have a complete transaction assembled, and we can send it to CKB:

    > const { RPC } = require("ckb-js-toolkit");
    > const rpc = new RPC("http://127.0.0.1:8114");
    > await rpc.send_transaction(tx);
    '0x88536e8c25f5f8c89866dec6a5a1a6a72cccbe282963e4a7bfb5542b4c15d376'

    Now we have successfully deposited CKBytes into CKB using lumos!

    Withdraw

    The following code can help us list all deposited Nervos DAO cells for an address:

    > for await (const cell of dao.listDaoCells(indexer, address, "deposit")) { console.log(cell); }
    {
    cell_output: {
    capacity: '0x174876e800',
    lock: {
    code_hash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8',
    hash_type: 'type',
    args: '0xcbfbb9edb5838e2d61061c3fc69eaaa5fdbd3273'
    },
    type: {
    code_hash: '0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e',
    hash_type: 'type',
    args: '0x'
    }
    },
    out_point: {
    tx_hash: '0x88536e8c25f5f8c89866dec6a5a1a6a72cccbe282963e4a7bfb5542b4c15d376',
    index: '0x0'
    },
    block_hash: '0xa1ec7dc291774bc0fc229efba4a162c099a8d88ffa7ae2fa410cc574e0701ced',
    block_number: '0x196',
    data: '0x0000000000000000'
    }

    Here we can find the cell we just deposited to Nervos DAO. Let's now try to withdraw it from Nervos DAO:

    > // First, we will need to locate the cell. In a real dapp this is most likely
    > // coming from user selection.
    > const cell = (await dao.listDaoCells(indexer, address, "deposit").next()).value;
    > // For a new action, let's create a new transaction skeleton
    > skeleton = TransactionSkeleton({ cellProvider: indexer });
    > // This time, we invoke withdraw method to prepare a withdraw skeleton
    > skeleton = await dao.withdraw(skeleton, cell, address);
    > // Fees are also necessary
    > skeleton = await secp256k1Blake160.payFee(skeleton, address, 100000000n);
    > // And let's generate signing entries again.
    > skeleton = secp256k1Blake160.prepareSigningEntries(skeleton);
    > skeleton.get("signingEntries").toArray();
    [
    {
    type: 'witness_args_lock',
    index: 0,
    message: '0x24370c5cedc03c34ae0a00a10d9e62324bce07e8d155c839ff10991d73684c34'
    }
    ]
    > // After we signed the message, we can get the signature:
    > const signatures2 = ["0x5aed4480c82844506fefc1d92dd18422a123b8e880018ea4cfa7f95891c4781e6578facedd765676831cf3cca04492ec3ec3885ac8d0b6d90cb6c1d6f99e6ffb01"];
    > // Now we can seal and send the transaction
    > const tx2 = sealTransaction(skeleton, signatures2);
    > await rpc.send_transaction(tx2);
    '0xe411eb6a3cf4f659461cc7a9df9ff95a72b9624bf850b9ccad0c4d7f2ab444f6'

    See that withdrawing transaction is not so hard!

    Locktime Pool

    We could've just showed the unlock method in dao module, which let you complete the withdrawing from Nervos DAO. But here I want to talk about a different construct in lumos: locktime pool.

    If you look closer, you would notice that the cell consumed in withdraw phase 2, is really nothing but a cell with a certain lock period. Likewise, there might be other scripts on CKB, when combined with certain cell, just provide lock periods. The multisig script included in genesis cell, is one such example. So the idea arises: what if we build a unified pool, that handles all cells that have lock periods? When designed properly, we can ignore the fact that they might come from different dapps, using different scripts. What we do care, is that each of those cells comes with a capacity and lock period, when the lock period is reached, they are nothing but ordinary cells in one's wallet.

    Given this thought, we designed locktime pool in lumos. Right now it only processes Nervos DAO cells in withdraw phase 2 and multisig cells, but in the future there is nothing stopping us from integrating more scripts that provide lock periods. From a developer point of view, locktime pool, can be used to manage all of them, provide a unified view in dapps.

    As usual, we can query for all cells currently in the locktime pool:

    > const { locktimePool } = require("@ckb-lumos/common-scripts");
    > for await (const cell of locktimePool.collectCells(indexer, address)) { console.log(cell); }
    {
    cell_output: {
    capacity: '0x174876e800',
    lock: {
    code_hash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8',
    hash_type: 'type',
    args: '0xcbfbb9edb5838e2d61061c3fc69eaaa5fdbd3273'
    },
    type: {
    code_hash: '0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e',
    hash_type: 'type',
    args: '0x'
    }
    },
    out_point: {
    tx_hash: '0xe411eb6a3cf4f659461cc7a9df9ff95a72b9624bf850b9ccad0c4d7f2ab444f6',
    index: '0x0'
    },
    block_hash: '0xb468ec0a1aed1f7070fc00952453ac882dbe36b1afbfb520c822fe46b3b81dfe',
    block_number: '0x543',
    data: '0x9601000000000000',
    maximumCapacity: 100153459536n,
    since: '0x20000a00060000dc',
    depositBlockHash: '0xa1ec7dc291774bc0fc229efba4a162c099a8d88ffa7ae2fa410cc574e0701ced',
    withdrawBlockHash: '0xb468ec0a1aed1f7070fc00952453ac882dbe36b1afbfb520c822fe46b3b81dfe',
    sinceBaseValue: undefined
    }

    Here we can found the cell just created from NervosDAO withdrawing step. Let's try to consume it using locktimePool:

    > // Notice you will wait till the lock period of the cell has passed, otherwise this function would throw an error:
    > skeleton = await locktimePool.transfer(skeleton, [address], address, 100153459536n, (await rpc.get_tip_header()));
    > console.log(JSON.stringify(createTransactionFromSkeleton(skeleton), null, 2));
    {
    "version": "0x0",
    "cell_deps": [],
    "header_deps": [],
    "inputs": [],
    "outputs": [],
    "outputs_data": [],
    "witnesses": []
    }

    This might actually be a surprise: we invoked transfer method, but it does nothing! Turns out the reason here, is that we are using the same address as both transfer input, and transfer output. Lumos is smart enough to figure out that when you are using the same input and output, we don't need to perform the action so as to save certain transaction fee.

    One different question you might ask, is that we use the same address in deposit and withdraw steps, why those previous attempts work? The reason for this, is that deposited cell, or created cell in withdraw step 1 has special purposes, they represent unique actions that we want to perform, hence they are freezed in the transaction skeleton, so later when we optimize the transaction to combine inputs/outputs, we won't touch those specially created cells. On the other hand, in locktime pool design, we treat a cell with expired lock period the same as a normal cell, they really have nothing different, hence here, lumos will try to optimize the transaction, by removing the action transferring amount from an address to itself. In lumos' eye, this is a no-op.

    Now let's try the same step using a different target address:

    > skeleton = await locktimePool.transfer(skeleton, [address], "ckt1qyqx57xrsztnq7g5mlw6r998uyc2f5hm3vnsvgsaet", 100153459536n, (await rpc.get_tip_header()));
    > skeleton = await secp256k1Blake160.payFee(skeleton, address, 100000000n);
    > skeleton = secp256k1Blake160.prepareSigningEntries(skeleton);
    > skeleton.get("signingEntries").toArray();
    [
    {
    type: 'witness_args_lock',
    index: 0,
    message: '0xf01fb9988ba0265597760f50df92a56162d650b119cc95e8508079af584bdbc7'
    }
    ]

    We can generate the signature as always:

    > const signatures3 = ["0x6edde41592b41d445fabfd1b1d6854cf643bba724a338b5751827d991affa5a979d12339250bf5ade45f7f2742cba1e3de0791e37ef03914459bcdd099908ec601"];
    > const tx3 = sealTransaction(skeleton, signatures3);
    > await rpc.send_transaction(tx3);
    '0xbaa7bdd71b7ec975f5a75c49d300857981f333c4346d6d6de1297d8d9d9ce0e0'

    This is really the core part of this post, if you are not understanding this part, we recommend you to read it again, and try it in CKB by yourself. What we are showing here, is that by designing a set of common APIs, we can build a general facility, that manages many different script instances, given the fact that they share the same behavior. And it is really not only the secp256k1-blake160 single signing script that shall be managed by a wallet. Any scripts that follow certain behavior, can be treated as a cell managed in a wallet.

    Common Script

    As we show above, locktime pool is one step ahead of the journey at managing different cells/scripts with similar behaviors. But we are not stopping here, we can continue further down the path: it is mentioned above, that those cells with lock period already passed, can be thought as normal cells. Can we treat them as usual, without needing to deal with locktime pool?

    We have build common module for this. Given a set of address/configurations(since for some P2SH script, address alone won't be enough), it can manage all cells using those scripts, including cells with expired lock period. Right now this includes the following:

    • secp256k1-blake160 single signing script
    • secp256k1-blake160 multiple signing script
    • NervosDAO script(only cells in withdraw phase 2 are managed)

    And the list doesn't stop here, we are working to provide a common API specification, that once implemented, can enable common and locktime pool to support those additional scripts as well. We do hope those 2 modules can help enable a unified cell manager in lumos, in which common handles all consumable cells, while locktime pool gives insights into cells that are locked now but will be usable in the future.

    Recap

    Lumos aims to take care of the full lifecycle of your CKB dapp. In this post, we are just taking a sneak peek at all the powers. We will continue to work on documents as well as sample projects to showcase all the powers enabled by lumos. We welcome all of you to try out lumos, and tell us what you think of it. So we can continue enhancing it, to make it the beloved framework for building CKB dapps.

    - +

    Introduction to Lumos via NervosDAO

    In the real world, one hardly sees a blockchain exposed and used directly by the ordinary users. Apps, websites or other services are built on top of blockchains to provide a seamless service. Based on this belief, we built lumos, a JavaScript/TypeScript framework, that aids dapp development on CKB. Lumos should be able to free you from most, if not all of the hassles for dealing with CKB, and let you focus on the specific logic in your dapp.

    In this tutorial, we will provide an introduction on lumos via a real example: Nervos DAO, while quite valuable on CKB, can be a real pain to integrate for many dapps. Here we will demonstrate that how lumos can be used to streamline Nervos DAO integration.

    Components

    Lumos is designed as a framework, meaning it is expected to be used in a intrinsic way: certain setup code will be needed when you first boot your application. Global states might also be kept in your application memory space for bookkeeping purposes. That being said, lumos is also organized into several components, some of which might be used in a non-intrinsic stateless fashion. In general, lumos consists of the following components:

    • indexer: a CKB cell indexer that fulfills Index-Query-Assemble pattern. For now, this package only contains RocksDB backed indexer. A separate package contains SQL backed indexer using the same interface. Later, we might merge the 2 packages into one for consistency.
    • base: a base package containing common types and utilities that are used by most packages. If there is a CKB specific task you need to perform, you might want to look here first. Chances are they are already provided.
    • helpers: a helper package containing more utilities. The difference between helpers and base, is that base contains pure stateless functions, while helpers works in a more intrinsic way: it requires config-manager mentioned below to be setup.
    • common-scripts: integrations for known scripts on CKB. While we try our best to provide integrations for popular CKB scripts, people might be working on innovations everyday. As a result, we are also designing a set of APIs, so developers can freely integrate their own scripts into lumos for everyone to use. One integrated, common-scripts should be able to leverage those new scripts as well.
    • config-manager: a manager for dealing with differences between different chains, such as mainnet, testnet, or numerous dev chains. We abstract each chain into individual config file. Once loaded, config manager will be able to handle the chain specific logic, so you don't have to deal with this in your own code.
    • transaction-manager: a transaction manager for CKB. One problem with UTXO based blockchains, is that a certain amount of gap period exists between a transaction is accepted by a blockchain, and when it is actually committed on chain. During this gap, new cells created by the pending transaction will not be available. Transaction manager package takes care of this. It wraps an indexer instance, and makes sure cells created in pending transactions, are also exposed and available for assembling new transactions. This means you are no longer bounded to one transaction at a time, you can freely send series of transactions as you wish.

    Initial CKB Setup

    To ease the whole process so we don't have to wait too long to see the results, let's setup our own dev chain with tweaks:

    $ export TOP=$(pwd)
    # I'm testing this on a Linux machine, if you use other platforms, please adjust
    # this accordingly.
    $ curl -LO https://github.com/nervosnetwork/ckb/releases/download/v0.33.0/ckb_v0.33.0_x86_64-unknown-linux-gnu.tar.gz
    $ tar xzf ckb_v0.33.0_x86_64-unknown-linux-gnu.tar.gz
    $ export PATH=$PATH:$TOP/ckb_v0.33.0_x86_64-unknown-linux-gnu
    $ ckb -V
    ckb 0.33.0
    $ ckb init -C devnet -c dev
    $ ed devnet/specs/dev.toml <<EOF
    91d
    90a
    genesis_epoch_length = 10
    permanent_difficulty_in_dummy = true
    .
    wq
    EOF
    $ ed devnet/ckb-miner.toml <<EOF
    39s/5000/1000/
    wq
    EOF
    $ ed devnet/ckb.toml <<EOF
    143a
    [block_assembler]
    code_hash = "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8"
    # private key: 0x29159d8bb4b27704b168fc7fae70ffebf82164ce432b3f6b4c904a116a969f19
    args = "0xcbfbb9edb5838e2d61061c3fc69eaaa5fdbd3273"
    hash_type = "type"
    message = "0x"
    .
    wq
    EOF
    $ ckb run -C devnet

    Here we are making the following configuration:

    • Create a dev chain
    • Modify the chain config to skip difficulty adjustment, and set all epoch to contain 10 blocks
    • Modify miner config to generate a new block every second
    • Use a specific private key as the wallet used in miner. Please do not use this private key elsewhere!
    • Start a CKB node with the dev chain

    In a different terminal, we can also start the CKB miner:

    $ export TOP=$(pwd)
    $ export PATH=$PATH:$TOP/ckb_v0.33.0_x86_64-unknown-linux-gnu
    $ ckb miner -C devnet

    Node Skeleton

    Now with CKB ready, we can create the node skeleton used to run our JS code:

    $ mkdir nervosdao-skeleton
    $ cd nervosdao-skeleton
    $ yarn init
    $ yarn add @ckb-lumos/indexer@0.4.3 @ckb-lumos/common-scripts@0.4.3

    In this lab, we will run the operation needed from a node shell with async/await enabled:

    $ node --experimental-repl-await
    Welcome to Node.js v12.16.2.
    Type ".help" for more information.
    >

    But this is only for demonstration purposes. There's nothing stopping you from copying the same code into a file that is then executed by node.

    Config Manager Setup

    The first step in using lumos, is setting up config manager. Even though CKB has a unified programming model, different configurations would still be required for different chain instances, such as mainnet, testnet or dev chains. Config manager allows the node app to boot with a specific chain configuration, so other parts in lumos can consult config manager directly for information.

    If you are using a well known chain configuration, you can use LUMOS_CONFIG_NAME environment variable to setup config manager:

    $ LUMOS_CONFIG_NAME=LINA node --experimental-repl-await
    Welcome to Node.js v12.16.2.
    Type ".help" for more information.
    > const { initializeConfig, getConfig } = require("@ckb-lumos/config-manager");
    > initializeConfig();
    > getConfig();
    {
    PREFIX: 'ckb',
    SCRIPTS: {
    SECP256K1_BLAKE160: {
    CODE_HASH: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8',
    HASH_TYPE: 'type',
    TX_HASH: '0x71a7ba8fc96349fea0ed3a5c47992e3b4084b031a42264a018e0072e8172e46c',
    INDEX: '0x0',
    DEP_TYPE: 'dep_group',
    SHORT_ID: 0
    },
    SECP256K1_BLAKE160_MULTISIG: {
    CODE_HASH: '0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8',
    HASH_TYPE: 'type',
    TX_HASH: '0x71a7ba8fc96349fea0ed3a5c47992e3b4084b031a42264a018e0072e8172e46c',
    INDEX: '0x1',
    DEP_TYPE: 'dep_group',
    SHORT_ID: 1
    },
    DAO: {
    CODE_HASH: '0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e',
    HASH_TYPE: 'type',
    TX_HASH: '0xe2fb199810d49a4d8beec56718ba2593b665db9d52299a0f9e6e75416d73ff5c',
    INDEX: '0x2',
    DEP_TYPE: 'code'
    }
    }
    }

    Supported well known configurations include:

    • LINA: mainnet config;
    • AGGRON4: current testnet config. Note at certain time, we might reset testnet, in that case, lumos might be upgraded with new testnet configurations.

    However there might be cases, where you don't use a pre-defined configuration. For example, the dev chain we use here, does not have a pre-defined configuration. Lumos also supports setting up config manager via a local config file. You can use LUMOS_CONFIG_FILE environment variable to point to the config file. If neither config variable is set, lumos will try to read config file from config.json file in current directory.

    $ cat <<EOF > config.json
    {
    "PREFIX": "ckt",
    "SCRIPTS": {
    "SECP256K1_BLAKE160": {
    "CODE_HASH": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8",
    "HASH_TYPE": "type",
    "TX_HASH": "0xace5ea83c478bb866edf122ff862085789158f5cbff155b7bb5f13058555b708",
    "INDEX": "0x0",
    "DEP_TYPE": "dep_group",
    "SHORT_ID": 0
    },
    "SECP256K1_BLAKE160_MULTISIG": {
    "CODE_HASH": "0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8",
    "HASH_TYPE": "type",
    "TX_HASH": "0xace5ea83c478bb866edf122ff862085789158f5cbff155b7bb5f13058555b708",
    "INDEX": "0x1",
    "DEP_TYPE": "dep_group",
    "SHORT_ID": 1
    },
    "DAO": {
    "CODE_HASH": "0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e",
    "HASH_TYPE": "type",
    "TX_HASH": "0xa563884b3686078ec7e7677a5f86449b15cf2693f3c1241766c6996f206cc541",
    "INDEX": "0x2",
    "DEP_TYPE": "code"
    }
    }
    }
    EOF
    $ LUMOS_CONFIG_FILE="config.json" node --experimental-repl-await
    Welcome to Node.js v12.16.2.
    Type ".help" for more information.
    > const { initializeConfig, getConfig } = require("@ckb-lumos/config-manager");
    > initializeConfig();

    Now config manager is successfully setup, we can proceed to the next step.

    Booting Indexer

    Lumos is designed based on the Index-Query-Assemble pattern, meaning a dapp shall have an indexer that keeps indexing new blocks in a format that is easier to query. This means any dapp built with lumos, should also have an indexer configured and running at all time:

    > const { Indexer } = require("@ckb-lumos/indexer");
    > const indexer = new Indexer("http://127.0.0.1:8114", "./indexed-data");
    > indexer.startForever();

    Here we are using the RocksDB backed indexer for simplicity. Lumos provides 2 indexer types:

    • RocksDB backed indexer
    • SQL backed indexer, supported SQL databases now include MySQL and PostgreSQL.

    If you want to test against the SQL indexer, some modifications to the above setup code might be required.

    You can check current indexed tip with the following code snippet:

    > await indexer.tip()
    {
    block_number: "0x29c",
    block_hash: "0x3e44b571c82a09117231baee1939d38440d71f56de8bc600ac32b1dead9be46d"
    }

    Please wait a while till lumos has caught up with the current chain tip. This should not take much time for a dev chain.

    Deposit

    To deposit to Nervos DAO, we need to first create a deposit transaction. You could of course go the hard way and create a transaction manually, but lumos has already provide a solution for simplifying transaction creation. Let's look at TransactionSkeleton and how it works in lumos first.

    Transaction Skeleton

    CKB provides great flexibility for dapp developers to build anything they want. But we all know that with great power comes great responsibility, a flexible programming model also significantly complicates transaction assembling. This includes but might not be limited to the following hurdles:

    • Different scripts used in transaction inputs will require separate message generation, and also separate signing steps.
    • Some cells might require special argument setup in witness, due to type script validation rules.
    • Coordination might be required, since both lock script and type script in a cell might require arguments in the same witness construct.

    Those problems will haunt you even when you are dealing with a single NervosDAO transaction. It is only gonna get more complicated, when we consider multiple cells containing different CKB scripts composed together. Looking into the future, we will definitely need a solution to this issue.

    TransactionSkeleton is the answer we propose in lumos. Each transaction skeleton corresponds to an action, and will be built into a single transaction that is ready to be submitted to CKB. Surrounding the idea of TransactionSkeleton, a series of conveniences are provided to aid transaction assembling:

    • A well designed component should automatically query and include cells to provide capacities required by the transaction.
    • Individual script logic should be managed and respected by the general transaction skeleton.
    • Scripts sharing the same behavior should be managed together in a unified interface. Developers can rely on abstractions instead of catering for every single detail.

    This still sounds quite complicated, let's walkthrough an example to see how we can leverage TransactionSkeleton.

    > // In practice, you might already have the address at your hand, here we just
    > // want to demonstrate how this works.
    > const script = {
    code_hash: "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8",
    hash_type: "type",
    args: "0xcbfbb9edb5838e2d61061c3fc69eaaa5fdbd3273"
    };
    > const {generateAddress, parseAddress, createTransactionFromSkeleton,
    sealTransaction, TransactionSkeleton } = require("@ckb-lumos/helpers");
    > const address = generateAddress(script);

    > // Now let's create the actual skeleton, and deposit CKBytes into the skeleton
    > let skeleton = TransactionSkeleton({ cellProvider: indexer });
    > const { secp256k1Blake160, dao } = require("@ckb-lumos/common-scripts");

    > // Using utility provided in common-scripts, let's deposit 1000 CKBytes into
    > // the skeleton. We will introduce common-scripts separately below. Here we are
    > // using the same address as from and to, but this does not have to be the case
    > // everywhere.
    > skeleton = await dao.deposit(skeleton, address, address, 100000000000n);

    > // createTransactionFromSkeleton is designed to build a final transaction, but
    > // there is nothing stopping you from using it to peek into the current skeleton.
    > console.log(JSON.stringify(createTransactionFromSkeleton(skeleton), null, 2));

    > // But this transaction is not yet complete, we still need 2 parts:
    > // * Transaction fee is not taken into consideration
    > // * The transaction is not signed yet
    > // Let's take a look at them separately.

    > // First, since we are using the default secp256k1-blake160 lock script, an
    > // existing module in common-scripts can be leveraged to incur transaction
    > // fee. Here we are using the same address to provide 1 CKByte as transaction
    > // fee.
    > skeleton = await secp256k1Blake160.payFee(skeleton, address, 100000000n);

    > // If you checked the transaction skeleton after incurring fees. You will
    > // notice that it only has one input. This might raise a question: if NervoDAO
    > // deposit consumes one input cell, transaction fee requires a different input
    > // cell, shouldn't there be 2 input cells with 3 output cells(a deposited cell,
    > // and 2 change cell)? The trick here, is that common-scripts is smart enough
    > // to figure out that the 2 actions here use the same address. Hence it just
    > // rewrite the change cell generated in the NervosDAO deposit action to pay
    > // enough transaction fee.
    > createTransactionFromSkeleton(skeleton).inputs.length;
    1

    > // Now the transaction is more or less complete, we can start generate messages
    > // used for signing.
    > skeleton = secp256k1Blake160.prepareSigningEntries(skeleton);
    > // This method actually loops through the skeleton, and create `signingEntries`
    > // that are using the default secp256k1-blake160 lock script:
    > skeleton.get("signingEntries").toArray();
    [
    {
    type: 'witness_args_lock',
    index: 0,
    message: '0x40811fd6ed74b9042f603dc7f2f577da7ebe0e05175d349dbb5c539b1111b83f'
    }
    ]

    Lumos, for now, does not handle message signing for the following reasons:

    • This is a serious matter that relates to the overall security of the dapp, we want to make sure we are doing this properly if/when we decide to do it.
    • Different dapps might have different requirements, some don't do signing at all, having signing built-in might render certain dapps hard to build.

    Using a secp256k1 tool, it's not hard to generate a signature here based on the private key listed above, and the message. And we can continue with this process:

    > const signatures = ["0x1cb952fd224d1d14d07af621587e91a65ccb051d55ed1371b3b66d4fe169cf7758173882e4c02587cb54054d2de287cbb1fdc2fc21d848d7b320ee8c5826479901"];
    > const tx = sealTransaction(skeleton, signatures);

    Now we have a complete transaction assembled, and we can send it to CKB:

    > const { RPC } = require("ckb-js-toolkit");
    > const rpc = new RPC("http://127.0.0.1:8114");
    > await rpc.send_transaction(tx);
    '0x88536e8c25f5f8c89866dec6a5a1a6a72cccbe282963e4a7bfb5542b4c15d376'

    Now we have successfully deposited CKBytes into CKB using lumos!

    Withdraw

    The following code can help us list all deposited Nervos DAO cells for an address:

    > for await (const cell of dao.listDaoCells(indexer, address, "deposit")) { console.log(cell); }
    {
    cell_output: {
    capacity: '0x174876e800',
    lock: {
    code_hash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8',
    hash_type: 'type',
    args: '0xcbfbb9edb5838e2d61061c3fc69eaaa5fdbd3273'
    },
    type: {
    code_hash: '0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e',
    hash_type: 'type',
    args: '0x'
    }
    },
    out_point: {
    tx_hash: '0x88536e8c25f5f8c89866dec6a5a1a6a72cccbe282963e4a7bfb5542b4c15d376',
    index: '0x0'
    },
    block_hash: '0xa1ec7dc291774bc0fc229efba4a162c099a8d88ffa7ae2fa410cc574e0701ced',
    block_number: '0x196',
    data: '0x0000000000000000'
    }

    Here we can find the cell we just deposited to Nervos DAO. Let's now try to withdraw it from Nervos DAO:

    > // First, we will need to locate the cell. In a real dapp this is most likely
    > // coming from user selection.
    > const cell = (await dao.listDaoCells(indexer, address, "deposit").next()).value;
    > // For a new action, let's create a new transaction skeleton
    > skeleton = TransactionSkeleton({ cellProvider: indexer });
    > // This time, we invoke withdraw method to prepare a withdraw skeleton
    > skeleton = await dao.withdraw(skeleton, cell, address);
    > // Fees are also necessary
    > skeleton = await secp256k1Blake160.payFee(skeleton, address, 100000000n);
    > // And let's generate signing entries again.
    > skeleton = secp256k1Blake160.prepareSigningEntries(skeleton);
    > skeleton.get("signingEntries").toArray();
    [
    {
    type: 'witness_args_lock',
    index: 0,
    message: '0x24370c5cedc03c34ae0a00a10d9e62324bce07e8d155c839ff10991d73684c34'
    }
    ]
    > // After we signed the message, we can get the signature:
    > const signatures2 = ["0x5aed4480c82844506fefc1d92dd18422a123b8e880018ea4cfa7f95891c4781e6578facedd765676831cf3cca04492ec3ec3885ac8d0b6d90cb6c1d6f99e6ffb01"];
    > // Now we can seal and send the transaction
    > const tx2 = sealTransaction(skeleton, signatures2);
    > await rpc.send_transaction(tx2);
    '0xe411eb6a3cf4f659461cc7a9df9ff95a72b9624bf850b9ccad0c4d7f2ab444f6'

    See that withdrawing transaction is not so hard!

    Locktime Pool

    We could've just showed the unlock method in dao module, which let you complete the withdrawing from Nervos DAO. But here I want to talk about a different construct in lumos: locktime pool.

    If you look closer, you would notice that the cell consumed in withdraw phase 2, is really nothing but a cell with a certain lock period. Likewise, there might be other scripts on CKB, when combined with certain cell, just provide lock periods. The multisig script included in genesis cell, is one such example. So the idea arises: what if we build a unified pool, that handles all cells that have lock periods? When designed properly, we can ignore the fact that they might come from different dapps, using different scripts. What we do care, is that each of those cells comes with a capacity and lock period, when the lock period is reached, they are nothing but ordinary cells in one's wallet.

    Given this thought, we designed locktime pool in lumos. Right now it only processes Nervos DAO cells in withdraw phase 2 and multisig cells, but in the future there is nothing stopping us from integrating more scripts that provide lock periods. From a developer point of view, locktime pool, can be used to manage all of them, provide a unified view in dapps.

    As usual, we can query for all cells currently in the locktime pool:

    > const { locktimePool } = require("@ckb-lumos/common-scripts");
    > for await (const cell of locktimePool.collectCells(indexer, address)) { console.log(cell); }
    {
    cell_output: {
    capacity: '0x174876e800',
    lock: {
    code_hash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8',
    hash_type: 'type',
    args: '0xcbfbb9edb5838e2d61061c3fc69eaaa5fdbd3273'
    },
    type: {
    code_hash: '0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e',
    hash_type: 'type',
    args: '0x'
    }
    },
    out_point: {
    tx_hash: '0xe411eb6a3cf4f659461cc7a9df9ff95a72b9624bf850b9ccad0c4d7f2ab444f6',
    index: '0x0'
    },
    block_hash: '0xb468ec0a1aed1f7070fc00952453ac882dbe36b1afbfb520c822fe46b3b81dfe',
    block_number: '0x543',
    data: '0x9601000000000000',
    maximumCapacity: 100153459536n,
    since: '0x20000a00060000dc',
    depositBlockHash: '0xa1ec7dc291774bc0fc229efba4a162c099a8d88ffa7ae2fa410cc574e0701ced',
    withdrawBlockHash: '0xb468ec0a1aed1f7070fc00952453ac882dbe36b1afbfb520c822fe46b3b81dfe',
    sinceBaseValue: undefined
    }

    Here we can found the cell just created from NervosDAO withdrawing step. Let's try to consume it using locktimePool:

    > // Notice you will wait till the lock period of the cell has passed, otherwise this function would throw an error:
    > skeleton = await locktimePool.transfer(skeleton, [address], address, 100153459536n, (await rpc.get_tip_header()));
    > console.log(JSON.stringify(createTransactionFromSkeleton(skeleton), null, 2));
    {
    "version": "0x0",
    "cell_deps": [],
    "header_deps": [],
    "inputs": [],
    "outputs": [],
    "outputs_data": [],
    "witnesses": []
    }

    This might actually be a surprise: we invoked transfer method, but it does nothing! Turns out the reason here, is that we are using the same address as both transfer input, and transfer output. Lumos is smart enough to figure out that when you are using the same input and output, we don't need to perform the action so as to save certain transaction fee.

    One different question you might ask, is that we use the same address in deposit and withdraw steps, why those previous attempts work? The reason for this, is that deposited cell, or created cell in withdraw step 1 has special purposes, they represent unique actions that we want to perform, hence they are freezed in the transaction skeleton, so later when we optimize the transaction to combine inputs/outputs, we won't touch those specially created cells. On the other hand, in locktime pool design, we treat a cell with expired lock period the same as a normal cell, they really have nothing different, hence here, lumos will try to optimize the transaction, by removing the action transferring amount from an address to itself. In lumos' eye, this is a no-op.

    Now let's try the same step using a different target address:

    > skeleton = await locktimePool.transfer(skeleton, [address], "ckt1qyqx57xrsztnq7g5mlw6r998uyc2f5hm3vnsvgsaet", 100153459536n, (await rpc.get_tip_header()));
    > skeleton = await secp256k1Blake160.payFee(skeleton, address, 100000000n);
    > skeleton = secp256k1Blake160.prepareSigningEntries(skeleton);
    > skeleton.get("signingEntries").toArray();
    [
    {
    type: 'witness_args_lock',
    index: 0,
    message: '0xf01fb9988ba0265597760f50df92a56162d650b119cc95e8508079af584bdbc7'
    }
    ]

    We can generate the signature as always:

    > const signatures3 = ["0x6edde41592b41d445fabfd1b1d6854cf643bba724a338b5751827d991affa5a979d12339250bf5ade45f7f2742cba1e3de0791e37ef03914459bcdd099908ec601"];
    > const tx3 = sealTransaction(skeleton, signatures3);
    > await rpc.send_transaction(tx3);
    '0xbaa7bdd71b7ec975f5a75c49d300857981f333c4346d6d6de1297d8d9d9ce0e0'

    This is really the core part of this post, if you are not understanding this part, we recommend you to read it again, and try it in CKB by yourself. What we are showing here, is that by designing a set of common APIs, we can build a general facility, that manages many different script instances, given the fact that they share the same behavior. And it is really not only the secp256k1-blake160 single signing script that shall be managed by a wallet. Any scripts that follow certain behavior, can be treated as a cell managed in a wallet.

    Common Script

    As we show above, locktime pool is one step ahead of the journey at managing different cells/scripts with similar behaviors. But we are not stopping here, we can continue further down the path: it is mentioned above, that those cells with lock period already passed, can be thought as normal cells. Can we treat them as usual, without needing to deal with locktime pool?

    We have build common module for this. Given a set of address/configurations(since for some P2SH script, address alone won't be enough), it can manage all cells using those scripts, including cells with expired lock period. Right now this includes the following:

    • secp256k1-blake160 single signing script
    • secp256k1-blake160 multiple signing script
    • NervosDAO script(only cells in withdraw phase 2 are managed)

    And the list doesn't stop here, we are working to provide a common API specification, that once implemented, can enable common and locktime pool to support those additional scripts as well. We do hope those 2 modules can help enable a unified cell manager in lumos, in which common handles all consumable cells, while locktime pool gives insights into cells that are locked now but will be usable in the future.

    Recap

    Lumos aims to take care of the full lifecycle of your CKB dapp. In this post, we are just taking a sneak peek at all the powers. We will continue to work on documents as well as sample projects to showcase all the powers enabled by lumos. We welcome all of you to try out lumos, and tell us what you think of it. So we can continue enhancing it, to make it the beloved framework for building CKB dapps.

    + \ No newline at end of file diff --git a/docs/labs/sudtbycapsule/index.html b/docs/labs/sudtbycapsule/index.html index 9fd4160e4..533ddc88c 100644 --- a/docs/labs/sudtbycapsule/index.html +++ b/docs/labs/sudtbycapsule/index.html @@ -14,16 +14,16 @@ Write an SUDT Script by Capsule | Nervos CKB - +
    -

    Write an SUDT Script by Capsule

    Introduction

    Capsule is a set of tools for Rust developers to develop scripts on CKB which covers the entire lifecycle of script development: writing,debugging,testing and deployment. We aim to improve the development experience of Rust developers.

    In this tutorial, you will learn how to write a SUDT script using Capsule. SUDT is the abbreviation of Simple User Defined Token which defines a minimal standard that contains what’s absolutely needed for dapp developers to issue custom tokens on Nervos CKB. You can refer to RFC: Simple UDT Draft Spec for more details.

    We expect that:

    • You are Rust developers and generally familiar with software development, writing code, and running your code.
    • You are generally familiar with Nervos CKB and have completed the How to use a development blockchain
    • You are open to learning about the bleeding edge of blockchain development

    If you run into an issue on this tutorial you can create a new issue or contact us on Nervos talk or Discord.

    What you will be doing:

    • Prepare to write the SUDT script
    • Write a SUDT script
    • Testing
    • Deployment

    Prepare to write the SUDT script

    Run a dev chain and ckb-cli

    You should be able to run a dev chain and know about how to use ckb-cli to send transactions. If you do not, please refer to this tutorial:How to use a development blockchain. Please don't forget to add ckb-cli to the PATH environment variable

    Install Capsule

    Prerequisites

    The following must be installed and available to use Capsule.

    • Cargo and Rust - Capsule uses cargo to generate Rust contracts and run tests. Install Rust
    • Docker - Capsule uses docker container to reproducible build contracts. It's also used by cross. https://docs.docker.com/get-docker/
    • cross-rs - Capsule uses cross to build rust contracts. Install with
    # Do this after you installed cargo
    cargo install cross --git https://github.com/cross-rs/cross

    Note: The current user must have permission to manage Docker instances. For more information, see Manage Docker as a non-root user.

    Now you can proceed to install Capsule. It is recommended to download the binary here.

    Or you can install Capsule from it's source:

    cargo install capsule --git https://github.com/nervosnetwork/capsule.git --tag v0.1.3

    Then check if it works with the following command:

    capsule check
    (click here to view response)
    ------------------------------
    cargo installed
    docker installed
    cross-util installed
    ckb-cli installed v1.4.0 (required v1.2.0)
    ------------------------------

    Create a project

    capsule new my-sudt
    (click here to view response)
    New project "my-sudt"
    Created file "capsule.toml"
    Created file "deployment.toml"
    Created file "README.md"
    Created file "rust-toolchain"
    Created file "Cross.toml"
    Created file "Cargo.toml"
    Created file ".gitignore"
    Initialized empty Git repository in ./my-sudt/.git/
    Created "./my-sudt"
    Created tests
    New contract "my-sudt"
    Rewrite Cargo.toml
    Rewrite capsule.toml
    Done

    You can check the project’s layout:

    ls my-sudt
    (click here to view response)

    build capsule.toml Cargo.toml contracts deployment.toml migrations README.md tests

    The default contract is under my-sudt/contracts/my-sudt directory which is a normal cargo project:

    ls my-sudt/contracts/my-sudt
    (click here to view response)

    Cargo.toml src

    You can open my-sudt/contracts/my-sudt/src/main.rs to see some pre-generated code:

    (click here to view full code)
    //! Generated by capsule
    //!
    //! `main.rs` is used to define rust lang items and modules.
    //! See `entry.rs` for the `main` function.
    //! See `error.rs` for the `Error` type.

    #![no_std]
    #![cfg_attr(not(test), no_main)]

    // define modules
    mod entry;
    mod error;

    #[cfg(test)]
    extern crate alloc;

    #[cfg(not(test))]
    use ckb_std::default_alloc;
    #[cfg(not(test))]
    ckb_std::entry!(program_entry);
    #[cfg(not(test))]
    default_alloc!();

    /// program entry
    pub fn program_entry() -> i8 {
    // Call main function and return error code
    match entry::main() {
    Ok(_) => 0,
    Err(err) => err as i8,
    }
    }

    and also my-sudt/contracts/my-sudt/src/entry.rs

    (click here to view full code)
    // Import from `core` instead of from `std` since we are in no-std mode
    use core::result::Result;

    // Import heap related library from `alloc`
    // https://doc.rust-lang.org/alloc/index.html
    use alloc::{vec, vec::Vec};

    // Import CKB syscalls and structures
    // https://docs.rs/ckb-std/
    use ckb_std::{
    debug,
    high_level::{load_script, load_tx_hash},
    ckb_types::{bytes::Bytes, prelude::*},
    };

    use crate::error::Error;

    pub fn main() -> Result<(), Error> {
    // remove below examples and write your code here

    let script = load_script()?;
    let args: Bytes = script.args().unpack();
    debug!("script args is {:?}", args);

    // return an error if args is invalid
    if args.is_empty() {
    return Err(Error::MyError);
    }

    let tx_hash = load_tx_hash()?;
    debug!("tx hash is {:?}", tx_hash);

    let _buf: Vec<_> = vec![0u8; 32];

    Ok(())
    }

    // Unit tests are supported.
    #[test]
    fn test_foo() {
    assert!(true);
    }

    Build the project

    Enter into the project my-sudt and build it.

    cd my-sudt
    capsule build
    (click here to view full console log)
    Building contract demo
    $ cross build -p demo
    info: syncing channel updates for '1.69.0-x86_64-unknown-linux-gnu'
    info: latest update on 2023-04-20, rust version 1.69.0 (84c898d65 2023-04-16)
    info: downloading component 'cargo'
    info: downloading component 'rust-std'
    27.2 MiB / 27.2 MiB (100 %) 14.7 MiB/s in 1s ETA: 0s
    info: downloading component 'rustc'
    60.0 MiB / 60.0 MiB (100 %) 18.8 MiB/s in 3s ETA: 0s
    info: installing component 'cargo'
    info: installing component 'rust-std'
    27.2 MiB / 27.2 MiB (100 %) 20.7 MiB/s in 1s ETA: 0s
    info: installing component 'rustc'
    60.0 MiB / 60.0 MiB (100 %) 23.6 MiB/s in 2s ETA: 0s

    1.69.0-x86_64-unknown-linux-gnu installed - (error reading rustc version)

    info: checking for self-updates
    info: downloading self-update
    info: downloading component 'rust-std' for 'riscv64imac-unknown-none-elf'
    info: installing component 'rust-std' for 'riscv64imac-unknown-none-elf'
    Unable to find image 'nervos/ckb-riscv-gnu-toolchain:focal-20230214' locally
    focal-20230214: Pulling from nervos/ckb-riscv-gnu-toolchain
    7608715873ec: Pull complete
    a237f683deea: Pull complete
    84750871be6c: Pull complete
    3056067387e4: Pull complete
    258c66296219: Pull complete
    e8ea3d081562: Pull complete
    32afd1383aeb: Pull complete
    6f6c3bd439ca: Pull complete
    Digest: sha256:5732afe996b2b88a37ed3c0e4deb948e9d2a6936fb4b52d4e7a0dc5ad330c306
    Status: Downloaded newer image for nervos/ckb-riscv-gnu-toolchain:focal-20230214
    Compiling cfg-if v1.0.0
    Compiling cc v1.0.79
    Compiling buddy-alloc v0.5.1
    Compiling molecule v0.7.5
    Compiling ckb-standalone-types v0.1.2
    Compiling ckb-std v0.13.0
    Compiling my-sudt v0.1.0 (./my-sudt/contracts/my-sudt)
    Finished dev [unoptimized + debuginfo] target(s) in 33.53s
    Done
    • Note: You might see some warning log like <jemalloc>: MADV_DONTNEED does not work (memset will be used instead), this isn't an abnormal behaviour, and won't make any trouble to us. It is caused by jemalloc under QEMU env, which is expected if you're running non-native docker containers under aarch64 architechture(for example an x86-64 container).

    You will find a new generated contract binary in the build/debug directory:

    ls build/debug
    (click here to view response)
    my-sudt

    You're all done? Great, let's get coding.

    Write a SUDT script

    SUDT scripts can be in owner mode and normal mode which include different verification rules, we should deal with that when we're coding.

    • owner mode:If one of the transaction input has a lock script matching the SUDT script argument, the SUDT script will be in owner mode. We don’t need to perform checks, the owner can perform any operations such as issuing more SUDTs or burning SUDTs.
    • normal mode:Otherwise, the SUDT script will be in normal mode. We need to ensure the sum of all inputs’ capacity is not smaller than the sum of all outputs capacity. Please note that only one type of SUDT can be issued for each unique lock script.

    The script is consisted of four parts:load script、check inputs、load inputs / outputs UDT amount、error handling. We should check the used libraries before coding.

    Check the used libraries

    Open contracts/my-sudt/Cargo.toml, we already have a dependency:

    [dependencies]
    ckb-std = "0.13"
    • ckb-std is a crate used to handling CKB syscalls.
    • ckb-standalone-types is a crate which re-exported as the ckb_std::ckb_types provides the definition of CKB structures.

    You may refer to Rust libraries for more useful crates. We can only use crates which supports no-std in scripts.

    Load Script

    At the beginning of the script, we need to check the SUDT’s mode, if it is owner mode, we simply skip the verification code and return 0, which represents the verification is successful, otherwise we check the amount of UDT.

    To achieve this, we need to load args of the current script, which the generated code already did for us. So we just remove the unused lines from the main function.

    In the code below, we load the current script(SUDT)'s args field, and invoke check_owner_mode which we have not defined yet.

    Notice since we are using no-std Rust, we can't directly use the std in the code. Instead, we need to import the Vec struct from the alloc crate, which is a rust builtin crate contains heap related structs.

    // contracts/my-sudt/src/entry.rs
    fn main() -> Result<(), Error> {
    // load current script
    // check verification branch is owner mode or normal mode
    let script = load_script()?;
    let args: Bytes = script.args().unpack();

    // unpack the Script#args field
    let args: Vec<u8> = script.args().unpack();

    // return success if owner mode is true
    if check_owner_mode(&args)? {
    return Ok(());
    }

    // more verifications ...
    return Ok(());
    }

    Check inputs

    Now we should check the owner mode status by defining the check_owner_mode function:

    We need to load every input's lock hash and compare it to the script's args. If we find an input's lock hash corresponds to the script's args, we are in owner mode; otherwise, we iterate all the inputs and finally got an IndexOutOfBound error, which means we are in normal mode.

    We use load_cell_lock_hash to load cell's lock hash from CKB. The Source::Input and i args denote we load input from i-th inputs.

    The error SysError::IndexOutOfBound represents that we request an index that does not exist, which means we cannot find a matched input cell, so we return Ok(false).

    use ckb_std::{
    high_level::{load_cell_lock_hash},
    ckb_constants::Source,
    };

    fn check_owner_mode(args: &Bytes) -> Result<bool, Error> {
    // With owner lock script extracted, we will look through each input in the
    // current transaction to see if any unlocked cell uses owner lock.
    for i in 0.. {
    // check input's lock_hash with script args
    let lock_hash = match load_cell_lock_hash(
    i,
    Source::Input,
    ) {
    Ok(lock_hash) => lock_hash,
    Err(SysError::IndexOutOfBound) => return Ok(false),
    Err(err) => return Err(err.into()),
    };
    // invalid length of loaded data
    if args[..] == lock_hash[..] {
    return Ok(true);
    }
    }
    Ok(false)
    }

    Load inputs / outputs UDT amount

    If the owner mode is false, we should continue the verification: check the total input SUDT amount is greater than or equals to the total output SUDT amount.

    • Define two methods:

      • collect_inputs_amount :collect total input SUDT amount
      • collect_outputs_amount :collect total output SUDT amount.
    • Since we aim to read all SUDT inputs which type is the current script(SUDT), we can use Source::GroupInput instead of Source::Input.

    • Source::GroupInput and i means load the i-th input from the "input group".

    Tips:

    • By using Source::GroupInput in the syscall, CKB verification engine will automatically group the inputs/outputs by lock and type script.
    • The data type of SUDT is u128, which is 16 bytes so we use the 16 bytes buffer.
    • i-th input of Source::Input(index of all inputs) may be or may not be the same cell of the i-th input of Source::GroupInput (index of inputs which lock/type is the current script).
    const UDT_LEN: usize = 16;

    fn collect_inputs_amount() -> Result<u128, Error> {
    // let's loop through all input cells containing current UDTs,
    // and gather the sum of all input tokens.
    let mut inputs_amount: u128 = 0;
    let mut buf = [0u8; UDT_LEN];

    // u128 is 16 bytes
    for i in 0.. {
    let data = match load_cell_data(i, Source::GroupInput) {
    Ok(data) => data,
    Err(SysError::IndexOutOfBound) => break,
    Err(err) => return Err(err.into()),
    };

    if data.len() != UDT_LEN {
    return Err(Error::Encoding);
    }
    buf.copy_from_slice(&data);
    inputs_amount += u128::from_le_bytes(buf);
    }
    Ok(inputs_amount)
    }

    The collect_outputs_amount function is similar, except we load data from outputs:

    fn collect_outputs_amount() -> Result<u128, Error> {
    // With the sum of all input UDT tokens gathered, let's now iterate through
    // output cells to grab the sum of all output UDT tokens.
    let mut outputs_amount: u128 = 0;
    let mut i = 0;

    // u128 is 16 bytes
    let mut buf = [0u8; UDT_LEN];
    for i in 0.. {
    let data = match load_cell_data(i, Source::GroupOutput) {
    Ok(data) => data,
    Err(SysError::IndexOutOfBound) => break,
    Err(err) => return Err(err.into()),
    };

    if data.len() != UDT_LEN {
    return Err(Error::Encoding);
    }
    buf.copy_from_slice(&data);
    outputs_amount += u128::from_le_bytes(buf);
    }
    Ok(outputs_amount)
    }
    • Update the error.rs to add an error stands for "Not enough amount"
    use ckb_std::error::SysError;

    /// Error
    #[repr(i8)]
    pub enum Error {
    IndexOutOfBound = 1,
    ItemMissing,
    LengthNotEnough,
    Encoding,
    // Add customized errors here...
    Amount,
    }

    impl From<SysError> for Error {
    fn from(err: SysError) -> Self {
    use SysError::*;
    match err {
    IndexOutOfBound => Self::IndexOutOfBound,
    ItemMissing => Self::ItemMissing,
    LengthNotEnough(_) => Self::LengthNotEnough,
    Encoding => Self::Encoding,
    Unknown(err_code) => panic!("unexpected sys error {}", err_code),
    }
    }
    }
    • Update the main function in entry.rs to check inputs / outputs UDT amount:
    pub fn main() -> Result<(), Error> {
    // remove below examples and write your code here

    let script = load_script()?;
    let args: Bytes = script.args().unpack();
    debug!("script args is {:?}", args);

    // return an error if args is invalid
    if args.is_empty() {
    return Err(Error::LengthNotEnough);
    }

    let tx_hash = load_tx_hash()?;
    debug!("tx hash is {:?}", tx_hash);

    let _buf: Vec<_> = vec![0u8; 32];

    // return success if owner mode is true
    if check_owner_mode(&args)? {
    return Ok(())
    }

    let inputs_amount = collect_inputs_amount()?;
    let outputs_amount = collect_outputs_amount()?;

    if inputs_amount < outputs_amount {
    return Err(Error::Amount);
    }
    // more verifications ...
    Ok(())
    }

    Use Iterator to query cells

    In the previous code, we use for loop to iterate inputs and outputs, since iteration over cells is a common pattern in CKB programming, ckb-std provides a high-level interface QueryIter to handle it.

    QueryIter needs two args, the first is a loading function, the seconds is Source. This is an example to load all grouped inputs cells data QueryIter::new(load_cell_data, Source::GroupInput).

    Rewrite our functions in entry.rs:


    // import this
    use ckb_std::high_level::QueryIter;

    // Other codes...

    fn check_owner_mode(args: &Bytes) -> Result<bool, Error> {
    // With owner lock script extracted, we will look through each input in the
    // current transaction to see if any unlocked cell uses owner lock.
    let is_owner_mode = QueryIter::new(load_cell_lock_hash, Source::Input)
    .find(|lock_hash| args[..] == lock_hash[..]).is_some();
    Ok(is_owner_mode)
    }

    fn collect_inputs_amount() -> Result<u128, Error> {
    // let's loop through all input cells containing current UDTs,
    // and gather the sum of all input tokens.
    let mut buf = [0u8; UDT_LEN];

    let udt_list = QueryIter::new(load_cell_data, Source::GroupInput)
    .map(|data|{
    if data.len() == UDT_LEN {
    buf.copy_from_slice(&data);
    // u128 is 16 bytes
    Ok(u128::from_le_bytes(buf))
    } else {
    Err(Error::Encoding)
    }
    }).collect::<Result<Vec<_>, Error>>()?;
    Ok(udt_list.into_iter().sum::<u128>())
    }

    fn collect_outputs_amount() -> Result<u128, Error> {
    // With the sum of all input UDT tokens gathered, let's now iterate through
    // output cells to grab the sum of all output UDT tokens.
    let mut buf = [0u8; UDT_LEN];

    let udt_list = QueryIter::new(load_cell_data, Source::GroupOutput)
    .map(|data|{
    if data.len() == UDT_LEN {
    buf.copy_from_slice(&data);
    // u128 is 16 bytes
    Ok(u128::from_le_bytes(buf))
    } else {
    Err(Error::Encoding)
    }
    }).collect::<Result<Vec<_>, Error>>()?;
    Ok(udt_list.into_iter().sum::<u128>())
    }

    Now we have finished the SUDT script, you may refer to Full code of my-sudt to check the full script code. If you are interested, you may also check the SUDT script written in C.

    Build the project

    Run capsule build under the project directory to build the script.If no error occurred, we can find the script binary at my-usdt/build/debug/my-sudt.

    Testing

    We will use the ckb-testtool crate to construct transactions and context for our testing.

    Check the default tests

    When create the project my-sudt,capsule have generated the default tests.The default tests create mock cells and unlock them for testing.

    Use capsule build under the project directory to build the script, +

    Write an SUDT Script by Capsule

    Introduction

    Capsule is a set of tools for Rust developers to develop scripts on CKB which covers the entire lifecycle of script development: writing,debugging,testing and deployment. We aim to improve the development experience of Rust developers.

    In this tutorial, you will learn how to write a SUDT script using Capsule. SUDT is the abbreviation of Simple User Defined Token which defines a minimal standard that contains what’s absolutely needed for dapp developers to issue custom tokens on Nervos CKB. You can refer to RFC: Simple UDT Draft Spec for more details.

    We expect that:

    • You are Rust developers and generally familiar with software development, writing code, and running your code.
    • You are generally familiar with Nervos CKB and have completed the How to use a development blockchain
    • You are open to learning about the bleeding edge of blockchain development

    If you run into an issue on this tutorial you can create a new issue or contact us on Nervos talk or Discord.

    What you will be doing:

    • Prepare to write the SUDT script
    • Write a SUDT script
    • Testing
    • Deployment

    Prepare to write the SUDT script

    Run a dev chain and ckb-cli

    You should be able to run a dev chain and know about how to use ckb-cli to send transactions. If you do not, please refer to this tutorial:How to use a development blockchain. Please don't forget to add ckb-cli to the PATH environment variable

    Install Capsule

    Prerequisites

    The following must be installed and available to use Capsule.

    • Cargo and Rust - Capsule uses cargo to generate Rust contracts and run tests. Install Rust
    • Docker - Capsule uses docker container to reproducible build contracts. It's also used by cross. https://docs.docker.com/get-docker/
    • cross-rs - Capsule uses cross to build rust contracts. Install with
    # Do this after you installed cargo
    cargo install cross --git https://github.com/cross-rs/cross

    Note: The current user must have permission to manage Docker instances. For more information, see Manage Docker as a non-root user.

    Now you can proceed to install Capsule. It is recommended to download the binary here.

    Or you can install Capsule from it's source:

    cargo install capsule --git https://github.com/nervosnetwork/capsule.git --tag v0.1.3

    Then check if it works with the following command:

    capsule check
    (click here to view response)
    ------------------------------
    cargo installed
    docker installed
    cross-util installed
    ckb-cli installed v1.4.0 (required v1.2.0)
    ------------------------------

    Create a project

    capsule new my-sudt
    (click here to view response)
    New project "my-sudt"
    Created file "capsule.toml"
    Created file "deployment.toml"
    Created file "README.md"
    Created file "rust-toolchain"
    Created file "Cross.toml"
    Created file "Cargo.toml"
    Created file ".gitignore"
    Initialized empty Git repository in ./my-sudt/.git/
    Created "./my-sudt"
    Created tests
    New contract "my-sudt"
    Rewrite Cargo.toml
    Rewrite capsule.toml
    Done

    You can check the project’s layout:

    ls my-sudt
    (click here to view response)

    build capsule.toml Cargo.toml contracts deployment.toml migrations README.md tests

    The default contract is under my-sudt/contracts/my-sudt directory which is a normal cargo project:

    ls my-sudt/contracts/my-sudt
    (click here to view response)

    Cargo.toml src

    You can open my-sudt/contracts/my-sudt/src/main.rs to see some pre-generated code:

    (click here to view full code)
    //! Generated by capsule
    //!
    //! `main.rs` is used to define rust lang items and modules.
    //! See `entry.rs` for the `main` function.
    //! See `error.rs` for the `Error` type.

    #![no_std]
    #![cfg_attr(not(test), no_main)]

    // define modules
    mod entry;
    mod error;

    #[cfg(test)]
    extern crate alloc;

    #[cfg(not(test))]
    use ckb_std::default_alloc;
    #[cfg(not(test))]
    ckb_std::entry!(program_entry);
    #[cfg(not(test))]
    default_alloc!();

    /// program entry
    pub fn program_entry() -> i8 {
    // Call main function and return error code
    match entry::main() {
    Ok(_) => 0,
    Err(err) => err as i8,
    }
    }

    and also my-sudt/contracts/my-sudt/src/entry.rs

    (click here to view full code)
    // Import from `core` instead of from `std` since we are in no-std mode
    use core::result::Result;

    // Import heap related library from `alloc`
    // https://doc.rust-lang.org/alloc/index.html
    use alloc::{vec, vec::Vec};

    // Import CKB syscalls and structures
    // https://docs.rs/ckb-std/
    use ckb_std::{
    debug,
    high_level::{load_script, load_tx_hash},
    ckb_types::{bytes::Bytes, prelude::*},
    };

    use crate::error::Error;

    pub fn main() -> Result<(), Error> {
    // remove below examples and write your code here

    let script = load_script()?;
    let args: Bytes = script.args().unpack();
    debug!("script args is {:?}", args);

    // return an error if args is invalid
    if args.is_empty() {
    return Err(Error::MyError);
    }

    let tx_hash = load_tx_hash()?;
    debug!("tx hash is {:?}", tx_hash);

    let _buf: Vec<_> = vec![0u8; 32];

    Ok(())
    }

    // Unit tests are supported.
    #[test]
    fn test_foo() {
    assert!(true);
    }

    Build the project

    Enter into the project my-sudt and build it.

    cd my-sudt
    capsule build
    (click here to view full console log)
    Building contract demo
    $ cross build -p demo
    info: syncing channel updates for '1.69.0-x86_64-unknown-linux-gnu'
    info: latest update on 2023-04-20, rust version 1.69.0 (84c898d65 2023-04-16)
    info: downloading component 'cargo'
    info: downloading component 'rust-std'
    27.2 MiB / 27.2 MiB (100 %) 14.7 MiB/s in 1s ETA: 0s
    info: downloading component 'rustc'
    60.0 MiB / 60.0 MiB (100 %) 18.8 MiB/s in 3s ETA: 0s
    info: installing component 'cargo'
    info: installing component 'rust-std'
    27.2 MiB / 27.2 MiB (100 %) 20.7 MiB/s in 1s ETA: 0s
    info: installing component 'rustc'
    60.0 MiB / 60.0 MiB (100 %) 23.6 MiB/s in 2s ETA: 0s

    1.69.0-x86_64-unknown-linux-gnu installed - (error reading rustc version)

    info: checking for self-updates
    info: downloading self-update
    info: downloading component 'rust-std' for 'riscv64imac-unknown-none-elf'
    info: installing component 'rust-std' for 'riscv64imac-unknown-none-elf'
    Unable to find image 'nervos/ckb-riscv-gnu-toolchain:focal-20230214' locally
    focal-20230214: Pulling from nervos/ckb-riscv-gnu-toolchain
    7608715873ec: Pull complete
    a237f683deea: Pull complete
    84750871be6c: Pull complete
    3056067387e4: Pull complete
    258c66296219: Pull complete
    e8ea3d081562: Pull complete
    32afd1383aeb: Pull complete
    6f6c3bd439ca: Pull complete
    Digest: sha256:5732afe996b2b88a37ed3c0e4deb948e9d2a6936fb4b52d4e7a0dc5ad330c306
    Status: Downloaded newer image for nervos/ckb-riscv-gnu-toolchain:focal-20230214
    Compiling cfg-if v1.0.0
    Compiling cc v1.0.79
    Compiling buddy-alloc v0.5.1
    Compiling molecule v0.7.5
    Compiling ckb-standalone-types v0.1.2
    Compiling ckb-std v0.13.0
    Compiling my-sudt v0.1.0 (./my-sudt/contracts/my-sudt)
    Finished dev [unoptimized + debuginfo] target(s) in 33.53s
    Done
    • Note: You might see some warning log like <jemalloc>: MADV_DONTNEED does not work (memset will be used instead), this isn't an abnormal behaviour, and won't make any trouble to us. It is caused by jemalloc under QEMU env, which is expected if you're running non-native docker containers under aarch64 architecture(for example an x86-64 container).

    You will find a new generated contract binary in the build/debug directory:

    ls build/debug
    (click here to view response)
    my-sudt

    You're all done? Great, let's get coding.

    Write a SUDT script

    SUDT scripts can be in owner mode and normal mode which include different verification rules, we should deal with that when we're coding.

    • owner mode:If one of the transaction input has a lock script matching the SUDT script argument, the SUDT script will be in owner mode. We don’t need to perform checks, the owner can perform any operations such as issuing more SUDTs or burning SUDTs.
    • normal mode:Otherwise, the SUDT script will be in normal mode. We need to ensure the sum of all inputs’ capacity is not smaller than the sum of all outputs capacity. Please note that only one type of SUDT can be issued for each unique lock script.

    The script is consisted of four parts:load script、check inputs、load inputs / outputs UDT amount、error handling. We should check the used libraries before coding.

    Check the used libraries

    Open contracts/my-sudt/Cargo.toml, we already have a dependency:

    [dependencies]
    ckb-std = "0.13"
    • ckb-std is a crate used to handling CKB syscalls.
    • ckb-standalone-types is a crate which re-exported as the ckb_std::ckb_types provides the definition of CKB structures.

    You may refer to Rust libraries for more useful crates. We can only use crates which supports no-std in scripts.

    Load Script

    At the beginning of the script, we need to check the SUDT’s mode, if it is owner mode, we simply skip the verification code and return 0, which represents the verification is successful, otherwise we check the amount of UDT.

    To achieve this, we need to load args of the current script, which the generated code already did for us. So we just remove the unused lines from the main function.

    In the code below, we load the current script(SUDT)'s args field, and invoke check_owner_mode which we have not defined yet.

    Notice since we are using no-std Rust, we can't directly use the std in the code. Instead, we need to import the Vec struct from the alloc crate, which is a rust builtin crate contains heap related structs.

    // contracts/my-sudt/src/entry.rs
    fn main() -> Result<(), Error> {
    // load current script
    // check verification branch is owner mode or normal mode
    let script = load_script()?;
    let args: Bytes = script.args().unpack();

    // unpack the Script#args field
    let args: Vec<u8> = script.args().unpack();

    // return success if owner mode is true
    if check_owner_mode(&args)? {
    return Ok(());
    }

    // more verifications ...
    return Ok(());
    }

    Check inputs

    Now we should check the owner mode status by defining the check_owner_mode function:

    We need to load every input's lock hash and compare it to the script's args. If we find an input's lock hash corresponds to the script's args, we are in owner mode; otherwise, we iterate all the inputs and finally got an IndexOutOfBound error, which means we are in normal mode.

    We use load_cell_lock_hash to load cell's lock hash from CKB. The Source::Input and i args denote we load input from i-th inputs.

    The error SysError::IndexOutOfBound represents that we request an index that does not exist, which means we cannot find a matched input cell, so we return Ok(false).

    use ckb_std::{
    high_level::{load_cell_lock_hash},
    ckb_constants::Source,
    };

    fn check_owner_mode(args: &Bytes) -> Result<bool, Error> {
    // With owner lock script extracted, we will look through each input in the
    // current transaction to see if any unlocked cell uses owner lock.
    for i in 0.. {
    // check input's lock_hash with script args
    let lock_hash = match load_cell_lock_hash(
    i,
    Source::Input,
    ) {
    Ok(lock_hash) => lock_hash,
    Err(SysError::IndexOutOfBound) => return Ok(false),
    Err(err) => return Err(err.into()),
    };
    // invalid length of loaded data
    if args[..] == lock_hash[..] {
    return Ok(true);
    }
    }
    Ok(false)
    }

    Load inputs / outputs UDT amount

    If the owner mode is false, we should continue the verification: check the total input SUDT amount is greater than or equals to the total output SUDT amount.

    • Define two methods:

      • collect_inputs_amount :collect total input SUDT amount
      • collect_outputs_amount :collect total output SUDT amount.
    • Since we aim to read all SUDT inputs which type is the current script(SUDT), we can use Source::GroupInput instead of Source::Input.

    • Source::GroupInput and i means load the i-th input from the "input group".

    Tips:

    • By using Source::GroupInput in the syscall, CKB verification engine will automatically group the inputs/outputs by lock and type script.
    • The data type of SUDT is u128, which is 16 bytes so we use the 16 bytes buffer.
    • i-th input of Source::Input(index of all inputs) may be or may not be the same cell of the i-th input of Source::GroupInput (index of inputs which lock/type is the current script).
    const UDT_LEN: usize = 16;

    fn collect_inputs_amount() -> Result<u128, Error> {
    // let's loop through all input cells containing current UDTs,
    // and gather the sum of all input tokens.
    let mut inputs_amount: u128 = 0;
    let mut buf = [0u8; UDT_LEN];

    // u128 is 16 bytes
    for i in 0.. {
    let data = match load_cell_data(i, Source::GroupInput) {
    Ok(data) => data,
    Err(SysError::IndexOutOfBound) => break,
    Err(err) => return Err(err.into()),
    };

    if data.len() != UDT_LEN {
    return Err(Error::Encoding);
    }
    buf.copy_from_slice(&data);
    inputs_amount += u128::from_le_bytes(buf);
    }
    Ok(inputs_amount)
    }

    The collect_outputs_amount function is similar, except we load data from outputs:

    fn collect_outputs_amount() -> Result<u128, Error> {
    // With the sum of all input UDT tokens gathered, let's now iterate through
    // output cells to grab the sum of all output UDT tokens.
    let mut outputs_amount: u128 = 0;
    let mut i = 0;

    // u128 is 16 bytes
    let mut buf = [0u8; UDT_LEN];
    for i in 0.. {
    let data = match load_cell_data(i, Source::GroupOutput) {
    Ok(data) => data,
    Err(SysError::IndexOutOfBound) => break,
    Err(err) => return Err(err.into()),
    };

    if data.len() != UDT_LEN {
    return Err(Error::Encoding);
    }
    buf.copy_from_slice(&data);
    outputs_amount += u128::from_le_bytes(buf);
    }
    Ok(outputs_amount)
    }
    • Update the error.rs to add an error stands for "Not enough amount"
    use ckb_std::error::SysError;

    /// Error
    #[repr(i8)]
    pub enum Error {
    IndexOutOfBound = 1,
    ItemMissing,
    LengthNotEnough,
    Encoding,
    // Add customized errors here...
    Amount,
    }

    impl From<SysError> for Error {
    fn from(err: SysError) -> Self {
    use SysError::*;
    match err {
    IndexOutOfBound => Self::IndexOutOfBound,
    ItemMissing => Self::ItemMissing,
    LengthNotEnough(_) => Self::LengthNotEnough,
    Encoding => Self::Encoding,
    Unknown(err_code) => panic!("unexpected sys error {}", err_code),
    }
    }
    }
    • Update the main function in entry.rs to check inputs / outputs UDT amount:
    pub fn main() -> Result<(), Error> {
    // remove below examples and write your code here

    let script = load_script()?;
    let args: Bytes = script.args().unpack();
    debug!("script args is {:?}", args);

    // return an error if args is invalid
    if args.is_empty() {
    return Err(Error::LengthNotEnough);
    }

    let tx_hash = load_tx_hash()?;
    debug!("tx hash is {:?}", tx_hash);

    let _buf: Vec<_> = vec![0u8; 32];

    // return success if owner mode is true
    if check_owner_mode(&args)? {
    return Ok(())
    }

    let inputs_amount = collect_inputs_amount()?;
    let outputs_amount = collect_outputs_amount()?;

    if inputs_amount < outputs_amount {
    return Err(Error::Amount);
    }
    // more verifications ...
    Ok(())
    }

    Use Iterator to query cells

    In the previous code, we use for loop to iterate inputs and outputs, since iteration over cells is a common pattern in CKB programming, ckb-std provides a high-level interface QueryIter to handle it.

    QueryIter needs two args, the first is a loading function, the seconds is Source. This is an example to load all grouped inputs cells data QueryIter::new(load_cell_data, Source::GroupInput).

    Rewrite our functions in entry.rs:


    // import this
    use ckb_std::high_level::QueryIter;

    // Other codes...

    fn check_owner_mode(args: &Bytes) -> Result<bool, Error> {
    // With owner lock script extracted, we will look through each input in the
    // current transaction to see if any unlocked cell uses owner lock.
    let is_owner_mode = QueryIter::new(load_cell_lock_hash, Source::Input)
    .find(|lock_hash| args[..] == lock_hash[..]).is_some();
    Ok(is_owner_mode)
    }

    fn collect_inputs_amount() -> Result<u128, Error> {
    // let's loop through all input cells containing current UDTs,
    // and gather the sum of all input tokens.
    let mut buf = [0u8; UDT_LEN];

    let udt_list = QueryIter::new(load_cell_data, Source::GroupInput)
    .map(|data|{
    if data.len() == UDT_LEN {
    buf.copy_from_slice(&data);
    // u128 is 16 bytes
    Ok(u128::from_le_bytes(buf))
    } else {
    Err(Error::Encoding)
    }
    }).collect::<Result<Vec<_>, Error>>()?;
    Ok(udt_list.into_iter().sum::<u128>())
    }

    fn collect_outputs_amount() -> Result<u128, Error> {
    // With the sum of all input UDT tokens gathered, let's now iterate through
    // output cells to grab the sum of all output UDT tokens.
    let mut buf = [0u8; UDT_LEN];

    let udt_list = QueryIter::new(load_cell_data, Source::GroupOutput)
    .map(|data|{
    if data.len() == UDT_LEN {
    buf.copy_from_slice(&data);
    // u128 is 16 bytes
    Ok(u128::from_le_bytes(buf))
    } else {
    Err(Error::Encoding)
    }
    }).collect::<Result<Vec<_>, Error>>()?;
    Ok(udt_list.into_iter().sum::<u128>())
    }

    Now we have finished the SUDT script, you may refer to Full code of my-sudt to check the full script code. If you are interested, you may also check the SUDT script written in C.

    Build the project

    Run capsule build under the project directory to build the script.If no error occurred, we can find the script binary at my-usdt/build/debug/my-sudt.

    Testing

    We will use the ckb-testtool crate to construct transactions and context for our testing.

    Check the default tests

    When create the project my-sudt,capsule have generated the default tests.The default tests create mock cells and unlock them for testing.

    Use capsule build under the project directory to build the script, then use capsule test to run the default tests.We will find the error message:

    failures:

    ---- tests::test_basic stdout ----
    thread 'tests::test_basic' panicked at 'pass verification: Error { kind: ValidationFailure(4)Script }', tests/src/tests.rs:52:5
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


    failures:
    tests::test_basic

    The error number 4 in Error { kind: ValidationFailure(4) refers to Error::Encoding, which means the cell’s data type is not u128.

    Let’s check the default tests code tests/src/tests.rs to find out how to write the tests, then we can write new tests adapted my-sudt

    • In the beginning part, initialize the Context which is a structure to simulate the chain environment. We can use Context to deploy exists cells and mock block headers.deploy_contract will return the out_point of the script.
    // deploy contract
    let mut context = Context::default();
    let contract_bin: Bytes = Loader::default().load_binary("my-sudt");
    let contract_out_point = context.deploy_contract(contract_bin);
    • Then build_script is called with the script's out_point , this function returns the Script which uses our script as the code. create_cell creates an existing cell in the context, which uses our script as the lock_script.

    Please note the default tests assume the script is a lock_script, but in our case, my-sudt is a type_script. We'll fix it later.

    // prepare scripts
    let lock_script = context.build_script(&contract_out_point, Default::default()).expect("script");
    let lock_script_dep = CellDep::new_builder().out_point(contract_out_point).build();

    // prepare cells
    let input_out_point = context.create_cell(
    CellOutput::new_builder()
    .capacity(1000u64.pack())
    .lock(lock_script.clone())
    .build(),
    Bytes::new(),
    );
    let input = CellInput::new_builder()
    .previous_output(input_out_point)
    .build();
    • After that, build two outputs cells and a transaction structure.It is necessary to include cell_deps field in the transaction which should contain all the referenced scripts, in this case, we can only refer to my-sudt. complete_tx also implement cell_deps, while the field is already completed manually, this line is not necessary.

    Please note that the transaction's outputs_data must have the same length with the outputs, even the data is empty.

    let outputs = vec![
    CellOutput::new_builder()
    .capacity(500u64.pack())
    .lock(lock_script.clone())
    .build(),
    CellOutput::new_builder()
    .capacity(500u64.pack())
    .lock(lock_script)
    .build(),
    ];

    let outputs_data = vec![Bytes::new(); 2];

    // build transaction
    let tx = TransactionBuilder::default()
    .input(input)
    .outputs(outputs)
    .outputs_data(outputs_data.pack())
    .cell_dep(lock_script_dep)
    .build();
    let tx = context.complete_tx(tx);
    • Finally, verify the transaction:
    // run
    context
    .verify_tx(&tx, MAX_CYCLES)
    .expect("pass verification");

    Write new tests

    We should create mock SUDT cells and spend them for testing SUDT verification. As my-sudt script is a type_script we need another script as lock_script for mock cells, it is recommended to use always success script returned 0. always success is built-in in the ckb-testtool.

    use ckb_testtool::{builtin::ALWAYS_SUCCESS, context::Context};

    // deploy always_success script
    let always_success_out_point = context.deploy_contract(ALWAYS_SUCCESS.clone());

    Before writing the code, let's think about our test cases:

    1. Return success when input tokens equals to output tokens.
    2. Return success when input tokens is greater than output tokens.
    3. Return failure when input tokens is less than output tokens.
    4. Return success when input tokens is less than output tokens with owner mode activated.
    • Define build_test_context to build transactions. There are three args:

      • The data type of inputs_token and outputs_token is u128. The function can generate SUDT inputs cells and outputs cells according to the two args.
      • is_owner_mode refers to the current transaction is in SUDT owner mode or normal mode.
    • Deploy the SUDT and always-success scripts.

    Please note that if is_owner_mode is true, we will set lock_script's lock_hash as owner script hash; otherwise, we will set [0u8; 32] which implies can't enter into owner mode.

    fn build_test_context(
    inputs_token: Vec<u128>,
    outputs_token: Vec<u128>,
    is_owner_mode: bool,
    ) -> (Context, TransactionView) {
    // deploy my-sudt script
    let mut context = Context::default();
    let sudt_bin: Bytes = Loader::default().load_binary("my-sudt");
    let sudt_out_point = context.deploy_contract(sudt_bin);
    // deploy always_success script
    let always_success_out_point = context.deploy_contract(ALWAYS_SUCCESS.clone());

    // build lock script
    let lock_script = context
    .build_script(&always_success_out_point, Default::default())
    .expect("script");
    let lock_script_dep = CellDep::new_builder()
    .out_point(always_success_out_point)
    .build();

    // build sudt script
    let sudt_script_args: Bytes = if is_owner_mode {
    // use always_success script hash as owner's lock
    let lock_hash: [u8; 32] = lock_script.calc_script_hash().unpack();
    lock_hash.to_vec().into()
    } else {
    // use zero hash as owner's lock which implies we can never enter owner mode
    [0u8; 32].to_vec().into()
    };

    let sudt_script = context
    .build_script(&sudt_out_point, sudt_script_args)
    .expect("script");
    let sudt_script_dep = CellDep::new_builder().out_point(sudt_out_point).build();

    //... more code below
    //}
    • Build inputs and outputs according to the inputs_token and outputs_token
    // ...
    // prepare inputs
    // assign 1000 Bytes to per input
    let input_ckb = Capacity::bytes(1000).unwrap().as_u64();
    let inputs = inputs_token.iter().map(|token| {
    let input_out_point = context.create_cell(
    CellOutput::new_builder()
    .capacity(input_ckb.pack())
    .lock(lock_script.clone())
    .type_(Some(sudt_script.clone()).pack())
    .build(),
    token.to_le_bytes().to_vec().into(),
    );
    let input = CellInput::new_builder()
    .previous_output(input_out_point)
    .build();
    input
    });

    // prepare outputs
    let output_ckb = input_ckb * inputs_token.len() as u64 / outputs_token.len() as u64;
    let outputs = outputs_token.iter().map(|_token| {
    CellOutput::new_builder()
    .capacity(output_ckb.pack())
    .lock(lock_script.clone())
    .type_(Some(sudt_script.clone()).pack())
    .build()
    });
    let outputs_data: Vec<_> = outputs_token
    .iter()
    .map(|token| Bytes::from(token.to_le_bytes().to_vec()))
    .collect();
    // ...
    • Finally construct the transaction and return it with context.
    // build transaction
    let tx = TransactionBuilder::default()
    .inputs(inputs)
    .outputs(outputs)
    .outputs_data(outputs_data.pack())
    .cell_dep(lock_script_dep)
    .cell_dep(sudt_script_dep)
    .build();
    (context, tx)

    Now the helper function build_test_context is finished, we can write our tests:

    #[test]
    fn test_basic() {
    let (mut context, tx) = build_test_context(vec![1000], vec![400, 600], false);
    let tx = context.complete_tx(tx);

    // run
    context
    .verify_tx(&tx, MAX_CYCLES)
    .expect("pass verification");
    }

    #[test]
    fn test_destroy_udt() {
    let (mut context, tx) = build_test_context(vec![1000], vec![800, 100, 50], false);
    let tx = context.complete_tx(tx);

    // run
    context
    .verify_tx(&tx, MAX_CYCLES)
    .expect("pass verification");
    }

    #[test]
    fn test_create_sudt_without_owner_mode() {
    let (mut context, tx) = build_test_context(vec![1000], vec![1200], false);
    let tx = context.complete_tx(tx);

    // run
    let err = context.verify_tx(&tx, MAX_CYCLES).unwrap_err();
    assert_error_eq!(err, ScriptError::ValidationFailure(ERROR_AMOUNT));
    }

    #[test]
    fn test_create_sudt_with_owner_mode() {
    let (mut context, tx) = build_test_context(vec![1000], vec![1200], true);
    let tx = context.complete_tx(tx);

    // run
    context
    .verify_tx(&tx, MAX_CYCLES)
    .expect("pass verification");
    }

    You may refer to my-sudt tests for the full tests. Run capsule test all tests will be passed.

    Deployment

    Run a dev chain and ckb-cli

    You should be running a dev chain and know about how to use ckb-cli to send transactions before deployment.

    Deploy

    1. Update the deployment configurations

      Open deployment.toml :

      • cells describes which cells to be deployed.

        • name: Define the reference name used in the deployment configuration.
        • enable_type_id : If it is set to true means create a type_id for the cell.
        • location : Define the script binary path.
      • dep_groups describes which dep_groups to be created. Dep Group is a cell which bundles several cells as its members. When a dep group cell is used in cell_deps, it has the same effect as adding all its members into cell_deps. In our case, we don’t need dep_groups.

      • lock describes the lock field of the new deployed cells.It is recommended to set lock to the deployer's address(an address that you can unlock) in the dev chain and in the testnet, which is easier to update the script.

    2. Uncomment the configuration file and replace the cell name and location with my-usdt.

    # [[cells]]
    # name = "my_cell"
    # enable_type_id = false
    # location = { file = "build/release/my_cell" }

    # # Dep group cells
    # [[dep_groups]]
    # name = "my_dep_group"
    # cells = [
    # "my_cell",
    # "secp256k1_data"
    # ]

    # # Replace with your own lock if you want to unlock deployed cells.
    # # The deployment code_hash is secp256k1 lock
    # [lock]
    # code_hash = "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8"
    # args = "0x0000000000000000000000000000000000000000"
    # hash_type = "type"
    1. Build release version of the script
    • The release version of script doesn’t include debug symbols which makes the size smaller.
    capsule build --release
    1. Deploy the script
    capsule deploy --address <ckt1....>

    If the ckb-cli has been installed and dev-chain RPC is connectable, you will see the deployment plan:

    • new_occupied_capacity and total_occupied_capacity refer how much CKB to store cells and data.
    • txs_fee_capacity refers how much CKB to pay the transaction fee.
    Deployment plan:
    ---
    migrated_capacity: 0.0 (CKB)
    new_occupied_capacity: 33629.0 (CKB)
    txs_fee_capacity: 0.0001 (CKB)
    total_occupied_capacity: 33629.0 (CKB)
    recipe:
    cells:
    - name: my-sudt
    index: 0
    tx_hash: 0x8b496cb19018c475cdc4605ee9cef83cbfe578dce4f81f3367395906eba52c29
    occupied_capacity: 33629.0 (CKB)
    data_hash: 0xaa3d472025e6afefdf3f65c5f9beefd206b4283b30551baef83cbb4762e6d397
    type_id: ~
    dep_groups: []
    Confirm deployment? (Yes/No)
    1. Type yes or y and input the password to unlock the account.
    send cell_tx 8b496cb19018c475cdc4605ee9cef83cbfe578dce4f81f3367395906eba52c29
    Deployment complete

    Now the SUDT script has been deployed, you can refer to this script by using tx_hash: 0xaa3d472025e6afefdf3f65c5f9beefd206b4283b30551baef83cbb4762e6d397 index: 0 as out_point(your tx_hash should be another value).

    Migration

    If you want to update the script code and deploy again, you can simply run this command again:

    capsule deploy --address ckt1qyq075y5ctzlgahu8pgsqxrqnglajgwa9zksmqdupd

    The new script will be automatically migrated which means destroy the old script cells and create new cells. You will find new_occupied_capacity is 0 because capacity is already covered by the old script cells.Please don’t forget the transaction fee you still need to pay it.

    Deployment plan:
    ---
    migrated_capacity: 33629.0 (CKB)
    new_occupied_capacity: 0.0 (CKB)
    txs_fee_capacity: 0.0001 (CKB)
    total_occupied_capacity: 33629.0 (CKB)
    recipe:
    cells:
    - name: my-sudt
    index: 0
    tx_hash: 0x10d508a0b44d3c1e02982f85a3e9b5d23d3961fddbf554d20abb4bf54f61950a
    occupied_capacity: 33629.0 (CKB)
    data_hash: 0xaa3d472025e6afefdf3f65c5f9beefd206b4283b30551baef83cbb4762e6d397
    type_id: ~
    dep_groups: []
    Confirm deployment? (Yes/No)

    Next Steps

    This is the end of our journey into writing a SUDT script by Capsule. We have launched the Nervos Grants Program and CKLabs to empower innovation and development and support the growth of a diverse and thriving ecosystem. We can't wait to see what you build next!

    - + \ No newline at end of file diff --git a/docs/reference/cell/index.html b/docs/reference/cell/index.html index 7f22bf38d..cc82029fd 100644 --- a/docs/reference/cell/index.html +++ b/docs/reference/cell/index.html @@ -14,13 +14,13 @@ Cell | Nervos CKB - +
    -

    Cell

    Nervos CKB (Common Knowledge Base) is a layer 1 blockchain, a decentralized and secure layer that provides common knowledge custody for the network. Common knowledge refers to states that are agreed via global consensus.

    Cells are the primary state units in CKB and assets owned by users. They must follow associated validation rules specified by scripts. In Bitcoin, money is the typical common knowledge stored in the Bitcoin ledger. Nervos CKB, however, takes one step further to store arbitrary common knowledge. We starts from Bitcoin's general architecture, and creates the Cell Model by generalizing from the UTXO model, while at the same time retaining the consistency and simplicity of Bitcoin.

    Data Structure

    Example:

    {
    "capacity": "0x19995d0ccf",
    "lock": {
    "code_hash": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8",
    "args": "0x0a486fb8f6fe60f76f001d6372da41be91172259",
    "hash_type": "type"
    },
    "type": null
    }

    A Cell has three fields:

    • capacity: Capacity serves 2 purposes: on one hand, it represents the amount of CKB tokens stored in the cell, on the other hand, it also sets the limit on how much information the cell can store. The basic unit for capacity is shannon, a bigger unit CKByte, or just CKB is also used. 1 CKB equals 10**8 shannons, 1 CKB also means the cell can store 1 byte of information. See below for how to calculate the total information size of a cell.
    • lock script: A script used to guard the cell: when the specified cell is used as an input cell in a transaction, the lock script included in a cell will be executed. The transaction will be rejected when the lock script fails in execution. One typical use case for lock script, is to represent the ownership of a cell, meaning a signature verification phase is usually included in the cell.
    • type script: A script used to validate cell structure. The type script of a cell will be executed both when the cell is included as an input cell, as well as when the cell is created as an output cell. Due to this nature, type script is typically used to validate dapp logic, such as creating UDTs.

    Each cell must have a lock script, while type script is optional, and can be omitted. Please refer to Script for the actual format of lock and type script.

    Cell data

    In addition to the above fields, each cell also contains a cell data field. Cell data is just a series of unformatted binary data. Depending on each dapp, anything could be stored in the cell data part:

    • Script code as explained in Script.
    • Token amount for User Defined Token cells.
    • Latest game stats for an on-chain fantasy game.

    For future potential, cell data is not stored directly in a cell. It is kept directly in the Transaction. You might find a field named outputs_data in each transaction. This array should have the same length with outputs. At each index location, the corresponding cell data could be located for each created output cell in the transaction. Conceptually, we still consider cell data as part of each output cell.

    Cell information size calculation

    Each cell on Nervos CKB, must not have a lower capacity than the total size of information stored in the cell. The size of information for a cell is calculated as the sum of the following fields:

    1. 8 bytes for cell capacity field.
    2. 32 bytes for code hash in lock script.
    3. 1 byte for hash type in lock script.
    4. Actual bytes of args field in lock script.
    5. If type script is present, 32 bytes for code hash in type script.
    6. If type script is present, 1 byte for hash type in type script.
    7. If type script is present, actual bytes of args field in type script.
    8. Actual bytes of cell data.

    By summing up all the above fields, we get the total size of information a cell needs. Cell capacity, when measured in CKBytes, respresents the maximum size of information that can be held, meaning a valid cell must ensure the CKBytes stored in capacity equal or is larger than the total size of information.

    Live Cell

    Live cell refers to an unspent cell in CKB. It is similar to the concept of UTXO in Bitcoin's terminology. The full set of live cells in CKB, is consider the full state of CKB at that particular point. Any transaction on CKB would consume some cells that were live cells just at the point before it is committed, and created new cells that are considered live cells after it is committed.

    Index-Query-Assemble Pattern

    Nervos CKB is designed based on the concept of cells. A transaction, at its core, really just consumes some cells, and create another set of cells. As a result, the ability to locate and transform cells, plays a critical role in building any CKB dapps, which leads to the index-query-assemble pattern:

    • Index: when a new block is committed to CKB, a dapp should be able to index relevant cells to its own storage for latter usage.
    • Query: when a user action is requested, cells satisfying certain criteria will be queried from the dapp storage.
    • Assemble: based on queried cells, a new transaction would be assembled to fulfill user requests.

    We believe all CKB dapps can be decomposed into individual actions following this pattern. Here are some examples:

    • In a normal CKB wallet, cells should be indexed based on lock scripts. A transfer action would first query cells from the sender, and assemble a transaction which transfer CKBytes to the receiver.
    • A NervosDAO manager might index only cells related to NervosDAO. A user might then pick a NervosDAO cell and perform withdraw action, even though there is only one cell related, we can still view it as cells queried from the NervosDAO manager, and a transaction will also be assembled which performs the actual withdraw action.
    • A state based dapp might choose to store the latest state in a CKB cell. The dapp will still need to track the latest live cell, which can also be viewed as an indexing operation, any action on the state will result in the latest live cell being queried, assembled into a transaction, then accepted by CKB with a new output cell containing the updated state.

    Tools

    Indexing & querying plays a central role in any CKB dapps. In most cases, you don't have to build an indexer from scratch. There are several existing tools one can leverage to fulfill the job:

    lumos

    Our dapp framework, lumos already contains a ready-to-use indexer. When you are using lumos, it is very likely the indexer is already setup for you to use. Please refer to our labs for how to setup lumos.

    ckb-indexer

    A ckb-indexer is built into ckb, also handles the job of indexing cells. It provides an RPC mechanism you can use to query for relevant cells. Please refer to the documentation of ckb-indexer for more details.

    perkins-tent

    If you are looking at a one-stop solution, Perkins' Tent provides a single docker image that starts both CKB and ckb-indexer in one dockerisntance. With a single command, you should be able to start a CKB instance and be ready to use the enclosed ckb-indexer for querying tasks.

    - +

    Cell

    Nervos CKB (Common Knowledge Base) is a layer 1 blockchain, a decentralized and secure layer that provides common knowledge custody for the network. Common knowledge refers to states that are agreed via global consensus.

    Cells are the primary state units in CKB and assets owned by users. They must follow associated validation rules specified by scripts. In Bitcoin, money is the typical common knowledge stored in the Bitcoin ledger. Nervos CKB, however, takes one step further to store arbitrary common knowledge. We starts from Bitcoin's general architecture, and creates the Cell Model by generalizing from the UTXO model, while at the same time retaining the consistency and simplicity of Bitcoin.

    Data Structure

    Example:

    {
    "capacity": "0x19995d0ccf",
    "lock": {
    "code_hash": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8",
    "args": "0x0a486fb8f6fe60f76f001d6372da41be91172259",
    "hash_type": "type"
    },
    "type": null
    }

    A Cell has three fields:

    • capacity: Capacity serves 2 purposes: on one hand, it represents the amount of CKB tokens stored in the cell, on the other hand, it also sets the limit on how much information the cell can store. The basic unit for capacity is shannon, a bigger unit CKByte, or just CKB is also used. 1 CKB equals 10**8 shannons, 1 CKB also means the cell can store 1 byte of information. See below for how to calculate the total information size of a cell.
    • lock script: A script used to guard the cell: when the specified cell is used as an input cell in a transaction, the lock script included in a cell will be executed. The transaction will be rejected when the lock script fails in execution. One typical use case for lock script, is to represent the ownership of a cell, meaning a signature verification phase is usually included in the cell.
    • type script: A script used to validate cell structure. The type script of a cell will be executed both when the cell is included as an input cell, as well as when the cell is created as an output cell. Due to this nature, type script is typically used to validate dapp logic, such as creating UDTs.

    Each cell must have a lock script, while type script is optional, and can be omitted. Please refer to Script for the actual format of lock and type script.

    Cell data

    In addition to the above fields, each cell also contains a cell data field. Cell data is just a series of unformatted binary data. Depending on each dapp, anything could be stored in the cell data part:

    • Script code as explained in Script.
    • Token amount for User Defined Token cells.
    • Latest game stats for an on-chain fantasy game.

    For future potential, cell data is not stored directly in a cell. It is kept directly in the Transaction. You might find a field named outputs_data in each transaction. This array should have the same length with outputs. At each index location, the corresponding cell data could be located for each created output cell in the transaction. Conceptually, we still consider cell data as part of each output cell.

    Cell information size calculation

    Each cell on Nervos CKB, must not have a lower capacity than the total size of information stored in the cell. The size of information for a cell is calculated as the sum of the following fields:

    1. 8 bytes for cell capacity field.
    2. 32 bytes for code hash in lock script.
    3. 1 byte for hash type in lock script.
    4. Actual bytes of args field in lock script.
    5. If type script is present, 32 bytes for code hash in type script.
    6. If type script is present, 1 byte for hash type in type script.
    7. If type script is present, actual bytes of args field in type script.
    8. Actual bytes of cell data.

    By summing up all the above fields, we get the total size of information a cell needs. Cell capacity, when measured in CKBytes, represents the maximum size of information that can be held, meaning a valid cell must ensure the CKBytes stored in capacity equal or is larger than the total size of information.

    Live Cell

    Live cell refers to an unspent cell in CKB. It is similar to the concept of UTXO in Bitcoin's terminology. The full set of live cells in CKB, is consider the full state of CKB at that particular point. Any transaction on CKB would consume some cells that were live cells just at the point before it is committed, and created new cells that are considered live cells after it is committed.

    Index-Query-Assemble Pattern

    Nervos CKB is designed based on the concept of cells. A transaction, at its core, really just consumes some cells, and create another set of cells. As a result, the ability to locate and transform cells, plays a critical role in building any CKB dapps, which leads to the index-query-assemble pattern:

    • Index: when a new block is committed to CKB, a dapp should be able to index relevant cells to its own storage for latter usage.
    • Query: when a user action is requested, cells satisfying certain criteria will be queried from the dapp storage.
    • Assemble: based on queried cells, a new transaction would be assembled to fulfill user requests.

    We believe all CKB dapps can be decomposed into individual actions following this pattern. Here are some examples:

    • In a normal CKB wallet, cells should be indexed based on lock scripts. A transfer action would first query cells from the sender, and assemble a transaction which transfer CKBytes to the receiver.
    • A NervosDAO manager might index only cells related to NervosDAO. A user might then pick a NervosDAO cell and perform withdraw action, even though there is only one cell related, we can still view it as cells queried from the NervosDAO manager, and a transaction will also be assembled which performs the actual withdraw action.
    • A state based dapp might choose to store the latest state in a CKB cell. The dapp will still need to track the latest live cell, which can also be viewed as an indexing operation, any action on the state will result in the latest live cell being queried, assembled into a transaction, then accepted by CKB with a new output cell containing the updated state.

    Tools

    Indexing & querying plays a central role in any CKB dapps. In most cases, you don't have to build an indexer from scratch. There are several existing tools one can leverage to fulfill the job:

    lumos

    Our dapp framework, lumos already contains a ready-to-use indexer. When you are using lumos, it is very likely the indexer is already setup for you to use. Please refer to our labs for how to setup lumos.

    ckb-indexer

    A ckb-indexer is built into ckb, also handles the job of indexing cells. It provides an RPC mechanism you can use to query for relevant cells. Please refer to the documentation of ckb-indexer for more details.

    perkins-tent

    If you are looking at a one-stop solution, Perkins' Tent provides a single docker image that starts both CKB and ckb-indexer in one dockerisntance. With a single command, you should be able to start a CKB instance and be ready to use the enclosed ckb-indexer for querying tasks.

    + \ No newline at end of file diff --git a/docs/reference/halving/index.html b/docs/reference/halving/index.html index 77c2bccf3..2d0f80e42 100644 --- a/docs/reference/halving/index.html +++ b/docs/reference/halving/index.html @@ -14,13 +14,13 @@ Halving | Nervos CKB - +

    Halving

    The base issuance of CKBytes are rewarded to miners for securing the network, and the reward halves approximately every 4 years until all the base issuance tokens (33.6 billion) are mined out.

    How does the CKByte-Halving work?

    In order to make the halving plan work as expected, a concept of time called epoch was introduced.

    An epoch is a period of time for a set of blocks.

    In Nervos, the PoW difficulty changes on a new epoch. All the blocks in the same epoch share the same difficulty target. The difficulty adjustment algorithm aims to stabilize the orphan block rate at 2.5% and the epoch duration at 4 hours.

    Epochs per halving is 4 * 365 * (24 / 4) = 8760, and the Nth halving of CKBytes firstly occurs on epoch: the_Nth_halving_epoch = 8760 * N .

    So, The CKByte halving event occurs on the specified epoch, e.g. 8760, 17520.

    When will CKByte be halved?

    The following table details the schedule for several upcoming CKB halvings and their corresponding base issuance rewards:

    EventDateEpoch numberEpoch rewardBlock reward(Calculated based on 1800 blocks per epoch)Daily rewardTotal new CKB between events
    Nervos launches16 Nov 20190 (genesis epoch)1,917,808 CKB1,065 CKB11,506,849 CKB16,800,000,000 CKB
    First halvingExpected 19 Nov 20238,760958,904 CKB533 CKB5,753,424 CKB8,400,000,000 CKB
    Second halvingExpected November 202717,520479,452 CKB266 CKB2,876,712 CKB4,200,000,000 CKB
    3rd halvingExpected November 203126,280239,726 CKB133 CKB1,438,356 CKB2,100,000,000 CKB
    4th halvingExpected November 203535,040119,863 CKB67 CKB719,178 CKB1,050,000,000 CKB
    5th havingExpected November 203943,80059,932 CKB33.5 CKB359,589 CKB525,000,000 CKB
    6th havingExpected November 204352,56029,966 CKB16.75 CKB179,794.5 CKB262,500,000 CKB
    7th havingExpected November 204761,32014,983 CKB8.375 CKB89,897.25 CKB131,250,000 CKB
    8th havingExpected November 205170,0807,491 CKB4.1875 CKB44,948.625 CKB65,625,000 CKB
    9th havingExpected November 205578,8403,746 CKB2.09375 CKB22,474.3125 CKB32,812,500 CKB
    10th havingExpected November 205987,6001,873 CKB1.046875 CKB11,237.15625 CKB16,406,250 CKB

    ⚠️ Note that CKB block rewards include Base (issuance) reward, Secondary (issuance) reward, Commit reward, and Proposal reward:

    However, when we are discussing CKB halving, it only relates to Base issuance rewards. Therefore, the block rewards listed in the table only include the portion of rewards from base issuance to help with understanding.

    - + \ No newline at end of file diff --git a/docs/reference/introduction/index.html b/docs/reference/introduction/index.html index f7642ea83..27045241a 100644 --- a/docs/reference/introduction/index.html +++ b/docs/reference/introduction/index.html @@ -14,13 +14,13 @@ Introduction | Nervos CKB - +

    Introduction

    Reference here provides a definitive guide to learn about Nervos CKB. You can read it word for word to learn about all the little details in CKB, or you can use it more like a dictionary: when you a puzzled by a part and want to learn about CKB's exact behavior. Reference section here will be your best friend.

    Right now, the following sections are available:

    • Cell: introduction to the fundamental cell model.
    • Script: behaviors about the Script data structure, including how Script is executed by CKB VM.
    • Transction: guide to the higher level transaction data structure.
    • JSON-RPC: notes on how to use JSON RPC to talk to a CKB node.
    • Halving: introduces the principle of CKB halving and the halving window.
    - + \ No newline at end of file diff --git a/docs/reference/rpc/index.html b/docs/reference/rpc/index.html index e49330ecb..b7642e2bb 100644 --- a/docs/reference/rpc/index.html +++ b/docs/reference/rpc/index.html @@ -14,13 +14,13 @@ JSON-RPC | Nervos CKB - +

    JSON-RPC

    CKB exposes a set of RPCs in JSON-RPC 2.0 protocols for interactions.

    Here are some initial tips:

    • The RPCs exposed by CKB are only designed for internal usage. Please limit the access to the CKB RPCs strictly to trusted machines (by using rpc.listen_address configuration option). Exposing CKB RPCs to the public Internet is dangerous and strongly discouraged.
    • CKB JSON-RPC only supports HTTP now. If you need SSL support, please setup a reverse proxy via nginx or other HTTPS servers.
    • Subscriptions require a full duplex connection. CKB offers such connections in the form of tcp (enable with rpc.tcp_listen_address configuration option) and websockets (enable with rpc.ws_listen_address), plain HTTP connection does not support subscriptions. See below for examples on this.

    Basic Usage

    Here we try to provide a starting point for interacting with CKB's RPCs. For more details, please refer to CKB JSON RPC Protocols Documentation.

    To use CKB JSON-RPC, you must first have a node running, please refer to existing guides on how to run a CKB Mainnet node, a CKB Testnet node, or a development-only CKB blockchain. The commands below also assumes you are exposing CKB JSON-RPC on the default 8114 port. If you are starting CKB JSON-RPC on a different port, please make changes accordingly.

    The following commands uses get_tip_block_number RPC to fetch the tip block number, of the latest block number in the longest blockchain:

    echo '{
    "id": 2,
    "jsonrpc": "2.0",
    "method": "get_tip_block_number",
    "params": []
    }' \
    | tr -d '\n' \
    | curl -H 'content-type: application/json' -d @- \
    http://localhost:8114
    (click here to view response)
    {"jsonrpc":"2.0","result":"0x2cb4","id":2}

    The following commands uses send_transaction RPC send transactions to the ckb network:

    echo '{
    "id": 3,
    "jsonrpc": "2.0",
    "method": "send_transaction",
    "params": [
    {
    "cell_deps": [
    {
    "dep_type": "code",
    "out_point": {
    "index": "0x0",
    "tx_hash": "0xa4037a893eb48e18ed4ef61034ce26eba9c585f15c9cee102ae58505565eccc3"
    }
    }
    ],
    "header_deps": [
    "0x7978ec7ce5b507cfb52e149e36b1a23f6062ed150503c85bbf825da3599095ed"
    ],
    "inputs": [
    {
    "previous_output": {
    "index": "0x0",
    "tx_hash": "0x365698b50ca0da75dca2c87f9e7b563811d3b5813736b8cc62cc3b106faceb17"
    },
    "since": "0x0"
    }
    ],
    "outputs": [
    {
    "capacity": "0x2540be400",
    "lock": {
    "code_hash": "0x28e83a1277d48add8e72fadaa9248559e1b632bab2bd60b27955ebc4c03800a5",
    "hash_type": "data",
    "args": "0x"
    },
    "type": null
    }
    ],
    "outputs_data": [
    "0x"
    ],
    "version": "0x0",
    "witnesses": []
    }
    ]
    }'\
    | tr -d '\n' \
    | curl -H 'content-type: application/json' -d @- \
    http://localhost:8114
    (click here to view response)
    {
    "id": 3,
    "jsonrpc": "2.0",
    "result": "0xa0ef4eb5f4ceeb08a4c8524d84c5da95dce2f608e0ca2ec8091191b0f330c6e3"
    }

    It should be noted that send_transaction is asynchronous, that is, the return of the transaction hash, does not mean that the transaction is fully verified, if you need to follow up on the status of the transaction, it is recommended to use the following get_transaction rpc:

    echo '{
    "id": 4,
    "jsonrpc": "2.0",
    "method": "get_transaction",
    "params": ["0xa0ef4eb5f4ceeb08a4c8524d84c5da95dce2f608e0ca2ec8091191b0f330c6e3"]
    }' \
    | tr -d '\n' \
    | curl -H 'content-type: application/json' -d @- \
    http://localhost:8114
    (click here to view response)
    {
    "id": 4,
    "jsonrpc": "2.0",
    "result": {
    "transaction": {
    "cell_deps": [
    {
    "dep_type": "code",
    "out_point": {
    "index": "0x0",
    "tx_hash": "0xa4037a893eb48e18ed4ef61034ce26eba9c585f15c9cee102ae58505565eccc3"
    }
    }
    ],
    "hash": "0xa0ef4eb5f4ceeb08a4c8524d84c5da95dce2f608e0ca2ec8091191b0f330c6e3",
    "header_deps": [
    "0x7978ec7ce5b507cfb52e149e36b1a23f6062ed150503c85bbf825da3599095ed"
    ],
    "inputs": [
    {
    "previous_output": {
    "index": "0x0",
    "tx_hash": "0x365698b50ca0da75dca2c87f9e7b563811d3b5813736b8cc62cc3b106faceb17"
    },
    "since": "0x0"
    }
    ],
    "outputs": [
    {
    "capacity": "0x2540be400",
    "lock": {
    "code_hash": "0x28e83a1277d48add8e72fadaa9248559e1b632bab2bd60b27955ebc4c03800a5",
    "hash_type": "data",
    "args": "0x"
    },
    "type": null
    }
    ],
    "outputs_data": [
    "0x"
    ],
    "version": "0x0",
    "witnesses": []
    },
    "cycles": "0x219",
    "time_added_to_pool" : "0x187b3d137a1",
    "tx_status": {
    "block_hash": null,
    "status": "pending",
    "reason": null
    }
    }
    }

    Subscription

    To use subscription feature, you need to configure CKB to enable such features. In this section, we assume you use the following configuration in ckb.toml section:

    [rpc]
    listen_address = "127.0.0.1:8114"
    tcp_listen_address = "127.0.0.1:18114"
    ws_listen_address = "127.0.0.1:18115"

    # ... more configs

    This above config ensures CKB listens at 8114 port for normal HTTP connections, 18114 port for TCP duplex connections, and 18115 port for WebSocket duplex connections.

    TCP Based RPC

    The following command uses netcat to connect via TCP to CKB, then fire the same get_tip_block_number RPC as shown above to fetch the block number in the longest chain:

    echo '{
    "id": 2,
    "jsonrpc": "2.0",
    "method": "get_tip_block_number",
    "params": []
    }' \
    | tr -d '\n' \
    | sed -e "s/$/\n/"
    | nc localhost 18114 -q 1
    {"jsonrpc":"2.0","result":"0xdc90","id":2}

    The following command uses netcat to connect to CKB, make a subscription request to monitor the latest committed block:

    cat <(echo '{
    "id": 2,
    "jsonrpc": "2.0",
    "method": "get_tip_block_number",
    "params": []
    }' \
    | tr -d '\n' \
    | sed -e "s/$/\n/") -
    | nc localhost 18114
    {"jsonrpc":"2.0","result":"0xa","id":2}
    {"jsonrpc":"2.0","method":"subscribe","params":{"result":"{\"version\":\"0x0\",\"compact_target\":\"0x1a2810cf\",\"timestamp\":\"0x16ee81d0d5f\",\"number\":\"0x30673\",\"epoch\":\"0x5f102b400007a\",\"parent_hash\":\"0xc9020c79d4f19797022af3631eb9e76c57933bd608fe81a137b834975616c991\",\"transactions_root\":\"0x7d8e3c102a5c52598cdbe7d208deb986eb2f0af189bc4655e6dd1a71564c2b25\",\"proposals_hash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"uncles_hash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"dao\":\"0x15b9ae7648400f2fb61d57e0379b2300fc641b7e8db5160000060394d5580007\",\"nonce\":\"0x1f86f056000002460000000053170600\",\"hash\":\"0xa3c8feda83d7e184f09cb4f05e535bccd4c159e2cc0ac7a06ea7d457e0051a08\"}","subscription":"0xa"}}
    {"jsonrpc":"2.0","method":"subscribe","params":{"result":"{\"version\":\"0x0\",\"compact_target\":\"0x1a2810cf\",\"timestamp\":\"0x16ee81d1dfd\",\"number\":\"0x30674\",\"epoch\":\"0x5f102b500007a\",\"parent_hash\":\"0xa3c8feda83d7e184f09cb4f05e535bccd4c159e2cc0ac7a06ea7d457e0051a08\",\"transactions_root\":\"0x6d2dfc88bd8dda743b5bae14453f5f405a2a29a3cf6fff00c60f0f5c60a84fbe\",\"proposals_hash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"uncles_hash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"dao\":\"0xb4e019376f400f2f34c172e7379b230031d1417d95b5160000a399ffd6580007\",\"nonce\":\"0xded8ffa1000000000000040a90000000\",\"hash\":\"0x7d10fd1fb459630aa2f87ee4de699b7466a5da6efc0aee6ff459ff17b6cc5904\"}","subscription":"0xa"}}
    // ... more data

    Use Ctrl-C to exit netcat here.

    WebSocket Based RPC

    To play with WebSocket based RPC, please make sure to install wscat first:

    npm install -g wscat

    You can use the following command to start wscat and connect to CKB:

    wscat -c ws://localhost:18115
    Connected (press CTRL+C to quit)
    >

    Now we can run the same get_tip_block_number request as above:

    > {"id": 2, "jsonrpc": "2.0", "method": "get_tip_block_number", "params": []}
    < {"jsonrpc":"2.0","result":"0x76887","id":2}

    You can also create subscriptions for new blocks:

    > {"id": 2, "jsonrpc": "2.0", "method": "subscribe", "params": ["new_tip_header"]}                                                                                                        < {"jsonrpc":"2.0","result":"0x2","id":2}                                                                                                                                                 < {"jsonrpc":"2.0","method":"subscribe","params":{"result":"{\"version\":\"0x0\",\"compact_target\":\"0x1a216e17\",\"timestamp\":\"0x16f886b2223\",\"number\":\"0x77e2a\",\"epoch\":\"0x6c$01a9000135\",\"parent_hash\":\"0x2662c8056c638408d8f018a53785d68f633bd1edfa06b82d7c29ddcac1d98927\",\"transactions_root\":\"0xa6488b15373521ec0b1bc9dff1f117cc1cad7d3579e8a6c38cc6e35166dad9bd\",\"proposals_hash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"uncles_hash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"dao\":\"0x1a1aab41ad3eb72fa260f4eedeb9230092c4510af45b390000547d684fc40007\",\"nonce\":\"0xce1aaca681000089001d0003cb2d0500\",\"hash\":\"0x993e593921024167c1779146348fe2d82864ecd3f657b3bd2b14fbdfa87c4f06\"}","subscription":"0x2"}}
    < {"jsonrpc":"2.0","method":"subscribe","params":{"result":"{\"version\":\"0x0\",\"compact_target\":\"0x1a216e17\",\"timestamp\":\"0x16f886b29e3\",\"number\":\"0x77e2b\",\"epoch\":\"0x6c601aa000135\",\"parent_hash\":\"0x993e593921024167c1779146348fe2d82864ecd3f657b3bd2b14fbdfa87c4f06\",\"transactions_root\":\"0xe64cb6afb57e92a2af1da34d8a1d547fcd8b833e187697ae28a9dfadaaeba247\",\"proposals_hash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"uncles_hash\":\"0xa807c9cbb16a5af7cf36fd5c20b29535f6db4de52062138ad21ea6790ba9529c\",\"dao\":\"0xba227d3fcf3eb72fc8d61ff5deb92300402b3f12fb5b390000f113d450c40007\",\"nonce\":\"0xfb68521601000000000000503c9e2338\",\"hash\":\"0xf55d0f7ae1d9b106eee96139d86313e46b109ec8fa0d92f9eb6eb8bc81c294ec\"}","subscription":"0x2"}}
    < {"jsonrpc":"2.0","method":"subscribe","params":{"result":"{\"version\":\"0x0\",\"compact_target\":\"0x1a216e17\",\"timestamp\":\"0x16f886b40a3\",\"number\":\"0x77e2c\",\"epoch\":\"0x6c601ab000135\",\"parent_hash\":\"0xf55d0f7ae1d9b106eee96139d86313e46b109ec8fa0d92f9eb6eb8bc81c294ec\",\"transactions_root\":\"0xad2c9e1eabc586c8e38cc1eaca61eba5e320bbf4655c510c5be5de9eaafea96f\",\"proposals_hash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"uncles_hash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"dao\":\"0x5a2b4f3df13eb72feb4c4bfbdeb923008c922c1a025c3900008eaa3f52c40007\",\"nonce\":\"0x7b5ad85601000000000000005b340000\",\"hash\":\"0x2077e0c022514fe07844411436cfbf50e413694858a3d4775e0c836e787ce7ab\"}","subscription":"0x2"}}
    << // ... more data.

    Serialization

    CKB's RPCs returns data in JSON format. While most fields are self-explanatory, CKB has special handling for numbers and binary data:

    Numbers

    All numbers used in CKB's RPCs, including request parameters and return values, use hex encoding, the number is encoded first in hexadecimal in the most compact format(meaning useless leading zeros should be striped), and then prefixed with 0x. Here are some examples:

    • 0 is encoded as 0x0, we cannot remove the remaining 0 since otherwise it won't be a proper number
    • 4 is encoded as 0x4
    • 15 is encoded as 0xf
    • 42 is encoded as 0x2a
    • 291 is encoded as 0x123
    • 3984 is encoded as 0xf90

    Binary data

    All binary data, including all the hashes, args in script, outputs_data items, are represented as hex string with 0x prefix. Some examples include:

    • 0x65b253cdcb6226e7f8cffec5c47c959b3d74af2caf7970a1eb1500e9b92aa200
    • 0x927f3e74dceb87c81ba65a19da4f098b4de75a0d
    • 0x40420f00000000000000000000000000
    • 0x (empty data)

    Unlike numbers, binary data should always have a even numbered length.

    - + \ No newline at end of file diff --git a/docs/reference/script/index.html b/docs/reference/script/index.html index b3da87a25..da41bb13b 100644 --- a/docs/reference/script/index.html +++ b/docs/reference/script/index.html @@ -14,13 +14,13 @@ Script | Nervos CKB - +

    Script

    If you are used to blockchains like Ethereum, you will recognize that CKB leverages a drastically different verification model: instead of creating a transaction that alters blockchain state when executing, a transaction in CKB contains state transitions directly in the form of cells. To alter the state of an existing cell, one just destroys the original cell, then create a new one in a single, atomic transaction. CKB scripts, running on CKB VM, actually perform series of validation rules on the input cells and output cells of the transaction.

    In this section we will look closer at the data structure of scripts, and explain how lock scripts and type script work together to ensure the validation rules of CKB.

    Notes: we will distinguish between script code and script

    • script code refers to the compiled program you write and deploy to CKB. It is the actual binary CKB VM will run to perform validation rules.
    • script refers to the script data structure use by lock script and type script in Cell data structure.

    Data Structure

    Both lock script and type script use the same data structure:Script

    Example:

    {
    "hash_type": "type",
    "code_hash": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8",
    "args": "0xc285e812f6a35c2479d6f5b9bbaa357dd4e60da1"
    }

    {
    "hash_type": "data",
    "code_hash": "0xe7f93d7120de3ca8548b34d2ab9c40fe662eec35023f07e143797789895b4869",
    "args": "0x42b5561f13c2a8f7c710843bea7d179656dc6133a98b7d763cebc6e74c8ba72a"
    }

    A script has three fields:

    • code_hash: A hash denoting which script in the transaction to execute. For space consideration, the actual script code is kept in the cell data part of a live cell on CKB. The current transaction should reference the live cell using a cell dep so as to locate and execute the script.

    • hash_type: The interpretation of code_hash when looking for script code to run from cell deps.

      • If hash_type contains data, code_hash should match the blake2b hash of data(which is also the actual script code) in a dep cell;

      • if hash_type contains type, code_hash should instead match the blake2b hash of type script contained by a a dep cell. Note CKB will throw a validation error when a) we are locating a script code using type as hash_type; and b) more than one cell referenced by cell deps contains the specified hash of type script.

        The combination of a code_hash and a hash_type, will uniquely identify a script code in CKB.

    • args: Auxiliary arguments for a script. This is why we need to distinguish between script code and script above: through args, a script actually represents an instance of a script code. Typical examples include:

      • While a single script code will be used for secp256k1 implementation, different people might include different public keys into args to create different scripts, which lead to different wallets.
      • While a single script code might provide implementation for the UDT specification, different people might inject different args for different types of tokens.

    We will talk about how to execute a script to validate transaction structure in sections below.

    Depending on the different types, scripts will be executed at different times:

    1. All lock scripts from all input cells in a transaction will be executed.
    2. All type scripts(if exist) from all input cells and output cells in a transaction will be executed.

    We will consider the transaction valid only when all the required scripts complete with a success status. Failure in any script will mark the transaction as invalid.

    Execution

    Here we are providing a basic introduction for script execution flow, for the more precise definition, please refer to the following RFCs:

    Each script that needs to be executed from a CKB transaction, will be run in a CKB VM instance. At its core, CKB VM is just an implementation of the RISC-V Instruction Set Architecture(ISA). It means any RISC-V standard compliant program(RV64IMC to be more precise, see the RFCs for more details) will be accepted by CKB VM. The common ELF format is used to package a binary.

    To use a RISC-V program as a script on CKB, one simply needs to create a new cell with the full program binary in the cell's data part. One the transaction generating the new cell is committed on CKB, scripts can then be assembled to use the program as script code. As mentioned above, a cell dep entry must be also create to reference the newly created cell containing script code.

    There are cases that RISC-V ISA is not be enough, for example, a script might want to read information from the enclosing transaction to enforce validation rules, CKB provides a series of syscalls that will handle this task. Notice syscall is a concept also designed and included by the RISC-V standard ISA, we are confronting to RISC-V standard specification as much as we can.

    To prevent infinite loops, cycles are introduced to CKB VM. Each executed RISC-V instruction and each syscall made will consume certain amount of cycles. At consensus layer, CKB has a hard limit on the maximum cycles that is allowed in a single block. The total cycles consumed by all executed scripts, from all transactions included in a blocks, must not exceed this number. Otherwise the block will be rejected.

    Use Cases

    Lock script and type script share the identical running environment, they can all access all the information contained in its enclosing transaction. But due to the fact they are executed in different times, they have formed into different use cases.

    Lock Script

    Lock scripts are more for representing ownerships. Typical use cases for lock scripts include:

    • Signature verification
    • Lock period ensurance

    You might notice that type script can actually replace all functionalities of a lock script, meaning a cell can use a dummy lock script that does nothing, and rely on type script for all behaviors. But that is an anti-pattern of CKB now. By making lock script mandatory, we want to ensure each cell at least uses a secure lock script.

    Lock script can be viewed as the last defense to ensure that your tokens stay safe. So we do recommend to keep your lock as simple as possible, to avoid the potential of vulnerabilities.

    Type Script

    Type script, on the other hand, is where innovations would more likely to happen on CKB. Some use cases of type scripts include:

    • User Defined Token(UDT) implementation
    • Ensuring cell data confronts to a certain format
    - + \ No newline at end of file diff --git a/docs/reference/transaction/index.html b/docs/reference/transaction/index.html index efacc6fb0..1cf82a87f 100644 --- a/docs/reference/transaction/index.html +++ b/docs/reference/transaction/index.html @@ -14,13 +14,13 @@ Transaction | Nervos CKB - +

    Transaction

    Transactions are the most fundamental entities for interacting with Nervos CKB. At Layer 1, we are focusing on states, the design of CKB as a Layer 1 blockchain, naturally emphasizes on states. In CKB, transactions are the only way to trigger state changes.

    A state change on CKB is represented by a transaction destroying some cells from previous transactions, and creating some new cells. The concept of state, is reflected via a set of live cells(including the data included in each cell) in CKB. A transaction is atomic, it either gets accepted, or rejected. Partial transaction will never be committed to Nervos CKB>

    Due to the above nature of CKB, state changes are usually calculated outside of Nervos CKB, the resulting state is then assembled into a transaction, which is then submitted, validated and finally accepted by Nervos CKB, which is then propagated to the entire network.

    Data Structure

    Example:

    {
    "cell_deps": [
    {
    "dep_type": "dep_group",
    "out_point": {
    "index": "0x0",
    "tx_hash": "0xf8de3bb47d055cdf460d93a2a6e1b05f7432f9777c8c474abf4eec1d4aee5d37"
    }
    },
    {
    "dep_type": "code",
    "out_point": {
    "index": "0x0",
    "tx_hash": "0xc1b2ae129fad7465aaa9acc9785f842ba3e6e8b8051d899defa89f5508a77958"
    }
    }
    ],
    "hash": "0x65b253cdcb6226e7f8cffec5c47c959b3d74af2caf7970a1eb1500e9b92aa200",
    "header_deps": [],
    "inputs": [
    {
    "previous_output": {
    "index": "0x0",
    "tx_hash": "0x6e64c2a3f248da5115c49ef8100b3a29c4f665517626a513b340821ba8b95f80"
    },
    "since": "0x0"
    }
    ],
    "outputs": [
    {
    "capacity": "0x34e62ce00",
    "lock": {
    "args": "0x927f3e74dceb87c81ba65a19da4f098b4de75a0d",
    "code_hash": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8",
    "hash_type": "type"
    },
    "type": {
    "args": "0x6e9b17739760ffc617017f157ed40641f7aa51b2af9ee017b35a0b35a1e2297b",
    "code_hash": "0x48dbf59b4c7ee1547238021b4869bceedf4eea6b43772e5d66ef8865b6ae7212",
    "hash_type": "data"
    }
    },
    {
    "capacity": "0x711befb618",
    "lock": {
    "args": "0x927f3e74dceb87c81ba65a19da4f098b4de75a0d",
    "code_hash": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8",
    "hash_type": "type"
    },
    "type": null
    }
    ],
    "outputs_data": [
    "0x40420f00000000000000000000000000",
    "0x"
    ],
    "version": "0x0",
    "witnesses": [
    "0x55000000100000005500000055000000410000007926ec98874bb86143d178826253e18425e50bf85fbb4b7cf9188462e7e87bc810ac602e55b9c73890ab8306368d7d02d96234f250750269e1aa023eb5b71b5100"
    ]
    }

    There are already 2 RFCs that describe the transaction structure in great details:

    - + \ No newline at end of file diff --git a/index.html b/index.html index eede55dda..ccfaad837 100644 --- a/index.html +++ b/index.html @@ -14,13 +14,13 @@ Nervos CKB - +
    -

    Nervos CKB

    Nervos CKB is a public permissionless blockchain and the layer 1 of Nervos.

    CKB generates trust and extends this trust to upper layers, making Nervos a trust network. It's also the value store of the Nervos network, providing public, secure and censorship-resistant custody services for assets, identities and other common knowledge created in the network. We will also vigorously develop the developer community and aim to offer blockchain developers exciting new capabilities.

    If you run into an issue on our documentation website you can contact us on Nervos talk or Discord.

    Getting Started

    If you are a beginner who just started experimenting with CKB for the first time, Basics will help you get to know CKB, and get the chain running. Reference contains advanced concepts that might also be of interest.

    Exchange & Wallet Integration

    Integrate section provides first hand experience gained in integrating CKB into existing exchanges and wallets. Reference might also help you learn more about CKB specific behavior.

    Building Dapps

    If you are developers who want to build dapps on CKB, Labs provides hands-on tutorials which you can follow. Reference also contains explanations for CKB concepts and specific blockchain behaviors.

    Clarification

    As dapp developers, you might need clarifications on specific part from time to time, Reference will be your best friend on this topc.

    Random Browsing

    For users who are just browing to get a glimpse of CKB's design, or developers who want to learn one or two tips, Essays will provide all sorts of articles explaining CKB related topics. Reference might also be of interest since it aims to describe specific constructs in CKB.

    - +

    Nervos CKB

    Nervos CKB is a public permissionless blockchain and the layer 1 of Nervos.

    CKB generates trust and extends this trust to upper layers, making Nervos a trust network. It's also the value store of the Nervos network, providing public, secure and censorship-resistant custody services for assets, identities and other common knowledge created in the network. We will also vigorously develop the developer community and aim to offer blockchain developers exciting new capabilities.

    If you run into an issue on our documentation website you can contact us on Nervos talk or Discord.

    Getting Started

    If you are a beginner who just started experimenting with CKB for the first time, Basics will help you get to know CKB, and get the chain running. Reference contains advanced concepts that might also be of interest.

    Exchange & Wallet Integration

    Integrate section provides first hand experience gained in integrating CKB into existing exchanges and wallets. Reference might also help you learn more about CKB specific behavior.

    Building Dapps

    If you are developers who want to build dapps on CKB, Labs provides hands-on tutorials which you can follow. Reference also contains explanations for CKB concepts and specific blockchain behaviors.

    Clarification

    As dapp developers, you might need clarifications on specific part from time to time, Reference will be your best friend on this topc.

    Random Browsing

    For users who are just browsing to get a glimpse of CKB's design, or developers who want to learn one or two tips, Essays will provide all sorts of articles explaining CKB related topics. Reference might also be of interest since it aims to describe specific constructs in CKB.

    + \ No newline at end of file diff --git a/search/index.html b/search/index.html index 3d5f200e6..941d9fb69 100644 --- a/search/index.html +++ b/search/index.html @@ -14,13 +14,13 @@ Search the documentation | Nervos CKB - +

    Search the documentation

    - + \ No newline at end of file