diff --git a/404.html b/404.html new file mode 100644 index 00000000..9569c404 --- /dev/null +++ b/404.html @@ -0,0 +1,28 @@ + + + + + + 404 | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + +
Skip to content

404

PAGE NOT FOUND

But if you don't change your direction, and if you keep looking, you may end up where you are heading.
+ + + + \ No newline at end of file diff --git a/apple-touch-icon.png b/apple-touch-icon.png new file mode 100644 index 00000000..63b5d4f8 Binary files /dev/null and b/apple-touch-icon.png differ diff --git a/assets/KeePassXC.BngrXRS-.png b/assets/KeePassXC.BngrXRS-.png new file mode 100644 index 00000000..be329b6d Binary files /dev/null and b/assets/KeePassXC.BngrXRS-.png differ diff --git a/assets/app.CQjEq298.js b/assets/app.CQjEq298.js new file mode 100644 index 00000000..37c76a24 --- /dev/null +++ b/assets/app.CQjEq298.js @@ -0,0 +1,7 @@ +import{j as o,a7 as p,a8 as u,a9 as c,aa as l,ab as f,ac as d,ad as m,ae as h,af as A,ag as g,Y as v,d as P,u as w,l as y,z as C,ah as R,ai as _,aj as b,ak as E}from"./chunks/framework.B6c1f-8R.js";import{R as j}from"./chunks/theme.BX4Y5IZy.js";function i(e){if(e.extends){const a=i(e.extends);return{...a,...e,async enhanceApp(t){a.enhanceApp&&await a.enhanceApp(t),e.enhanceApp&&await e.enhanceApp(t)}}}return e}const s=i(j),D=P({name:"VitePressApp",setup(){const{site:e,lang:a,dir:t}=w();return y(()=>{C(()=>{document.documentElement.lang=a.value,document.documentElement.dir=t.value})}),e.value.router.prefetchLinks&&R(),_(),b(),s.setup&&s.setup(),()=>E(s.Layout)}});async function T(){const e=O(),a=L();a.provide(u,e);const t=c(e.route);return a.provide(l,t),a.component("Content",f),a.component("ClientOnly",d),Object.defineProperties(a.config.globalProperties,{$frontmatter:{get(){return t.frontmatter.value}},$params:{get(){return t.page.value.params}}}),s.enhanceApp&&await s.enhanceApp({app:a,router:e,siteData:m}),{app:a,router:e,data:t}}function L(){return h(D)}function O(){let e=o,a;return A(t=>{let n=g(t),r=null;return n&&(e&&(a=n),(e||a===n)&&(n=n.replace(/\.js$/,".lean.js")),r=v(()=>import(n),__vite__mapDeps([]))),o&&(e=!1),r},s.NotFound)}o&&T().then(({app:e,router:a,data:t})=>{a.go().then(()=>{p(a.route,t.site),e.mount("#app")})});export{T as createApp}; +function __vite__mapDeps(indexes) { + if (!__vite__mapDeps.viteFileDeps) { + __vite__mapDeps.viteFileDeps = [] + } + return indexes.map((i) => __vite__mapDeps.viteFileDeps[i]) +} diff --git a/assets/appendix_running-iroha_cli-output.CtJXTWW9.png b/assets/appendix_running-iroha_cli-output.CtJXTWW9.png new file mode 100644 index 00000000..36ef3d37 Binary files /dev/null and b/assets/appendix_running-iroha_cli-output.CtJXTWW9.png differ diff --git a/assets/chunks/@localSearchIndexroot.BSq76Xc_.js b/assets/chunks/@localSearchIndexroot.BSq76Xc_.js new file mode 100644 index 00000000..b08a4a9c --- /dev/null +++ b/assets/chunks/@localSearchIndexroot.BSq76Xc_.js @@ -0,0 +1 @@ +const e='{"documentCount":754,"nextId":754,"documentIds":{"0":"/iroha-2-docs/documenting/snippets.html#code-snippets","1":"/iroha-2-docs/documenting/snippets.html#how-it-works","2":"/iroha-2-docs/documenting/snippets.html#snippet-sources","3":"/iroha-2-docs/documenting/snippets.html#fetching-snippets","4":"/iroha-2-docs/documenting/snippets.html#using-snippets-in-markdown","5":"/iroha-2-docs/documenting/snippets.html#example","6":"/iroha-2-docs/guide/advanced/hot-reload.html#how-to-hot-reload-iroha-in-a-docker-container","7":"/iroha-2-docs/guide/advanced/hot-reload.html#wiping-previous-blockchain-state-recommit-genesis","8":"/iroha-2-docs/guide/advanced/hot-reload.html#use-custom-configuration-files","9":"/iroha-2-docs/guide/advanced/hot-reload.html#use-custom-environment-variables","10":"/iroha-2-docs/guide/advanced/metrics.html#metrics","11":"/iroha-2-docs/guide/advanced/metrics.html#metrics-endpoint","12":"/iroha-2-docs/guide/advanced/metrics.html#how-to-use-metrics","13":"/iroha-2-docs/guide/advanced/running-iroha-on-bare-metal.html#iroha-on-bare-metal","14":"/iroha-2-docs/guide/advanced/running-iroha-on-bare-metal.html#prerequisites","15":"/iroha-2-docs/guide/advanced/running-iroha-on-bare-metal.html#setup","16":"/iroha-2-docs/guide/advanced/running-iroha-on-bare-metal.html#setup-environment-variables","17":"/iroha-2-docs/guide/advanced/running-iroha-on-bare-metal.html#setup-files","18":"/iroha-2-docs/guide/advanced/running-iroha-on-bare-metal.html#first-run-of-iroha-on-bare-metal","19":"/iroha-2-docs/guide/advanced/running-iroha-on-bare-metal.html#deploy-a-minimal-bft-network","20":"/iroha-2-docs/guide/advanced/running-iroha-on-bare-metal.html#using-environment-variables","21":"/iroha-2-docs/guide/advanced/running-iroha-on-bare-metal.html#using-files","22":"/iroha-2-docs/guide/advanced/running-iroha-on-bare-metal.html#real-world-deployment","23":"/iroha-2-docs/guide/blockchain/accounts.html#accounts","24":"/iroha-2-docs/guide/blockchain/assets.html#assets","25":"/iroha-2-docs/guide/blockchain/assets.html#value-types","26":"/iroha-2-docs/guide/blockchain/assets.html#asset-structure","27":"/iroha-2-docs/guide/blockchain/assets.html#instructions","28":"/iroha-2-docs/guide/blockchain/consensus.html#consensus","29":"/iroha-2-docs/guide/blockchain/data-model.html#data-model","30":"/iroha-2-docs/guide/blockchain/domains.html#domains","31":"/iroha-2-docs/guide/blockchain/events.html#events","32":"/iroha-2-docs/guide/blockchain/events.html#pipeline-events","33":"/iroha-2-docs/guide/blockchain/events.html#data-events","34":"/iroha-2-docs/guide/blockchain/events.html#time-events","35":"/iroha-2-docs/guide/blockchain/events.html#trigger-execution-events","36":"/iroha-2-docs/guide/blockchain/expressions.html#expressions-conditionals-logic","37":"/iroha-2-docs/guide/blockchain/filters.html#filters","38":"/iroha-2-docs/guide/blockchain/filters.html#data-filters","39":"/iroha-2-docs/guide/blockchain/how-iroha-works.html#how-iroha-works","40":"/iroha-2-docs/guide/blockchain/instructions.html#iroha-special-instructions","41":"/iroha-2-docs/guide/blockchain/instructions.html#summary","42":"/iroha-2-docs/guide/blockchain/instructions.html#un-register","43":"/iroha-2-docs/guide/blockchain/instructions.html#mint-burn","44":"/iroha-2-docs/guide/blockchain/instructions.html#transfer","45":"/iroha-2-docs/guide/blockchain/instructions.html#grant-revoke","46":"/iroha-2-docs/guide/blockchain/instructions.html#setkeyvalue-removekeyvalue","47":"/iroha-2-docs/guide/blockchain/instructions.html#newparameter-setparameter","48":"/iroha-2-docs/guide/blockchain/instructions.html#executetrigger","49":"/iroha-2-docs/guide/blockchain/instructions.html#composite-instructions","50":"/iroha-2-docs/guide/blockchain/metadata.html#metadata","51":"/iroha-2-docs/guide/blockchain/metadata.html#metadatachanged","52":"/iroha-2-docs/guide/blockchain/metadata.html#store-asset","53":"/iroha-2-docs/guide/blockchain/metadata.html#working-with-metadata","54":"/iroha-2-docs/guide/blockchain/metadata.html#queries","55":"/iroha-2-docs/guide/blockchain/metadata.html#permissions","56":"/iroha-2-docs/guide/blockchain/permissions.html#permissions","57":"/iroha-2-docs/guide/blockchain/permissions.html#permission-tokens","58":"/iroha-2-docs/guide/blockchain/permissions.html#pre-configured-permission-tokens","59":"/iroha-2-docs/guide/blockchain/permissions.html#permission-groups-roles","60":"/iroha-2-docs/guide/blockchain/permissions.html#register-a-new-role","61":"/iroha-2-docs/guide/blockchain/permissions.html#grant-a-role","62":"/iroha-2-docs/guide/blockchain/permissions.html#permission-validators","63":"/iroha-2-docs/guide/blockchain/permissions.html#runtime-validators","64":"/iroha-2-docs/guide/blockchain/permissions.html#supported-queries","65":"/iroha-2-docs/guide/blockchain/queries.html#queries","66":"/iroha-2-docs/guide/blockchain/queries.html#create-a-query","67":"/iroha-2-docs/guide/blockchain/queries.html#pagination","68":"/iroha-2-docs/guide/blockchain/queries.html#filters","69":"/iroha-2-docs/guide/blockchain/queries.html#sorting","70":"/iroha-2-docs/guide/blockchain/queries.html#reference","71":"/iroha-2-docs/guide/blockchain/transactions.html#transactions","72":"/iroha-2-docs/guide/blockchain/triggers.html#triggers","73":"/iroha-2-docs/guide/blockchain/triggers.html#the-anatomy-of-a-trigger","74":"/iroha-2-docs/guide/blockchain/triggers.html#trigger-id","75":"/iroha-2-docs/guide/blockchain/triggers.html#trigger-action","76":"/iroha-2-docs/guide/blockchain/triggers.html#action-executable","77":"/iroha-2-docs/guide/blockchain/triggers.html#action-repeats","78":"/iroha-2-docs/guide/blockchain/triggers.html#action-technical-account","79":"/iroha-2-docs/guide/blockchain/triggers.html#action-filter","80":"/iroha-2-docs/guide/blockchain/triggers.html#action-metadata","81":"/iroha-2-docs/guide/blockchain/triggers.html#how-triggers-work","82":"/iroha-2-docs/guide/blockchain/triggers.html#scope","83":"/iroha-2-docs/guide/blockchain/triggers.html#domain-scoped-triggers","84":"/iroha-2-docs/guide/blockchain/triggers.html#repetition-schema","85":"/iroha-2-docs/guide/blockchain/triggers.html#types-of-triggers","86":"/iroha-2-docs/guide/blockchain/triggers.html#data-triggers","87":"/iroha-2-docs/guide/blockchain/triggers.html#time-triggers","88":"/iroha-2-docs/guide/blockchain/triggers.html#scheduled-triggers","89":"/iroha-2-docs/guide/blockchain/triggers.html#pre-commit-triggers","90":"/iroha-2-docs/guide/blockchain/triggers.html#by-call-triggers","91":"/iroha-2-docs/guide/blockchain/triggers.html#event-triggers-by-example","92":"/iroha-2-docs/guide/blockchain/triggers.html#_1-register-accounts","93":"/iroha-2-docs/guide/blockchain/triggers.html#_2-register-a-trigger","94":"/iroha-2-docs/guide/blockchain/triggers.html#_3-define-an-event-filter","95":"/iroha-2-docs/guide/blockchain/triggers.html#_4-create-a-trigger-instance","96":"/iroha-2-docs/guide/blockchain/triggers.html#_5-create-a-transaction","97":"/iroha-2-docs/guide/blockchain/triggers.html#how-it-works","98":"/iroha-2-docs/guide/blockchain/triggers.html#supported-isi","99":"/iroha-2-docs/guide/blockchain/triggers.html#supported-queries","100":"/iroha-2-docs/guide/blockchain/wasm.html#wasm","101":"/iroha-2-docs/guide/blockchain/wasm.html#working-with-wasm","102":"/iroha-2-docs/guide/blockchain/wasm.html#simple-rust-smart-contract-example","103":"/iroha-2-docs/guide/blockchain/wasm.html#_1-create-a-new-project","104":"/iroha-2-docs/guide/blockchain/wasm.html#_2-write-a-smart-contract","105":"/iroha-2-docs/guide/blockchain/wasm.html#advanced-smart-contracts-optimising-for-size","106":"/iroha-2-docs/guide/blockchain/wasm.html#remove-debugging-info","107":"/iroha-2-docs/guide/blockchain/wasm.html#work-under-a-no-std-environment","108":"/iroha-2-docs/guide/blockchain/wasm.html#re-compile-libcore","109":"/iroha-2-docs/guide/blockchain/wasm.html#use-tools-to-optimise-wasm-size","110":"/iroha-2-docs/guide/blockchain/wasm.html#conclusion","111":"/iroha-2-docs/guide/blockchain/world.html#world","112":"/iroha-2-docs/guide/blockchain/world.html#world-state-view-wsv","113":"/iroha-2-docs/guide/configure/client-configuration.html#client-configuration","114":"/iroha-2-docs/guide/configure/client-configuration.html#generation","115":"/iroha-2-docs/guide/configure/client-configuration.html#public-and-private-keys","116":"/iroha-2-docs/guide/configure/client-configuration.html#user-account","117":"/iroha-2-docs/guide/configure/client-configuration.html#basic-authentication-credentials","118":"/iroha-2-docs/guide/configure/client-configuration.html#iroha-public-addresses","119":"/iroha-2-docs/guide/configure/client-configuration.html#torii-api-url","120":"/iroha-2-docs/guide/configure/client-configuration.html#torii-telemetry-url","121":"/iroha-2-docs/guide/configure/client-configuration.html#transaction-limits","122":"/iroha-2-docs/guide/configure/client-configuration.html#transaction-ttl-and-timeout","123":"/iroha-2-docs/guide/configure/client-configuration.html#transaction-nonce","124":"/iroha-2-docs/guide/configure/configuration-types.html#configuration-types","125":"/iroha-2-docs/guide/configure/configuration-types.html#option","126":"/iroha-2-docs/guide/configure/configuration-types.html#option-option","127":"/iroha-2-docs/guide/configure/configuration-types.html#sumeragi-default-null-values","128":"/iroha-2-docs/guide/configure/genesis.html#genesis-block","129":"/iroha-2-docs/guide/configure/genesis.html#generation","130":"/iroha-2-docs/guide/configure/genesis.html#generate-default-genesis-block","131":"/iroha-2-docs/guide/configure/genesis.html#configuration","132":"/iroha-2-docs/guide/configure/keys-for-network-deployment.html#keys-for-network-deployment","133":"/iroha-2-docs/guide/configure/keys-for-network-deployment.html#setting-keys-for-a-new-network","134":"/iroha-2-docs/guide/configure/keys-for-network-deployment.html#_1-generate-new-key-pairs","135":"/iroha-2-docs/guide/configure/keys-for-network-deployment.html#_2-update-keys-for-peers","136":"/iroha-2-docs/guide/configure/keys-for-network-deployment.html#_3-register-a-non-genesis-account","137":"/iroha-2-docs/guide/configure/metadata-and-store-assets.html#choosing-between-the-store-and-metadata-assets","138":"/iroha-2-docs/guide/configure/modes.html#public-and-private-blockchains","139":"/iroha-2-docs/guide/configure/modes.html#permissions","140":"/iroha-2-docs/guide/configure/modes.html#peers","141":"/iroha-2-docs/guide/configure/modes.html#registering-accounts","142":"/iroha-2-docs/guide/configure/overview.html#configuration-and-management","143":"/iroha-2-docs/guide/configure/peer-configuration.html#peer-configuration","144":"/iroha-2-docs/guide/configure/peer-configuration.html#generation","145":"/iroha-2-docs/guide/configure/peer-configuration.html#public-and-private-keys","146":"/iroha-2-docs/guide/configure/peer-configuration.html#trusted-peers","147":"/iroha-2-docs/guide/configure/peer-configuration.html#iroha-public-addresses","148":"/iroha-2-docs/guide/configure/peer-configuration.html#api-url","149":"/iroha-2-docs/guide/configure/peer-configuration.html#p2p-addr","150":"/iroha-2-docs/guide/configure/peer-configuration.html#telemetry-url","151":"/iroha-2-docs/guide/configure/peer-configuration.html#genesis","152":"/iroha-2-docs/guide/configure/peer-configuration.html#logger","153":"/iroha-2-docs/guide/configure/peer-configuration.html#max-log-level","154":"/iroha-2-docs/guide/configure/peer-configuration.html#log-file-path","155":"/iroha-2-docs/guide/configure/peer-configuration.html#kura","156":"/iroha-2-docs/guide/configure/peer-management.html#peer-management","157":"/iroha-2-docs/guide/configure/peer-management.html#public-blockchain","158":"/iroha-2-docs/guide/configure/peer-management.html#private-blockchain","159":"/iroha-2-docs/guide/configure/peer-management.html#registering-peers","160":"/iroha-2-docs/guide/configure/peer-management.html#_1-grant-the-user-permissions","161":"/iroha-2-docs/guide/configure/peer-management.html#_2-set-up-a-peer","162":"/iroha-2-docs/guide/configure/peer-management.html#_3-submit-the-instruction","163":"/iroha-2-docs/guide/configure/peer-management.html#unregistering-peers","164":"/iroha-2-docs/guide/configure/sample-configuration.html#sample-configuration-files","165":"/iroha-2-docs/guide/get-started/#iroha-2","166":"/iroha-2-docs/guide/get-started/#get-started","167":"/iroha-2-docs/guide/get-started/#explore-in-depth","168":"/iroha-2-docs/guide/get-started/#learn-more","169":"/iroha-2-docs/guide/get-started/install-iroha-2.html#install-iroha-2","170":"/iroha-2-docs/guide/get-started/install-iroha-2.html#_1-prerequisites","171":"/iroha-2-docs/guide/get-started/install-iroha-2.html#_2-clone-iroha-from-github","172":"/iroha-2-docs/guide/get-started/install-iroha-2.html#_3-install-iroha-binaries","173":"/iroha-2-docs/guide/get-started/javascript.html#javascript-typescript-guide","174":"/iroha-2-docs/guide/get-started/javascript.html#_1-client-installation","175":"/iroha-2-docs/guide/get-started/javascript.html#_2-client-configuration","176":"/iroha-2-docs/guide/get-started/javascript.html#_3-registering-a-domain","177":"/iroha-2-docs/guide/get-started/javascript.html#_4-registering-an-account","178":"/iroha-2-docs/guide/get-started/javascript.html#_5-registering-and-minting-assets","179":"/iroha-2-docs/guide/get-started/javascript.html#_6-transferring-assets","180":"/iroha-2-docs/guide/get-started/javascript.html#_7-querying-for-domains-accounts-and-assets","181":"/iroha-2-docs/guide/get-started/javascript.html#_8-visualizing-outputs-in-web-ui","182":"/iroha-2-docs/guide/get-started/javascript.html#demo","183":"/iroha-2-docs/guide/get-started/javascript.html#_9-subscribing-to-block-stream","184":"/iroha-2-docs/guide/get-started/kotlin-java.html#kotlin-java-guide","185":"/iroha-2-docs/guide/get-started/kotlin-java.html#_1-iroha-2-client-setup","186":"/iroha-2-docs/guide/get-started/kotlin-java.html#_2-configuring-iroha-2","187":"/iroha-2-docs/guide/get-started/kotlin-java.html#_3-querying-and-registering-domains","188":"/iroha-2-docs/guide/get-started/kotlin-java.html#_4-registering-an-account","189":"/iroha-2-docs/guide/get-started/kotlin-java.html#_5-registering-and-minting-assets","190":"/iroha-2-docs/guide/get-started/kotlin-java.html#_6-transferring-assets","191":"/iroha-2-docs/guide/get-started/kotlin-java.html#_7-burning-assets","192":"/iroha-2-docs/guide/get-started/kotlin-java.html#_8-visualizing-outputs","193":"/iroha-2-docs/guide/get-started/kotlin-java.html#_9-samples-in-pure-java","194":"/iroha-2-docs/guide/get-started/launch-iroha-2.html#launch-iroha-2","195":"/iroha-2-docs/guide/get-started/launch-iroha-2.html#_1-prerequisites","196":"/iroha-2-docs/guide/get-started/launch-iroha-2.html#_2-launch-iroha-network","197":"/iroha-2-docs/guide/get-started/launch-iroha-2.html#docker-options","198":"/iroha-2-docs/guide/get-started/operate-iroha-2-via-cli.html#operate-iroha-2-via-cli","199":"/iroha-2-docs/guide/get-started/operate-iroha-2-via-cli.html#_1-set-up-iroha-client-cli","200":"/iroha-2-docs/guide/get-started/operate-iroha-2-via-cli.html#_2-configure-iroha-client-cli","201":"/iroha-2-docs/guide/get-started/operate-iroha-2-via-cli.html#_3-register-a-domain","202":"/iroha-2-docs/guide/get-started/operate-iroha-2-via-cli.html#_4-register-an-account","203":"/iroha-2-docs/guide/get-started/operate-iroha-2-via-cli.html#_5-transfer-a-domain","204":"/iroha-2-docs/guide/get-started/operate-iroha-2-via-cli.html#_6-register-and-mint-assets","205":"/iroha-2-docs/guide/get-started/operate-iroha-2-via-cli.html#_7-transfer-assets","206":"/iroha-2-docs/guide/get-started/operate-iroha-2-via-cli.html#_8-burn-assets","207":"/iroha-2-docs/guide/get-started/operate-iroha-2-via-cli.html#_9-visualize-outputs","208":"/iroha-2-docs/guide/get-started/operate-iroha-2-via-cli.html#what-s-next","209":"/iroha-2-docs/guide/get-started/python.html#python-3-guide","210":"/iroha-2-docs/guide/get-started/python.html#_1-iroha-2-client-setup","211":"/iroha-2-docs/guide/get-started/python.html#_2-configuring-iroha-2","212":"/iroha-2-docs/guide/get-started/python.html#_3-registering-a-domain","213":"/iroha-2-docs/guide/get-started/python.html#_4-registering-an-account","214":"/iroha-2-docs/guide/get-started/python.html#_5-registering-and-minting-assets","215":"/iroha-2-docs/guide/get-started/python.html#_6-visualizing-outputs","216":"/iroha-2-docs/guide/get-started/rust.html#rust-guide","217":"/iroha-2-docs/guide/get-started/rust.html#_1-iroha-2-client-setup","218":"/iroha-2-docs/guide/get-started/rust.html#_2-configuring-iroha-2","219":"/iroha-2-docs/guide/get-started/rust.html#_3-registering-a-domain","220":"/iroha-2-docs/guide/get-started/rust.html#_4-registering-an-account","221":"/iroha-2-docs/guide/get-started/rust.html#_5-registering-and-minting-assets","222":"/iroha-2-docs/guide/get-started/rust.html#_6-transferring-assets","223":"/iroha-2-docs/guide/get-started/rust.html#_7-burning-assets","224":"/iroha-2-docs/guide/get-started/rust.html#_8-visualising-outputs","225":"/iroha-2-docs/guide/get-started/tutorials.html#introduction","226":"/iroha-2-docs/guide/get-started/tutorials.html#preamble","227":"/iroha-2-docs/guide/get-started/tutorials.html#navigation","228":"/iroha-2-docs/guide/get-started/tutorials.html#tutorial-updates","229":"/iroha-2-docs/guide/iroha-2.html#iroha-2-vs-iroha-1","230":"/iroha-2-docs/guide/iroha-2.html#fault-tolerance","231":"/iroha-2-docs/guide/iroha-2.html#minimalist-code-base","232":"/iroha-2-docs/guide/iroha-2.html#flexibility","233":"/iroha-2-docs/guide/iroha-2.html#smart-contracts","234":"/iroha-2-docs/guide/iroha-2.html#static-and-dynamic-linking","235":"/iroha-2-docs/guide/iroha-2.html#testing","236":"/iroha-2-docs/guide/reports/csd-rtgs.html#csd-rtgs-linkages-proof-of-concept","237":"/iroha-2-docs/guide/security/generating-cryptographic-keys.html#generating-cryptographic-keys","238":"/iroha-2-docs/guide/security/generating-cryptographic-keys.html#kagami","239":"/iroha-2-docs/guide/security/generating-cryptographic-keys.html#examples","240":"/iroha-2-docs/guide/security/generating-cryptographic-keys.html#other-operations-with-kagami","241":"/iroha-2-docs/guide/security/generating-cryptographic-keys.html#_1-building-kagami","242":"/iroha-2-docs/guide/security/generating-cryptographic-keys.html#_2-installing-the-source-built-kagami-into-bin","243":"/iroha-2-docs/guide/security/generating-cryptographic-keys.html#_3-moving-kagami-to-the-local-bin-directory","244":"/iroha-2-docs/guide/security/generating-cryptographic-keys.html#making-the-username-local-bin-directory-available-to-the-shell","245":"/iroha-2-docs/guide/security/#security","246":"/iroha-2-docs/guide/security/#navigation","247":"/iroha-2-docs/guide/security/operational-security.html#operational-security","248":"/iroha-2-docs/guide/security/operational-security.html#recommended-opsec-measures","249":"/iroha-2-docs/guide/security/operational-security.html#using-browsers","250":"/iroha-2-docs/guide/security/operational-security.html#recovery-plan","251":"/iroha-2-docs/guide/security/password-security.html#password-security","252":"/iroha-2-docs/guide/security/password-security.html#password-strength","253":"/iroha-2-docs/guide/security/password-security.html#password-vulnerabilities","254":"/iroha-2-docs/guide/security/public-key-cryptography.html#public-key-cryptography","255":"/iroha-2-docs/guide/security/public-key-cryptography.html#encryption-and-signatures","256":"/iroha-2-docs/guide/security/public-key-cryptography.html#keys-on-the-client-side","257":"/iroha-2-docs/guide/security/security-principles.html#security-principles","258":"/iroha-2-docs/guide/security/security-principles.html#general-security-principles","259":"/iroha-2-docs/guide/security/security-principles.html#security-principles-for-individual-users","260":"/iroha-2-docs/guide/security/security-principles.html#security-principles-for-organisations","261":"/iroha-2-docs/guide/security/storing-cryptographic-keys.html#storing-cryptographic-keys","262":"/iroha-2-docs/guide/security/storing-cryptographic-keys.html#storing-cryptographic-keys-digitally","263":"/iroha-2-docs/guide/security/storing-cryptographic-keys.html#using-ssh-and-ssh-agent","264":"/iroha-2-docs/guide/security/storing-cryptographic-keys.html#adding-a-password-manager-program","265":"/iroha-2-docs/guide/security/storing-cryptographic-keys.html#configuring-keepassxc","266":"/iroha-2-docs/guide/security/storing-cryptographic-keys.html#expected-results","267":"/iroha-2-docs/guide/security/storing-cryptographic-keys.html#storing-cryptographic-keys-physically","268":"/iroha-2-docs/guide/security/storing-cryptographic-keys.html#using-a-hardware-key","269":"/iroha-2-docs/guide/security/storing-cryptographic-keys.html#using-a-mnemonic-phrase","270":"/iroha-2-docs/guide/support.html#receive-support","271":"/iroha-2-docs/guide/troubleshooting/configuration-issues.html#troubleshooting-configuration-issues","272":"/iroha-2-docs/guide/troubleshooting/configuration-issues.html#outdated-genesis-on-a-docker-compose-setup","273":"/iroha-2-docs/guide/troubleshooting/configuration-issues.html#multihash-format-of-private-and-public-keys","274":"/iroha-2-docs/guide/troubleshooting/deployment-issues.html#troubleshooting-deployment-issues","275":"/iroha-2-docs/guide/troubleshooting/deployment-issues.html#docker","276":"/iroha-2-docs/guide/troubleshooting/deployment-issues.html#kubernetes","277":"/iroha-2-docs/guide/troubleshooting/installation-issues.html#troubleshooting-installation-issues","278":"/iroha-2-docs/guide/troubleshooting/installation-issues.html#troubleshooting-rust-toolchain","279":"/iroha-2-docs/guide/troubleshooting/installation-issues.html#check-rust-version","280":"/iroha-2-docs/guide/troubleshooting/installation-issues.html#check-installation-location","281":"/iroha-2-docs/guide/troubleshooting/installation-issues.html#check-the-default-rust-version","282":"/iroha-2-docs/guide/troubleshooting/installation-issues.html#check-if-there-are-other-rust-versions","283":"/iroha-2-docs/guide/troubleshooting/installation-issues.html#troubleshooting-python-toolchain","284":"/iroha-2-docs/guide/troubleshooting/integration-issues.html#troubleshooting-integration-issues","285":"/iroha-2-docs/guide/troubleshooting/overview.html#troubleshooting","286":"/iroha-2-docs/guide/troubleshooting/overview.html#check-the-keys","287":"/iroha-2-docs/reference/compatibility-matrix.html#compatibility-matrix","288":"/iroha-2-docs/reference/data-model-schema.html#data-model-schema","289":"/iroha-2-docs/reference/data-model-schema.html#account","290":"/iroha-2-docs/reference/data-model-schema.html#accountevent","291":"/iroha-2-docs/reference/data-model-schema.html#accounteventfilter","292":"/iroha-2-docs/reference/data-model-schema.html#accounteventset","293":"/iroha-2-docs/reference/data-model-schema.html#accountid","294":"/iroha-2-docs/reference/data-model-schema.html#accountmintbox","295":"/iroha-2-docs/reference/data-model-schema.html#accountpermissionchanged","296":"/iroha-2-docs/reference/data-model-schema.html#accountrolechanged","297":"/iroha-2-docs/reference/data-model-schema.html#action","298":"/iroha-2-docs/reference/data-model-schema.html#algorithm","299":"/iroha-2-docs/reference/data-model-schema.html#array-u16-8","300":"/iroha-2-docs/reference/data-model-schema.html#array-u8-32","301":"/iroha-2-docs/reference/data-model-schema.html#array-u8-4","302":"/iroha-2-docs/reference/data-model-schema.html#asset","303":"/iroha-2-docs/reference/data-model-schema.html#assetchanged","304":"/iroha-2-docs/reference/data-model-schema.html#assetdefinition","305":"/iroha-2-docs/reference/data-model-schema.html#assetdefinitionevent","306":"/iroha-2-docs/reference/data-model-schema.html#assetdefinitioneventfilter","307":"/iroha-2-docs/reference/data-model-schema.html#assetdefinitioneventset","308":"/iroha-2-docs/reference/data-model-schema.html#assetdefinitionid","309":"/iroha-2-docs/reference/data-model-schema.html#assetdefinitionownerchanged","310":"/iroha-2-docs/reference/data-model-schema.html#assetdefinitiontotalquantitychanged","311":"/iroha-2-docs/reference/data-model-schema.html#assetevent","312":"/iroha-2-docs/reference/data-model-schema.html#asseteventfilter","313":"/iroha-2-docs/reference/data-model-schema.html#asseteventset","314":"/iroha-2-docs/reference/data-model-schema.html#assetid","315":"/iroha-2-docs/reference/data-model-schema.html#assettransferbox","316":"/iroha-2-docs/reference/data-model-schema.html#assetvalue","317":"/iroha-2-docs/reference/data-model-schema.html#assetvaluetype","318":"/iroha-2-docs/reference/data-model-schema.html#atindex","319":"/iroha-2-docs/reference/data-model-schema.html#batchedresponse-queryoutputbox","320":"/iroha-2-docs/reference/data-model-schema.html#batchedresponsev1-queryoutputbox","321":"/iroha-2-docs/reference/data-model-schema.html#blockevent","322":"/iroha-2-docs/reference/data-model-schema.html#blockeventfilter","323":"/iroha-2-docs/reference/data-model-schema.html#blockheader","324":"/iroha-2-docs/reference/data-model-schema.html#blockmessage","325":"/iroha-2-docs/reference/data-model-schema.html#blockpayload","326":"/iroha-2-docs/reference/data-model-schema.html#blockrejectionreason","327":"/iroha-2-docs/reference/data-model-schema.html#blockstatus","328":"/iroha-2-docs/reference/data-model-schema.html#blocksubscriptionrequest","329":"/iroha-2-docs/reference/data-model-schema.html#burn-numeric-asset","330":"/iroha-2-docs/reference/data-model-schema.html#burn-publickey-account","331":"/iroha-2-docs/reference/data-model-schema.html#burn-u32-trigger","332":"/iroha-2-docs/reference/data-model-schema.html#burnbox","333":"/iroha-2-docs/reference/data-model-schema.html#chainid","334":"/iroha-2-docs/reference/data-model-schema.html#compact-u128","335":"/iroha-2-docs/reference/data-model-schema.html#compact-u32","336":"/iroha-2-docs/reference/data-model-schema.html#configurationevent","337":"/iroha-2-docs/reference/data-model-schema.html#configurationeventfilter","338":"/iroha-2-docs/reference/data-model-schema.html#configurationeventset","339":"/iroha-2-docs/reference/data-model-schema.html#container","340":"/iroha-2-docs/reference/data-model-schema.html#dataevent","341":"/iroha-2-docs/reference/data-model-schema.html#dataeventfilter","342":"/iroha-2-docs/reference/data-model-schema.html#domain","343":"/iroha-2-docs/reference/data-model-schema.html#domainevent","344":"/iroha-2-docs/reference/data-model-schema.html#domaineventfilter","345":"/iroha-2-docs/reference/data-model-schema.html#domaineventset","346":"/iroha-2-docs/reference/data-model-schema.html#domainid","347":"/iroha-2-docs/reference/data-model-schema.html#domainownerchanged","348":"/iroha-2-docs/reference/data-model-schema.html#duration","349":"/iroha-2-docs/reference/data-model-schema.html#eventbox","350":"/iroha-2-docs/reference/data-model-schema.html#eventfilterbox","351":"/iroha-2-docs/reference/data-model-schema.html#eventmessage","352":"/iroha-2-docs/reference/data-model-schema.html#eventsubscriptionrequest","353":"/iroha-2-docs/reference/data-model-schema.html#executable","354":"/iroha-2-docs/reference/data-model-schema.html#executetrigger","355":"/iroha-2-docs/reference/data-model-schema.html#executetriggerevent","356":"/iroha-2-docs/reference/data-model-schema.html#executetriggereventfilter","357":"/iroha-2-docs/reference/data-model-schema.html#executiontime","358":"/iroha-2-docs/reference/data-model-schema.html#executor","359":"/iroha-2-docs/reference/data-model-schema.html#executorevent","360":"/iroha-2-docs/reference/data-model-schema.html#executoreventfilter","361":"/iroha-2-docs/reference/data-model-schema.html#executoreventset","362":"/iroha-2-docs/reference/data-model-schema.html#fail","363":"/iroha-2-docs/reference/data-model-schema.html#findaccountbyid","364":"/iroha-2-docs/reference/data-model-schema.html#findaccountkeyvaluebyidandkey","365":"/iroha-2-docs/reference/data-model-schema.html#findaccountsbydomainid","366":"/iroha-2-docs/reference/data-model-schema.html#findaccountsbyname","367":"/iroha-2-docs/reference/data-model-schema.html#findaccountswithasset","368":"/iroha-2-docs/reference/data-model-schema.html#findallaccounts","369":"/iroha-2-docs/reference/data-model-schema.html#findallactivetriggerids","370":"/iroha-2-docs/reference/data-model-schema.html#findallassets","371":"/iroha-2-docs/reference/data-model-schema.html#findallassetsdefinitions","372":"/iroha-2-docs/reference/data-model-schema.html#findallblockheaders","373":"/iroha-2-docs/reference/data-model-schema.html#findallblocks","374":"/iroha-2-docs/reference/data-model-schema.html#findalldomains","375":"/iroha-2-docs/reference/data-model-schema.html#findallparameters","376":"/iroha-2-docs/reference/data-model-schema.html#findallpeers","377":"/iroha-2-docs/reference/data-model-schema.html#findallroleids","378":"/iroha-2-docs/reference/data-model-schema.html#findallroles","379":"/iroha-2-docs/reference/data-model-schema.html#findalltransactions","380":"/iroha-2-docs/reference/data-model-schema.html#findassetbyid","381":"/iroha-2-docs/reference/data-model-schema.html#findassetdefinitionbyid","382":"/iroha-2-docs/reference/data-model-schema.html#findassetdefinitionkeyvaluebyidandkey","383":"/iroha-2-docs/reference/data-model-schema.html#findassetkeyvaluebyidandkey","384":"/iroha-2-docs/reference/data-model-schema.html#findassetquantitybyid","385":"/iroha-2-docs/reference/data-model-schema.html#findassetsbyaccountid","386":"/iroha-2-docs/reference/data-model-schema.html#findassetsbyassetdefinitionid","387":"/iroha-2-docs/reference/data-model-schema.html#findassetsbydomainid","388":"/iroha-2-docs/reference/data-model-schema.html#findassetsbydomainidandassetdefinitionid","389":"/iroha-2-docs/reference/data-model-schema.html#findassetsbyname","390":"/iroha-2-docs/reference/data-model-schema.html#findblockheaderbyhash","391":"/iroha-2-docs/reference/data-model-schema.html#finddomainbyid","392":"/iroha-2-docs/reference/data-model-schema.html#finddomainkeyvaluebyidandkey","393":"/iroha-2-docs/reference/data-model-schema.html#finderror","394":"/iroha-2-docs/reference/data-model-schema.html#findpermissiontokenschema","395":"/iroha-2-docs/reference/data-model-schema.html#findpermissiontokensbyaccountid","396":"/iroha-2-docs/reference/data-model-schema.html#findrolebyroleid","397":"/iroha-2-docs/reference/data-model-schema.html#findrolesbyaccountid","398":"/iroha-2-docs/reference/data-model-schema.html#findtotalassetquantitybyassetdefinitionid","399":"/iroha-2-docs/reference/data-model-schema.html#findtransactionbyhash","400":"/iroha-2-docs/reference/data-model-schema.html#findtransactionsbyaccountid","401":"/iroha-2-docs/reference/data-model-schema.html#findtriggerbyid","402":"/iroha-2-docs/reference/data-model-schema.html#findtriggerkeyvaluebyidandkey","403":"/iroha-2-docs/reference/data-model-schema.html#findtriggersbydomainid","404":"/iroha-2-docs/reference/data-model-schema.html#forwardcursor","405":"/iroha-2-docs/reference/data-model-schema.html#genericpredicatebox-queryoutputpredicate","406":"/iroha-2-docs/reference/data-model-schema.html#grant-permissiontoken-account","407":"/iroha-2-docs/reference/data-model-schema.html#grant-permissiontoken-role","408":"/iroha-2-docs/reference/data-model-schema.html#grant-roleid-account","409":"/iroha-2-docs/reference/data-model-schema.html#grantbox","410":"/iroha-2-docs/reference/data-model-schema.html#hash","411":"/iroha-2-docs/reference/data-model-schema.html#hashof-merkletree-signedtransaction","412":"/iroha-2-docs/reference/data-model-schema.html#hashof-signedblock","413":"/iroha-2-docs/reference/data-model-schema.html#hashof-signedtransaction","414":"/iroha-2-docs/reference/data-model-schema.html#idbox","415":"/iroha-2-docs/reference/data-model-schema.html#identifiablebox","416":"/iroha-2-docs/reference/data-model-schema.html#instructionbox","417":"/iroha-2-docs/reference/data-model-schema.html#instructionevaluationerror","418":"/iroha-2-docs/reference/data-model-schema.html#instructionexecutionerror","419":"/iroha-2-docs/reference/data-model-schema.html#instructionexecutionfail","420":"/iroha-2-docs/reference/data-model-schema.html#instructiontype","421":"/iroha-2-docs/reference/data-model-schema.html#invalidparametererror","422":"/iroha-2-docs/reference/data-model-schema.html#ipfspath","423":"/iroha-2-docs/reference/data-model-schema.html#ipv4addr","424":"/iroha-2-docs/reference/data-model-schema.html#ipv6addr","425":"/iroha-2-docs/reference/data-model-schema.html#jsonstring","426":"/iroha-2-docs/reference/data-model-schema.html#lengthlimits","427":"/iroha-2-docs/reference/data-model-schema.html#level","428":"/iroha-2-docs/reference/data-model-schema.html#limits","429":"/iroha-2-docs/reference/data-model-schema.html#log","430":"/iroha-2-docs/reference/data-model-schema.html#matherror","431":"/iroha-2-docs/reference/data-model-schema.html#merkletree-signedtransaction","432":"/iroha-2-docs/reference/data-model-schema.html#metadata","433":"/iroha-2-docs/reference/data-model-schema.html#metadatachanged-accountid","434":"/iroha-2-docs/reference/data-model-schema.html#metadatachanged-assetdefinitionid","435":"/iroha-2-docs/reference/data-model-schema.html#metadatachanged-assetid","436":"/iroha-2-docs/reference/data-model-schema.html#metadatachanged-domainid","437":"/iroha-2-docs/reference/data-model-schema.html#metadatachanged-triggerid","438":"/iroha-2-docs/reference/data-model-schema.html#metadataerror","439":"/iroha-2-docs/reference/data-model-schema.html#metadatavaluebox","440":"/iroha-2-docs/reference/data-model-schema.html#mint-numeric-asset","441":"/iroha-2-docs/reference/data-model-schema.html#mint-publickey-account","442":"/iroha-2-docs/reference/data-model-schema.html#mint-signaturecheckcondition-account","443":"/iroha-2-docs/reference/data-model-schema.html#mint-u32-trigger","444":"/iroha-2-docs/reference/data-model-schema.html#mintbox","445":"/iroha-2-docs/reference/data-model-schema.html#mintabilityerror","446":"/iroha-2-docs/reference/data-model-schema.html#mintable","447":"/iroha-2-docs/reference/data-model-schema.html#mismatch-assetvaluetype","448":"/iroha-2-docs/reference/data-model-schema.html#name","449":"/iroha-2-docs/reference/data-model-schema.html#newaccount","450":"/iroha-2-docs/reference/data-model-schema.html#newassetdefinition","451":"/iroha-2-docs/reference/data-model-schema.html#newdomain","452":"/iroha-2-docs/reference/data-model-schema.html#newparameter","453":"/iroha-2-docs/reference/data-model-schema.html#newrole","454":"/iroha-2-docs/reference/data-model-schema.html#nontrivial-genericpredicatebox-queryoutputpredicate","455":"/iroha-2-docs/reference/data-model-schema.html#nonzero-u32","456":"/iroha-2-docs/reference/data-model-schema.html#nonzero-u64","457":"/iroha-2-docs/reference/data-model-schema.html#numeric","458":"/iroha-2-docs/reference/data-model-schema.html#numericspec","459":"/iroha-2-docs/reference/data-model-schema.html#option-accountid","460":"/iroha-2-docs/reference/data-model-schema.html#option-assetdefinitionid","461":"/iroha-2-docs/reference/data-model-schema.html#option-assetid","462":"/iroha-2-docs/reference/data-model-schema.html#option-blockstatus","463":"/iroha-2-docs/reference/data-model-schema.html#option-domainid","464":"/iroha-2-docs/reference/data-model-schema.html#option-duration","465":"/iroha-2-docs/reference/data-model-schema.html#option-hashof-merkletree-signedtransaction","466":"/iroha-2-docs/reference/data-model-schema.html#option-hashof-signedblock","467":"/iroha-2-docs/reference/data-model-schema.html#option-hashof-signedtransaction","468":"/iroha-2-docs/reference/data-model-schema.html#option-ipfspath","469":"/iroha-2-docs/reference/data-model-schema.html#option-nonzero-u32","470":"/iroha-2-docs/reference/data-model-schema.html#option-nonzero-u64","471":"/iroha-2-docs/reference/data-model-schema.html#option-option-u64","472":"/iroha-2-docs/reference/data-model-schema.html#option-parameterid","473":"/iroha-2-docs/reference/data-model-schema.html#option-peerid","474":"/iroha-2-docs/reference/data-model-schema.html#option-roleid","475":"/iroha-2-docs/reference/data-model-schema.html#option-string","476":"/iroha-2-docs/reference/data-model-schema.html#option-timeinterval","477":"/iroha-2-docs/reference/data-model-schema.html#option-transactionrejectionreason","478":"/iroha-2-docs/reference/data-model-schema.html#option-transactionstatus","479":"/iroha-2-docs/reference/data-model-schema.html#option-triggercompletedoutcometype","480":"/iroha-2-docs/reference/data-model-schema.html#option-triggerid","481":"/iroha-2-docs/reference/data-model-schema.html#option-u32","482":"/iroha-2-docs/reference/data-model-schema.html#option-u64","483":"/iroha-2-docs/reference/data-model-schema.html#parameter","484":"/iroha-2-docs/reference/data-model-schema.html#parameterid","485":"/iroha-2-docs/reference/data-model-schema.html#parametervaluebox","486":"/iroha-2-docs/reference/data-model-schema.html#peer","487":"/iroha-2-docs/reference/data-model-schema.html#peerevent","488":"/iroha-2-docs/reference/data-model-schema.html#peereventfilter","489":"/iroha-2-docs/reference/data-model-schema.html#peereventset","490":"/iroha-2-docs/reference/data-model-schema.html#peerid","491":"/iroha-2-docs/reference/data-model-schema.html#permissiontoken","492":"/iroha-2-docs/reference/data-model-schema.html#permissiontokenschema","493":"/iroha-2-docs/reference/data-model-schema.html#permissiontokenschemaupdateevent","494":"/iroha-2-docs/reference/data-model-schema.html#pipelineeventbox","495":"/iroha-2-docs/reference/data-model-schema.html#pipelineeventfilterbox","496":"/iroha-2-docs/reference/data-model-schema.html#publickey","497":"/iroha-2-docs/reference/data-model-schema.html#querybox","498":"/iroha-2-docs/reference/data-model-schema.html#queryexecutionfail","499":"/iroha-2-docs/reference/data-model-schema.html#queryoutputbox","500":"/iroha-2-docs/reference/data-model-schema.html#queryoutputpredicate","501":"/iroha-2-docs/reference/data-model-schema.html#querypayload","502":"/iroha-2-docs/reference/data-model-schema.html#register-account","503":"/iroha-2-docs/reference/data-model-schema.html#register-asset","504":"/iroha-2-docs/reference/data-model-schema.html#register-assetdefinition","505":"/iroha-2-docs/reference/data-model-schema.html#register-domain","506":"/iroha-2-docs/reference/data-model-schema.html#register-peer","507":"/iroha-2-docs/reference/data-model-schema.html#register-role","508":"/iroha-2-docs/reference/data-model-schema.html#register-trigger","509":"/iroha-2-docs/reference/data-model-schema.html#registerbox","510":"/iroha-2-docs/reference/data-model-schema.html#removekeyvalue-account","511":"/iroha-2-docs/reference/data-model-schema.html#removekeyvalue-asset","512":"/iroha-2-docs/reference/data-model-schema.html#removekeyvalue-assetdefinition","513":"/iroha-2-docs/reference/data-model-schema.html#removekeyvalue-domain","514":"/iroha-2-docs/reference/data-model-schema.html#removekeyvalue-trigger","515":"/iroha-2-docs/reference/data-model-schema.html#removekeyvaluebox","516":"/iroha-2-docs/reference/data-model-schema.html#repeats","517":"/iroha-2-docs/reference/data-model-schema.html#repetitionerror","518":"/iroha-2-docs/reference/data-model-schema.html#revoke-permissiontoken-account","519":"/iroha-2-docs/reference/data-model-schema.html#revoke-permissiontoken-role","520":"/iroha-2-docs/reference/data-model-schema.html#revoke-roleid-account","521":"/iroha-2-docs/reference/data-model-schema.html#revokebox","522":"/iroha-2-docs/reference/data-model-schema.html#role","523":"/iroha-2-docs/reference/data-model-schema.html#roleevent","524":"/iroha-2-docs/reference/data-model-schema.html#roleeventfilter","525":"/iroha-2-docs/reference/data-model-schema.html#roleeventset","526":"/iroha-2-docs/reference/data-model-schema.html#roleid","527":"/iroha-2-docs/reference/data-model-schema.html#rolepermissionchanged","528":"/iroha-2-docs/reference/data-model-schema.html#schedule","529":"/iroha-2-docs/reference/data-model-schema.html#semiinterval-numeric","530":"/iroha-2-docs/reference/data-model-schema.html#semiinterval-u128","531":"/iroha-2-docs/reference/data-model-schema.html#semirange","532":"/iroha-2-docs/reference/data-model-schema.html#setkeyvalue-account","533":"/iroha-2-docs/reference/data-model-schema.html#setkeyvalue-asset","534":"/iroha-2-docs/reference/data-model-schema.html#setkeyvalue-assetdefinition","535":"/iroha-2-docs/reference/data-model-schema.html#setkeyvalue-domain","536":"/iroha-2-docs/reference/data-model-schema.html#setkeyvalue-trigger","537":"/iroha-2-docs/reference/data-model-schema.html#setkeyvaluebox","538":"/iroha-2-docs/reference/data-model-schema.html#setparameter","539":"/iroha-2-docs/reference/data-model-schema.html#signature","540":"/iroha-2-docs/reference/data-model-schema.html#signaturecheckcondition","541":"/iroha-2-docs/reference/data-model-schema.html#signatureof-blockpayload","542":"/iroha-2-docs/reference/data-model-schema.html#signatureof-querypayload","543":"/iroha-2-docs/reference/data-model-schema.html#signatureof-transactionpayload","544":"/iroha-2-docs/reference/data-model-schema.html#signaturesof-blockpayload","545":"/iroha-2-docs/reference/data-model-schema.html#signaturesof-transactionpayload","546":"/iroha-2-docs/reference/data-model-schema.html#signedblock","547":"/iroha-2-docs/reference/data-model-schema.html#signedblockv1","548":"/iroha-2-docs/reference/data-model-schema.html#signedquery","549":"/iroha-2-docs/reference/data-model-schema.html#signedqueryv1","550":"/iroha-2-docs/reference/data-model-schema.html#signedtransaction","551":"/iroha-2-docs/reference/data-model-schema.html#signedtransactionv1","552":"/iroha-2-docs/reference/data-model-schema.html#sizeerror","553":"/iroha-2-docs/reference/data-model-schema.html#socketaddr","554":"/iroha-2-docs/reference/data-model-schema.html#socketaddrhost","555":"/iroha-2-docs/reference/data-model-schema.html#socketaddrv4","556":"/iroha-2-docs/reference/data-model-schema.html#socketaddrv6","557":"/iroha-2-docs/reference/data-model-schema.html#sortedmap-accountid-account","558":"/iroha-2-docs/reference/data-model-schema.html#sortedmap-assetdefinitionid-assetdefinition","559":"/iroha-2-docs/reference/data-model-schema.html#sortedmap-assetdefinitionid-numeric","560":"/iroha-2-docs/reference/data-model-schema.html#sortedmap-assetid-asset","561":"/iroha-2-docs/reference/data-model-schema.html#sortedmap-name-metadatavaluebox","562":"/iroha-2-docs/reference/data-model-schema.html#sortedvec-permissiontoken","563":"/iroha-2-docs/reference/data-model-schema.html#sortedvec-publickey","564":"/iroha-2-docs/reference/data-model-schema.html#sortedvec-signatureof-blockpayload","565":"/iroha-2-docs/reference/data-model-schema.html#sortedvec-signatureof-transactionpayload","566":"/iroha-2-docs/reference/data-model-schema.html#string","567":"/iroha-2-docs/reference/data-model-schema.html#stringpredicate","568":"/iroha-2-docs/reference/data-model-schema.html#timeevent","569":"/iroha-2-docs/reference/data-model-schema.html#timeeventfilter","570":"/iroha-2-docs/reference/data-model-schema.html#timeinterval","571":"/iroha-2-docs/reference/data-model-schema.html#transactionevent","572":"/iroha-2-docs/reference/data-model-schema.html#transactioneventfilter","573":"/iroha-2-docs/reference/data-model-schema.html#transactionlimiterror","574":"/iroha-2-docs/reference/data-model-schema.html#transactionlimits","575":"/iroha-2-docs/reference/data-model-schema.html#transactionpayload","576":"/iroha-2-docs/reference/data-model-schema.html#transactionqueryoutput","577":"/iroha-2-docs/reference/data-model-schema.html#transactionrejectionreason","578":"/iroha-2-docs/reference/data-model-schema.html#transactionstatus","579":"/iroha-2-docs/reference/data-model-schema.html#transactionvalue","580":"/iroha-2-docs/reference/data-model-schema.html#transfer-account-assetdefinitionid-account","581":"/iroha-2-docs/reference/data-model-schema.html#transfer-account-domainid-account","582":"/iroha-2-docs/reference/data-model-schema.html#transfer-asset-metadata-account","583":"/iroha-2-docs/reference/data-model-schema.html#transfer-asset-numeric-account","584":"/iroha-2-docs/reference/data-model-schema.html#transferbox","585":"/iroha-2-docs/reference/data-model-schema.html#trigger","586":"/iroha-2-docs/reference/data-model-schema.html#triggercompletedevent","587":"/iroha-2-docs/reference/data-model-schema.html#triggercompletedeventfilter","588":"/iroha-2-docs/reference/data-model-schema.html#triggercompletedoutcome","589":"/iroha-2-docs/reference/data-model-schema.html#triggercompletedoutcometype","590":"/iroha-2-docs/reference/data-model-schema.html#triggerevent","591":"/iroha-2-docs/reference/data-model-schema.html#triggereventfilter","592":"/iroha-2-docs/reference/data-model-schema.html#triggereventset","593":"/iroha-2-docs/reference/data-model-schema.html#triggerid","594":"/iroha-2-docs/reference/data-model-schema.html#triggernumberofexecutionschanged","595":"/iroha-2-docs/reference/data-model-schema.html#triggeringeventfilterbox","596":"/iroha-2-docs/reference/data-model-schema.html#typeerror","597":"/iroha-2-docs/reference/data-model-schema.html#unregister-account","598":"/iroha-2-docs/reference/data-model-schema.html#unregister-asset","599":"/iroha-2-docs/reference/data-model-schema.html#unregister-assetdefinition","600":"/iroha-2-docs/reference/data-model-schema.html#unregister-domain","601":"/iroha-2-docs/reference/data-model-schema.html#unregister-peer","602":"/iroha-2-docs/reference/data-model-schema.html#unregister-role","603":"/iroha-2-docs/reference/data-model-schema.html#unregister-trigger","604":"/iroha-2-docs/reference/data-model-schema.html#unregisterbox","605":"/iroha-2-docs/reference/data-model-schema.html#upgrade","606":"/iroha-2-docs/reference/data-model-schema.html#validationfail","607":"/iroha-2-docs/reference/data-model-schema.html#vec-eventbox","608":"/iroha-2-docs/reference/data-model-schema.html#vec-eventfilterbox","609":"/iroha-2-docs/reference/data-model-schema.html#vec-genericpredicatebox-queryoutputpredicate","610":"/iroha-2-docs/reference/data-model-schema.html#vec-instructionbox","611":"/iroha-2-docs/reference/data-model-schema.html#vec-metadatavaluebox","612":"/iroha-2-docs/reference/data-model-schema.html#vec-name","613":"/iroha-2-docs/reference/data-model-schema.html#vec-peerid","614":"/iroha-2-docs/reference/data-model-schema.html#vec-publickey","615":"/iroha-2-docs/reference/data-model-schema.html#vec-queryoutputbox","616":"/iroha-2-docs/reference/data-model-schema.html#vec-transactionvalue","617":"/iroha-2-docs/reference/data-model-schema.html#vec-u8","618":"/iroha-2-docs/reference/data-model-schema.html#wasmexecutionfail","619":"/iroha-2-docs/reference/data-model-schema.html#wasmsmartcontract","620":"/iroha-2-docs/reference/data-model-schema.html#bool","621":"/iroha-2-docs/reference/data-model-schema.html#u128","622":"/iroha-2-docs/reference/data-model-schema.html#u16","623":"/iroha-2-docs/reference/data-model-schema.html#u32","624":"/iroha-2-docs/reference/data-model-schema.html#u64","625":"/iroha-2-docs/reference/data-model-schema.html#u8","626":"/iroha-2-docs/reference/glossary.html#glossary","627":"/iroha-2-docs/reference/glossary.html#blockchain-ledgers","628":"/iroha-2-docs/reference/glossary.html#peer","629":"/iroha-2-docs/reference/glossary.html#asset","630":"/iroha-2-docs/reference/glossary.html#fungible-assets","631":"/iroha-2-docs/reference/glossary.html#non-fungible-assets","632":"/iroha-2-docs/reference/glossary.html#mintable-assets","633":"/iroha-2-docs/reference/glossary.html#non-mintable-assets","634":"/iroha-2-docs/reference/glossary.html#byzantine-fault-tolerance-bft","635":"/iroha-2-docs/reference/glossary.html#iroha-components","636":"/iroha-2-docs/reference/glossary.html#sumeragi-emperor","637":"/iroha-2-docs/reference/glossary.html#torii-gate","638":"/iroha-2-docs/reference/glossary.html#kura-warehouse","639":"/iroha-2-docs/reference/glossary.html#kagami-teacher-and-exemplar-and-or-looking-glass","640":"/iroha-2-docs/reference/glossary.html#merkle-tree-hash-tree","641":"/iroha-2-docs/reference/glossary.html#smart-contracts","642":"/iroha-2-docs/reference/glossary.html#triggers","643":"/iroha-2-docs/reference/glossary.html#versioning","644":"/iroha-2-docs/reference/glossary.html#hijiri-peer-reputation-system","645":"/iroha-2-docs/reference/glossary.html#iroha-modules","646":"/iroha-2-docs/reference/glossary.html#iroha-special-instructions-isi","647":"/iroha-2-docs/reference/glossary.html#utility-iroha-special-instructions","648":"/iroha-2-docs/reference/glossary.html#core-iroha-special-instructions","649":"/iroha-2-docs/reference/glossary.html#domain-specific-iroha-special-instructions","650":"/iroha-2-docs/reference/glossary.html#custom-iroha-special-instruction","651":"/iroha-2-docs/reference/glossary.html#iroha-query","652":"/iroha-2-docs/reference/glossary.html#view-change","653":"/iroha-2-docs/reference/glossary.html#world-state-view-wsv","654":"/iroha-2-docs/reference/glossary.html#leader","655":"/iroha-2-docs/reference/ffi.html#foreign-function-interfaces-ffi","656":"/iroha-2-docs/reference/ffi.html#why-ffi","657":"/iroha-2-docs/reference/ffi.html#example","658":"/iroha-2-docs/reference/ffi.html#ffi-binding-generation","659":"/iroha-2-docs/reference/ffi.html#name-mangling","660":"/iroha-2-docs/reference/naming.html#naming-conventions","661":"/iroha-2-docs/reference/instructions.html#iroha-special-instructions","662":"/iroha-2-docs/reference/permissions.html#permissions","663":"/iroha-2-docs/reference/permissions.html#permission-tokens","664":"/iroha-2-docs/reference/permissions.html#general-example","665":"/iroha-2-docs/reference/queries.html#queries","666":"/iroha-2-docs/reference/queries.html#conventions","667":"/iroha-2-docs/reference/queries.html#role","668":"/iroha-2-docs/reference/queries.html#findallroles","669":"/iroha-2-docs/reference/queries.html#findallroleids","670":"/iroha-2-docs/reference/queries.html#findrolebyroleid","671":"/iroha-2-docs/reference/queries.html#findrolesbyaccountid","672":"/iroha-2-docs/reference/queries.html#permission","673":"/iroha-2-docs/reference/queries.html#findallpermissiontokendefinitions","674":"/iroha-2-docs/reference/queries.html#findpermissiontokensbyaccountid","675":"/iroha-2-docs/reference/queries.html#account","676":"/iroha-2-docs/reference/queries.html#findallaccounts","677":"/iroha-2-docs/reference/queries.html#findaccountbyid","678":"/iroha-2-docs/reference/queries.html#findaccountkeyvaluebyidandkey","679":"/iroha-2-docs/reference/queries.html#findaccountsbyname","680":"/iroha-2-docs/reference/queries.html#findaccountsbydomainid","681":"/iroha-2-docs/reference/queries.html#findaccountswithasset","682":"/iroha-2-docs/reference/queries.html#asset","683":"/iroha-2-docs/reference/queries.html#findallassets","684":"/iroha-2-docs/reference/queries.html#findallassetdefinitions","685":"/iroha-2-docs/reference/queries.html#findassetbyid","686":"/iroha-2-docs/reference/queries.html#findassetsbyname","687":"/iroha-2-docs/reference/queries.html#findassetsbyaccountid","688":"/iroha-2-docs/reference/queries.html#findassetsbyassetdefinitionid","689":"/iroha-2-docs/reference/queries.html#findassetsbydomainid","690":"/iroha-2-docs/reference/queries.html#findassetsbydomainidandassetdefinitionid","691":"/iroha-2-docs/reference/queries.html#findassetquantitybyid","692":"/iroha-2-docs/reference/queries.html#findassetkeyvaluebyidandkey","693":"/iroha-2-docs/reference/queries.html#findassetdefinitionkeyvaluebyidandkey","694":"/iroha-2-docs/reference/queries.html#findtotalassetquantitybyassetdefinitionid","695":"/iroha-2-docs/reference/queries.html#block","696":"/iroha-2-docs/reference/queries.html#findallblocks","697":"/iroha-2-docs/reference/queries.html#findallblockheaders","698":"/iroha-2-docs/reference/queries.html#findblockheaderbyhash","699":"/iroha-2-docs/reference/queries.html#domain","700":"/iroha-2-docs/reference/queries.html#findalldomains","701":"/iroha-2-docs/reference/queries.html#finddomainbyid","702":"/iroha-2-docs/reference/queries.html#finddomainkeyvaluebyidandkey","703":"/iroha-2-docs/reference/queries.html#peer","704":"/iroha-2-docs/reference/queries.html#findallpeers","705":"/iroha-2-docs/reference/queries.html#findallparameters","706":"/iroha-2-docs/reference/queries.html#transaction","707":"/iroha-2-docs/reference/queries.html#findtransactionsbyaccountid","708":"/iroha-2-docs/reference/queries.html#findtransactionbyhash","709":"/iroha-2-docs/reference/queries.html#trigger","710":"/iroha-2-docs/reference/queries.html#findallactivetriggerids","711":"/iroha-2-docs/reference/queries.html#findtriggerbyid","712":"/iroha-2-docs/reference/queries.html#findtriggerkeyvaluebyidandkey","713":"/iroha-2-docs/reference/queries.html#findtriggersbydomainid","714":"/iroha-2-docs/reference/torii-endpoints.html#torii-endpoints","715":"/iroha-2-docs/reference/torii-endpoints.html#api-version","716":"/iroha-2-docs/reference/torii-endpoints.html#requests","717":"/iroha-2-docs/reference/torii-endpoints.html#responses","718":"/iroha-2-docs/reference/torii-endpoints.html#blocks-stream","719":"/iroha-2-docs/reference/torii-endpoints.html#handshake","720":"/iroha-2-docs/reference/torii-endpoints.html#data-exchange","721":"/iroha-2-docs/reference/torii-endpoints.html#configuration-retrieve","722":"/iroha-2-docs/reference/torii-endpoints.html#requests-1","723":"/iroha-2-docs/reference/torii-endpoints.html#responses-1","724":"/iroha-2-docs/reference/torii-endpoints.html#configuration-update","725":"/iroha-2-docs/reference/torii-endpoints.html#requests-2","726":"/iroha-2-docs/reference/torii-endpoints.html#responses-2","727":"/iroha-2-docs/reference/torii-endpoints.html#events","728":"/iroha-2-docs/reference/torii-endpoints.html#transaction-events","729":"/iroha-2-docs/reference/torii-endpoints.html#handshake-1","730":"/iroha-2-docs/reference/torii-endpoints.html#data-exchange-1","731":"/iroha-2-docs/reference/torii-endpoints.html#health","732":"/iroha-2-docs/reference/torii-endpoints.html#requests-3","733":"/iroha-2-docs/reference/torii-endpoints.html#responses-3","734":"/iroha-2-docs/reference/torii-endpoints.html#metrics","735":"/iroha-2-docs/reference/torii-endpoints.html#responses-4","736":"/iroha-2-docs/reference/torii-endpoints.html#pending-transactions","737":"/iroha-2-docs/reference/torii-endpoints.html#requests-4","738":"/iroha-2-docs/reference/torii-endpoints.html#responses-5","739":"/iroha-2-docs/reference/torii-endpoints.html#query","740":"/iroha-2-docs/reference/torii-endpoints.html#requests-5","741":"/iroha-2-docs/reference/torii-endpoints.html#responses-6","742":"/iroha-2-docs/reference/torii-endpoints.html#account-not-found-404","743":"/iroha-2-docs/reference/torii-endpoints.html#asset-not-found-404","744":"/iroha-2-docs/reference/torii-endpoints.html#schema","745":"/iroha-2-docs/reference/torii-endpoints.html#requests-6","746":"/iroha-2-docs/reference/torii-endpoints.html#responses-7","747":"/iroha-2-docs/reference/torii-endpoints.html#status","748":"/iroha-2-docs/reference/torii-endpoints.html#requests-7","749":"/iroha-2-docs/reference/torii-endpoints.html#responses-8","750":"/iroha-2-docs/reference/torii-endpoints.html#sub-routing","751":"/iroha-2-docs/reference/torii-endpoints.html#transaction","752":"/iroha-2-docs/reference/torii-endpoints.html#requests-8","753":"/iroha-2-docs/reference/torii-endpoints.html#responses-9"},"fieldIds":{"title":0,"titles":1,"text":2},"fieldLength":{"0":[2,1,34],"1":[3,2,1],"2":[2,5,56],"3":[2,5,59],"4":[4,5,47],"5":[1,2,139],"6":[9,1,155],"7":[7,9,25],"8":[4,9,30],"9":[4,9,34],"10":[1,1,38],"11":[3,2,7],"12":[4,1,105],"13":[4,1,88],"14":[1,4,84],"15":[1,4,1],"16":[3,5,203],"17":[2,5,72],"18":[7,4,223],"19":[5,4,36],"20":[3,9,111],"21":[2,9,131],"22":[3,4,90],"23":[1,1,2],"24":[1,1,53],"25":[2,1,71],"26":[2,1,1],"27":[1,1,35],"28":[1,1,161],"29":[2,1,81],"30":[1,1,2],"31":[1,1,31],"32":[2,1,50],"33":[2,1,37],"34":[2,1,16],"35":[3,1,12],"36":[3,1,89],"37":[1,1,22],"38":[2,1,46],"39":[3,1,139],"40":[3,1,112],"41":[1,3,135],"42":[3,3,164],"43":[2,3,82],"44":[1,3,34],"45":[2,3,39],"46":[2,3,37],"47":[2,3,17],"48":[1,3,8],"49":[2,3,28],"50":[1,1,74],"51":[1,1,41],"52":[2,1,78],"53":[3,1,105],"54":[1,1,18],"55":[1,1,25],"56":[1,1,80],"57":[2,1,93],"58":[4,3,14],"59":[4,1,31],"60":[4,5,41],"61":[3,5,29],"62":[2,1,119],"63":[2,3,70],"64":[2,1,17],"65":[1,1,144],"66":[3,1,38],"67":[1,1,70],"68":[1,1,17],"69":[1,1,64],"70":[1,1,12],"71":[1,1,65],"72":[1,1,90],"73":[5,1,14],"74":[2,6,37],"75":[2,6,24],"76":[2,7,16],"77":[2,7,16],"78":[3,7,59],"79":[2,7,55],"80":[2,7,31],"81":[3,1,55],"82":[1,3,61],"83":[3,4,43],"84":[2,3,60],"85":[3,1,49],"86":[2,3,42],"87":[2,3,62],"88":[2,4,200],"89":[3,4,87],"90":[3,3,65],"91":[4,1,34],"92":[3,4,71],"93":[4,4,59],"94":[5,4,155],"95":[5,4,31],"96":[4,4,26],"97":[3,4,253],"98":[2,1,75],"99":[2,1,62],"100":[1,1,103],"101":[3,1,124],"102":[5,1,22],"103":[5,6,149],"104":[5,6,138],"105":[6,1,95],"106":[3,7,90],"107":[6,7,51],"108":[3,7,63],"109":[6,7,41],"110":[1,7,72],"111":[1,1,41],"112":[5,1,28],"113":[2,1,48],"114":[1,2,15],"115":[4,2,30],"116":[2,2,56],"117":[3,2,51],"118":[3,2,25],"119":[3,5,39],"120":[3,5,62],"121":[2,2,31],"122":[4,2,32],"123":[2,2,21],"124":[2,1,43],"125":[4,2,114],"126":[4,2,90],"127":[4,2,96],"128":[2,1,211],"129":[1,2,28],"130":[4,3,39],"131":[1,2,27],"132":[4,1,42],"133":[6,4,1],"134":[5,8,100],"135":[5,8,122],"136":[6,4,70],"137":[7,1,301],"138":[4,1,57],"139":[1,4,41],"140":[1,4,24],"141":[2,4,162],"142":[3,1,1],"143":[2,1,207],"144":[1,2,15],"145":[4,2,36],"146":[2,2,127],"147":[3,2,13],"148":[2,5,46],"149":[2,5,24],"150":[2,5,71],"151":[1,2,88],"152":[1,2,15],"153":[3,3,58],"154":[3,3,98],"155":[1,2,37],"156":[2,1,22],"157":[2,2,26],"158":[2,2,31],"159":[2,4,25],"160":[5,6,83],"161":[5,6,71],"162":[4,6,35],"163":[2,4,57],"164":[3,1,133],"165":[2,1,50],"166":[2,2,94],"167":[3,2,75],"168":[2,2,26],"169":[3,1,19],"170":[2,3,51],"171":[5,3,66],"172":[4,6,58],"173":[3,1,31],"174":[3,3,264],"175":[3,3,332],"176":[4,3,195],"177":[4,3,168],"178":[5,3,186],"179":[3,3,67],"180":[7,3,74],"181":[6,3,366],"182":[1,9,12],"183":[5,3,90],"184":[3,1,1],"185":[5,3,171],"186":[3,3,138],"187":[5,3,220],"188":[4,3,169],"189":[5,3,169],"190":[3,3,159],"191":[3,3,113],"192":[3,3,112],"193":[5,3,138],"194":[3,1,11],"195":[2,3,15],"196":[4,3,233],"197":[2,4,53],"198":[5,1,28],"199":[6,5,35],"200":[5,5,161],"201":[4,5,83],"202":[4,5,128],"203":[4,5,132],"204":[5,5,84],"205":[3,5,26],"206":[3,5,20],"207":[3,5,89],"208":[3,5,38],"209":[3,1,1],"210":[5,3,113],"211":[3,3,101],"212":[4,3,100],"213":[4,3,128],"214":[5,3,203],"215":[3,3,140],"216":[2,1,1],"217":[5,2,238],"218":[3,2,159],"219":[4,2,208],"220":[4,2,168],"221":[5,2,253],"222":[3,2,65],"223":[3,2,37],"224":[3,2,154],"225":[1,1,27],"226":[1,1,80],"227":[1,1,53],"228":[2,1,48],"229":[4,1,84],"230":[2,4,115],"231":[3,4,95],"232":[1,4,77],"233":[2,4,89],"234":[4,4,73],"235":[1,4,41],"236":[6,1,47],"237":[3,1,52],"238":[5,3,234],"239":[1,5,53],"240":[4,3,1],"241":[3,7,87],"242":[8,7,43],"243":[8,7,76],"244":[11,15,77],"245":[1,1,58],"246":[1,2,110],"247":[2,1,150],"248":[3,2,183],"249":[2,2,311],"250":[2,2,158],"251":[2,1,30],"252":[2,2,246],"253":[2,2,248],"254":[3,1,65],"255":[3,3,75],"256":[5,3,173],"257":[2,1,24],"258":[3,2,97],"259":[5,2,153],"260":[4,2,196],"261":[3,1,60],"262":[4,3,61],"263":[4,4,154],"264":[5,4,108],"265":[2,9,103],"266":[2,11,73],"267":[4,3,38],"268":[4,4,167],"269":[4,4,37],"270":[2,1,74],"271":[3,1,38],"272":[7,3,167],"273":[7,3,165],"274":[3,1,26],"275":[1,3,2],"276":[1,3,2],"277":[3,1,26],"278":[3,3,39],"279":[3,5,56],"280":[3,5,60],"281":[5,5,35],"282":[7,5,138],"283":[3,3,91],"284":[3,1,27],"285":[1,1,46],"286":[3,1,73],"287":[2,1,88],"288":[3,1,7],"289":[1,3,24],"290":[1,3,38],"291":[1,3,16],"292":[1,3,31],"293":[1,3,11],"294":[1,3,16],"295":[1,3,12],"296":[1,3,12],"297":[1,3,17],"298":[1,3,16],"299":[6,3,7],"300":[6,3,7],"301":[6,3,7],"302":[1,3,10],"303":[1,3,12],"304":[1,3,23],"305":[1,3,29],"306":[1,3,16],"307":[1,3,23],"308":[1,3,11],"309":[1,3,14],"310":[1,3,14],"311":[1,3,26],"312":[1,3,16],"313":[1,3,21],"314":[1,3,12],"315":[1,3,18],"316":[1,3,13],"317":[1,3,13],"318":[1,3,11],"319":[5,3,14],"320":[5,3,11],"321":[1,3,16],"322":[1,3,14],"323":[1,3,27],"324":[1,3,5],"325":[1,3,20],"326":[1,3,10],"327":[1,3,17],"328":[1,3,8],"329":[6,3,12],"330":[6,3,12],"331":[6,3,12],"332":[1,3,22],"333":[1,3,5],"334":[5,3,5],"335":[5,3,5],"336":[1,3,15],"337":[1,3,16],"338":[1,3,15],"339":[1,3,15],"340":[1,3,29],"341":[1,3,39],"342":[1,3,29],"343":[1,3,30],"344":[1,3,16],"345":[1,3,23],"346":[1,3,8],"347":[1,3,13],"348":[1,3,6],"349":[1,3,23],"350":[1,3,23],"351":[1,3,5],"352":[1,3,8],"353":[1,3,17],"354":[1,3,10],"355":[1,3,12],"356":[1,3,15],"357":[1,3,12],"358":[1,3,9],"359":[1,3,10],"360":[1,3,10],"361":[1,3,11],"362":[1,3,9],"363":[1,3,9],"364":[1,3,11],"365":[1,3,10],"366":[1,3,8],"367":[1,3,11],"368":[1,3,7],"369":[1,3,7],"370":[1,3,7],"371":[1,3,7],"372":[1,3,7],"373":[1,3,7],"374":[1,3,7],"375":[1,3,7],"376":[1,3,7],"377":[1,3,7],"378":[1,3,7],"379":[1,3,7],"380":[1,3,9],"381":[1,3,9],"382":[1,3,11],"383":[1,3,11],"384":[1,3,9],"385":[1,3,10],"386":[1,3,11],"387":[1,3,10],"388":[1,3,13],"389":[1,3,8],"390":[1,3,12],"391":[1,3,9],"392":[1,3,11],"393":[1,3,48],"394":[1,3,7],"395":[1,3,9],"396":[1,3,9],"397":[1,3,9],"398":[1,3,9],"399":[1,3,12],"400":[1,3,10],"401":[1,3,9],"402":[1,3,11],"403":[1,3,10],"404":[1,3,16],"405":[5,3,21],"406":[6,3,12],"407":[6,3,12],"408":[6,3,12],"409":[1,3,19],"410":[1,3,9],"411":[6,3,5],"412":[5,3,5],"413":[5,3,5],"414":[1,3,27],"415":[1,3,32],"416":[1,3,47],"417":[1,3,16],"418":[1,3,39],"419":[1,3,11],"420":[1,3,38],"421":[1,3,13],"422":[1,3,5],"423":[1,3,9],"424":[1,3,9],"425":[1,3,5],"426":[1,3,10],"427":[1,3,18],"428":[1,3,12],"429":[1,3,11],"430":[1,3,23],"431":[5,3,8],"432":[1,3,9],"433":[5,3,13],"434":[5,3,13],"435":[5,3,13],"436":[5,3,13],"437":[5,3,13],"438":[1,3,20],"439":[1,3,28],"440":[6,3,12],"441":[6,3,12],"442":[6,3,12],"443":[6,3,12],"444":[1,3,21],"445":[1,3,12],"446":[1,3,14],"447":[5,3,10],"448":[1,3,5],"449":[1,3,16],"450":[1,3,20],"451":[1,3,16],"452":[1,3,9],"453":[1,3,9],"454":[6,3,9],"455":[5,3,5],"456":[5,3,5],"457":[1,3,14],"458":[1,3,12],"459":[5,3,5],"460":[5,3,5],"461":[5,3,5],"462":[5,3,5],"463":[5,3,5],"464":[5,3,5],"465":[7,3,9],"466":[6,3,8],"467":[6,3,8],"468":[5,3,5],"469":[6,3,8],"470":[6,3,8],"471":[5,3,7],"472":[5,3,5],"473":[5,3,5],"474":[5,3,5],"475":[5,3,5],"476":[5,3,5],"477":[5,3,5],"478":[5,3,5],"479":[5,3,5],"480":[5,3,5],"481":[5,3,5],"482":[5,3,5],"483":[1,3,11],"484":[1,3,8],"485":[1,3,17],"486":[1,3,9],"487":[1,3,13],"488":[1,3,16],"489":[1,3,13],"490":[1,3,12],"491":[1,3,12],"492":[1,3,15],"493":[1,3,11],"494":[1,3,14],"495":[1,3,14],"496":[1,3,14],"497":[1,3,88],"498":[1,3,20],"499":[1,3,36],"500":[1,3,26],"501":[1,3,16],"502":[5,3,9],"503":[5,3,9],"504":[5,3,9],"505":[5,3,9],"506":[5,3,9],"507":[5,3,9],"508":[5,3,9],"509":[1,3,25],"510":[5,3,12],"511":[5,3,12],"512":[5,3,12],"513":[5,3,12],"514":[5,3,12],"515":[1,3,21],"516":[1,3,13],"517":[1,3,12],"518":[6,3,12],"519":[6,3,12],"520":[6,3,12],"521":[1,3,19],"522":[1,3,14],"523":[1,3,19],"524":[1,3,16],"525":[1,3,17],"526":[1,3,8],"527":[1,3,13],"528":[1,3,13],"529":[5,3,10],"530":[5,3,10],"531":[1,3,13],"532":[5,3,13],"533":[5,3,13],"534":[5,3,13],"535":[5,3,13],"536":[5,3,13],"537":[1,3,21],"538":[1,3,9],"539":[1,3,15],"540":[1,3,16],"541":[5,3,5],"542":[5,3,5],"543":[5,3,5],"544":[5,3,13],"545":[5,3,13],"546":[1,3,11],"547":[1,3,13],"548":[1,3,11],"549":[1,3,13],"550":[1,3,11],"551":[1,3,13],"552":[1,3,11],"553":[1,3,17],"554":[1,3,11],"555":[1,3,11],"556":[1,3,11],"557":[6,3,7],"558":[6,3,7],"559":[6,3,7],"560":[6,3,7],"561":[6,3,7],"562":[5,3,5],"563":[5,3,5],"564":[6,3,8],"565":[6,3,8],"566":[1,3,5],"567":[1,3,17],"568":[1,3,13],"569":[1,3,5],"570":[1,3,10],"571":[1,3,18],"572":[1,3,18],"573":[1,3,9],"574":[1,3,14],"575":[1,3,30],"576":[1,3,15],"577":[1,3,23],"578":[1,3,17],"579":[1,3,13],"580":[6,3,13],"581":[6,3,13],"582":[7,3,14],"583":[7,3,14],"584":[1,3,21],"585":[1,3,11],"586":[1,3,12],"587":[1,3,16],"588":[1,3,13],"589":[1,3,12],"590":[1,3,25],"591":[1,3,16],"592":[1,3,21],"593":[1,3,14],"594":[1,3,12],"595":[1,3,20],"596":[1,3,17],"597":[5,3,10],"598":[5,3,10],"599":[5,3,10],"600":[5,3,10],"601":[5,3,10],"602":[5,3,10],"603":[5,3,10],"604":[1,3,25],"605":[1,3,9],"606":[1,3,21],"607":[5,3,5],"608":[5,3,5],"609":[6,3,8],"610":[5,3,5],"611":[5,3,5],"612":[5,3,5],"613":[5,3,5],"614":[5,3,5],"615":[5,3,5],"616":[5,3,5],"617":[5,3,5],"618":[1,3,9],"619":[1,3,8],"620":[1,3,5],"621":[1,3,5],"622":[1,3,5],"623":[1,3,5],"624":[1,3,5],"625":[1,3,5],"626":[1,1,60],"627":[2,1,53],"628":[1,1,66],"629":[1,1,20],"630":[2,2,41],"631":[3,2,54],"632":[2,2,14],"633":[3,2,28],"634":[5,1,26],"635":[2,1,6],"636":[3,3,7],"637":[3,3,27],"638":[3,3,15],"639":[8,3,16],"640":[4,3,28],"641":[2,3,25],"642":[1,3,24],"643":[1,3,30],"644":[5,3,26],"645":[2,1,10],"646":[5,1,24],"647":[4,10,23],"648":[4,6,16],"649":[5,6,28],"650":[4,6,47],"651":[2,1,17],"652":[2,1,21],"653":[5,1,24],"654":[1,1,33],"655":[5,1,39],"656":[2,5,163],"657":[1,5,47],"658":[3,5,141],"659":[2,6,60],"660":[2,1,57],"661":[3,1,64],"662":[1,1,27],"663":[2,1,124],"664":[2,3,80],"665":[1,1,33],"666":[1,1,133],"667":[1,1,32],"668":[1,2,19],"669":[1,2,34],"670":[1,2,28],"671":[1,2,29],"672":[1,1,54],"673":[1,2,13],"674":[1,2,18],"675":[1,1,17],"676":[1,2,15],"677":[1,2,13],"678":[1,2,22],"679":[1,2,37],"680":[1,2,26],"681":[1,2,16],"682":[1,1,25],"683":[1,2,50],"684":[1,2,48],"685":[1,2,14],"686":[1,2,19],"687":[1,2,19],"688":[1,2,20],"689":[1,2,18],"690":[1,2,20],"691":[1,2,26],"692":[1,2,21],"693":[1,2,22],"694":[1,2,27],"695":[1,1,1],"696":[1,2,12],"697":[1,2,15],"698":[1,2,15],"699":[1,1,32],"700":[1,2,33],"701":[1,2,13],"702":[1,2,18],"703":[1,1,34],"704":[1,2,22],"705":[1,2,58],"706":[1,1,22],"707":[1,2,36],"708":[1,2,10],"709":[1,1,32],"710":[1,2,22],"711":[1,2,12],"712":[1,2,20],"713":[1,2,17],"714":[2,1,121],"715":[2,2,27],"716":[1,5,7],"717":[1,5,50],"718":[2,2,11],"719":[1,5,28],"720":[2,5,50],"721":[2,2,9],"722":[1,5,7],"723":[1,5,43],"724":[2,2,9],"725":[1,5,79],"726":[1,5,39],"727":[1,2,10],"728":[2,3,91],"729":[1,4,27],"730":[2,4,19],"731":[1,2,9],"732":[1,5,7],"733":[1,5,18],"734":[1,2,24],"735":[1,5,91],"736":[2,2,10],"737":[1,6,7],"738":[1,6,24],"739":[1,2,9],"740":[1,5,29],"741":[1,5,85],"742":[4,3,15],"743":[4,3,20],"744":[1,2,23],"745":[1,7,7],"746":[1,7,21],"747":[1,2,26],"748":[1,7,40],"749":[1,7,126],"750":[2,3,58],"751":[1,2,9],"752":[1,5,9],"753":[1,5,30]},"averageFieldLength":[2.5384615384615405,2.957559681697612,42.03050397877991],"storedFields":{"0":{"title":"Code Snippets","titles":[]},"1":{"title":"How it works","titles":["Code Snippets"]},"2":{"title":"Snippet Sources","titles":["Code Snippets","How it works"]},"3":{"title":"Fetching Snippets","titles":["Code Snippets","How it works"]},"4":{"title":"Using Snippets in Markdown","titles":["Code Snippets","How it works"]},"5":{"title":"Example","titles":["Code Snippets"]},"6":{"title":"How to hot reload Iroha in a Docker container","titles":[]},"7":{"title":"Wiping previous blockchain state (recommit genesis)","titles":["How to hot reload Iroha in a Docker container"]},"8":{"title":"Use custom configuration files","titles":["How to hot reload Iroha in a Docker container"]},"9":{"title":"Use custom environment variables","titles":["How to hot reload Iroha in a Docker container"]},"10":{"title":"Metrics","titles":[]},"11":{"title":"/metrics Endpoint","titles":["Metrics",null,null]},"12":{"title":"How to use metrics","titles":["Metrics"]},"13":{"title":"Iroha on bare metal","titles":[]},"14":{"title":"Prerequisites","titles":["Iroha on bare metal"]},"15":{"title":"Setup","titles":["Iroha on bare metal"]},"16":{"title":"Setup: Environment variables","titles":["Iroha on bare metal","Setup"]},"17":{"title":"Setup: Files","titles":["Iroha on bare metal","Setup"]},"18":{"title":"First run of Iroha on bare metal","titles":["Iroha on bare metal"]},"19":{"title":"Deploy a minimal BFT network","titles":["Iroha on bare metal"]},"20":{"title":"Using Environment Variables","titles":["Iroha on bare metal","Deploy a minimal BFT network"]},"21":{"title":"Using Files","titles":["Iroha on bare metal","Deploy a minimal BFT network"]},"22":{"title":"Real-world deployment","titles":["Iroha on bare metal"]},"23":{"title":"Accounts","titles":[]},"24":{"title":"Assets","titles":[]},"25":{"title":"Value Types","titles":["Assets"]},"26":{"title":"Asset Structure","titles":["Assets"]},"27":{"title":"Instructions","titles":["Assets"]},"28":{"title":"Consensus","titles":[]},"29":{"title":"Data Model","titles":[]},"30":{"title":"Domains","titles":[]},"31":{"title":"Events","titles":[]},"32":{"title":"Pipeline Events","titles":["Events"]},"33":{"title":"Data Events","titles":["Events"]},"34":{"title":"Time Events","titles":["Events"]},"35":{"title":"Trigger Execution Events","titles":["Events"]},"36":{"title":"Expressions, Conditionals, Logic","titles":[]},"37":{"title":"Filters","titles":[]},"38":{"title":"Data Filters","titles":["Filters"]},"39":{"title":"How Iroha works","titles":[]},"40":{"title":"Iroha Special Instructions","titles":[]},"41":{"title":"Summary","titles":["Iroha Special Instructions"]},"42":{"title":"(Un)Register","titles":["Iroha Special Instructions"]},"43":{"title":"Mint/Burn","titles":["Iroha Special Instructions"]},"44":{"title":"Transfer","titles":["Iroha Special Instructions"]},"45":{"title":"Grant/Revoke","titles":["Iroha Special Instructions"]},"46":{"title":"SetKeyValue/RemoveKeyValue","titles":["Iroha Special Instructions"]},"47":{"title":"NewParameter/SetParameter","titles":["Iroha Special Instructions"]},"48":{"title":"ExecuteTrigger","titles":["Iroha Special Instructions"]},"49":{"title":"Composite instructions","titles":["Iroha Special Instructions"]},"50":{"title":"Metadata","titles":[]},"51":{"title":"MetadataChanged","titles":["Metadata"]},"52":{"title":"Store Asset","titles":["Metadata"]},"53":{"title":"Working with metadata","titles":["Metadata"]},"54":{"title":"Queries","titles":["Metadata"]},"55":{"title":"Permissions","titles":["Metadata"]},"56":{"title":"Permissions","titles":[]},"57":{"title":"Permission Tokens","titles":["Permissions"]},"58":{"title":"Pre-configured Permission Tokens","titles":["Permissions","Permission Tokens"]},"59":{"title":"Permission Groups (Roles)","titles":["Permissions"]},"60":{"title":"Register a new role","titles":["Permissions","Permission Groups (Roles)"]},"61":{"title":"Grant a role","titles":["Permissions","Permission Groups (Roles)"]},"62":{"title":"Permission Validators","titles":["Permissions"]},"63":{"title":"Runtime Validators","titles":["Permissions","Permission Validators"]},"64":{"title":"Supported Queries","titles":["Permissions"]},"65":{"title":"Queries","titles":[]},"66":{"title":"Create a query","titles":["Queries"]},"67":{"title":"Pagination","titles":["Queries"]},"68":{"title":"Filters","titles":["Queries"]},"69":{"title":"Sorting","titles":["Queries"]},"70":{"title":"Reference","titles":["Queries"]},"71":{"title":"Transactions","titles":[]},"72":{"title":"Triggers","titles":[]},"73":{"title":"The Anatomy of a Trigger","titles":["Triggers"]},"74":{"title":"Trigger.id","titles":["Triggers","The Anatomy of a Trigger"]},"75":{"title":"Trigger.action","titles":["Triggers","The Anatomy of a Trigger"]},"76":{"title":"Action.executable","titles":["Triggers","The Anatomy of a Trigger","Trigger.action"]},"77":{"title":"Action.repeats","titles":["Triggers","The Anatomy of a Trigger","Trigger.action"]},"78":{"title":"Action.technical_account","titles":["Triggers","The Anatomy of a Trigger","Trigger.action"]},"79":{"title":"Action.filter","titles":["Triggers","The Anatomy of a Trigger","Trigger.action"]},"80":{"title":"Action.metadata","titles":["Triggers","The Anatomy of a Trigger","Trigger.action"]},"81":{"title":"How Triggers Work","titles":["Triggers"]},"82":{"title":"Scope","titles":["Triggers","How Triggers Work"]},"83":{"title":"Domain-scoped Triggers","titles":["Triggers","How Triggers Work","Scope"]},"84":{"title":"Repetition Schema","titles":["Triggers","How Triggers Work"]},"85":{"title":"Types of Triggers","titles":["Triggers"]},"86":{"title":"Data Triggers","titles":["Triggers","Types of Triggers"]},"87":{"title":"Time Triggers","titles":["Triggers","Types of Triggers"]},"88":{"title":"Scheduled Triggers","titles":["Triggers","Types of Triggers","Time Triggers"]},"89":{"title":"Pre-commit Triggers","titles":["Triggers","Types of Triggers","Time Triggers"]},"90":{"title":"By-call Triggers","titles":["Triggers","Types of Triggers"]},"91":{"title":"Event Triggers by Example","titles":["Triggers"]},"92":{"title":"1. Register accounts","titles":["Triggers","Event Triggers by Example"]},"93":{"title":"2. Register a trigger","titles":["Triggers","Event Triggers by Example"]},"94":{"title":"3. Define an event filter","titles":["Triggers","Event Triggers by Example"]},"95":{"title":"4. Create a Trigger instance","titles":["Triggers","Event Triggers by Example"]},"96":{"title":"5. Create a transaction","titles":["Triggers","Event Triggers by Example"]},"97":{"title":"How it works","titles":["Triggers","Event Triggers by Example"]},"98":{"title":"Supported ISI","titles":["Triggers"]},"99":{"title":"Supported Queries","titles":["Triggers"]},"100":{"title":"WASM","titles":[]},"101":{"title":"Working with WASM","titles":["WASM"]},"102":{"title":"Simple Rust Smart Contract Example","titles":["WASM"]},"103":{"title":"1. Create a new project","titles":["WASM","Simple Rust Smart Contract Example"]},"104":{"title":"2. Write a smart contract","titles":["WASM","Simple Rust Smart Contract Example"]},"105":{"title":"Advanced Smart Contracts: Optimising for Size","titles":["WASM"]},"106":{"title":"Remove debugging info","titles":["WASM","Advanced Smart Contracts: Optimising for Size"]},"107":{"title":"Work under a no_std environment","titles":["WASM","Advanced Smart Contracts: Optimising for Size"]},"108":{"title":"Re-compile libcore","titles":["WASM","Advanced Smart Contracts: Optimising for Size"]},"109":{"title":"Use tools to optimise WASM size","titles":["WASM","Advanced Smart Contracts: Optimising for Size"]},"110":{"title":"Conclusion","titles":["WASM","Advanced Smart Contracts: Optimising for Size"]},"111":{"title":"World","titles":[]},"112":{"title":"World State View (WSV)","titles":["World"]},"113":{"title":"Client Configuration","titles":[]},"114":{"title":"Generation","titles":["Client Configuration"]},"115":{"title":"Public and Private Keys","titles":["Client Configuration"]},"116":{"title":"User account","titles":["Client Configuration"]},"117":{"title":"Basic Authentication Credentials","titles":["Client Configuration"]},"118":{"title":"Iroha Public Addresses","titles":["Client Configuration"]},"119":{"title":"TORII_API_URL","titles":["Client Configuration","Iroha Public Addresses"]},"120":{"title":"TORII_TELEMETRY_URL","titles":["Client Configuration","Iroha Public Addresses"]},"121":{"title":"Transaction Limits","titles":["Client Configuration"]},"122":{"title":"Transaction TTL and Timeout","titles":["Client Configuration"]},"123":{"title":"Transaction Nonce","titles":["Client Configuration"]},"124":{"title":"Configuration Types","titles":[]},"125":{"title":"Option<..>","titles":["Configuration Types"]},"126":{"title":"Option<Option<..>>","titles":["Configuration Types"]},"127":{"title":"Sumeragi: default null values","titles":["Configuration Types"]},"128":{"title":"Genesis Block","titles":[]},"129":{"title":"Generation","titles":["Genesis Block"]},"130":{"title":"Generate default genesis block","titles":["Genesis Block","Generation"]},"131":{"title":"Configuration","titles":["Genesis Block"]},"132":{"title":"Keys for Network Deployment","titles":[]},"133":{"title":"Setting Keys For a New Network","titles":["Keys for Network Deployment"]},"134":{"title":"1. Generate New Key Pairs","titles":["Keys for Network Deployment","Setting Keys For a New Network"]},"135":{"title":"2. Update Keys For Peers","titles":["Keys for Network Deployment","Setting Keys For a New Network"]},"136":{"title":"3. Register a Non-Genesis Account","titles":["Keys for Network Deployment"]},"137":{"title":"Choosing Between the Store and Metadata Assets","titles":[]},"138":{"title":"Public and Private Blockchains","titles":[]},"139":{"title":"Permissions","titles":["Public and Private Blockchains"]},"140":{"title":"Peers","titles":["Public and Private Blockchains"]},"141":{"title":"Registering accounts","titles":["Public and Private Blockchains"]},"142":{"title":"Configuration and Management","titles":[]},"143":{"title":"Peer Configuration","titles":[]},"144":{"title":"Generation","titles":["Peer Configuration"]},"145":{"title":"Public and private keys","titles":["Peer Configuration"]},"146":{"title":"Trusted Peers","titles":["Peer Configuration"]},"147":{"title":"Iroha Public Addresses","titles":["Peer Configuration"]},"148":{"title":"API_URL","titles":["Peer Configuration","Iroha Public Addresses"]},"149":{"title":"P2P_ADDR","titles":["Peer Configuration","Iroha Public Addresses"]},"150":{"title":"TELEMETRY_URL","titles":["Peer Configuration","Iroha Public Addresses"]},"151":{"title":"Genesis","titles":["Peer Configuration"]},"152":{"title":"Logger","titles":["Peer Configuration"]},"153":{"title":"MAX_LOG_LEVEL","titles":["Peer Configuration","Logger"]},"154":{"title":"LOG_FILE_PATH","titles":["Peer Configuration","Logger"]},"155":{"title":"Kura","titles":["Peer Configuration"]},"156":{"title":"Peer Management","titles":[]},"157":{"title":"Public Blockchain","titles":["Peer Management"]},"158":{"title":"Private Blockchain","titles":["Peer Management"]},"159":{"title":"Registering peers","titles":["Peer Management","Private Blockchain"]},"160":{"title":"1. Grant the user permissions","titles":["Peer Management","Private Blockchain","Registering peers"]},"161":{"title":"2. Set up a peer","titles":["Peer Management","Private Blockchain","Registering peers"]},"162":{"title":"3. Submit the instruction","titles":["Peer Management","Private Blockchain","Registering peers"]},"163":{"title":"Unregistering peers","titles":["Peer Management","Private Blockchain"]},"164":{"title":"Sample Configuration Files","titles":[]},"165":{"title":"Iroha 2","titles":[]},"166":{"title":"Get Started","titles":["Iroha 2"]},"167":{"title":"Explore In-Depth","titles":["Iroha 2"]},"168":{"title":"Learn More","titles":["Iroha 2"]},"169":{"title":"Install Iroha 2","titles":[]},"170":{"title":"1. Prerequisites","titles":["Install Iroha 2"]},"171":{"title":"2. Clone Iroha from GitHub","titles":["Install Iroha 2"]},"172":{"title":"3. Install Iroha Binaries","titles":["Install Iroha 2","2. Clone Iroha from GitHub"]},"173":{"title":"JavaScript/TypeScript Guide","titles":[]},"174":{"title":"1. Client Installation","titles":["JavaScript/TypeScript Guide"]},"175":{"title":"2. Client Configuration","titles":["JavaScript/TypeScript Guide"]},"176":{"title":"3. Registering a Domain","titles":["JavaScript/TypeScript Guide"]},"177":{"title":"4. Registering an Account","titles":["JavaScript/TypeScript Guide"]},"178":{"title":"5. Registering and minting assets","titles":["JavaScript/TypeScript Guide"]},"179":{"title":"6. Transferring assets","titles":["JavaScript/TypeScript Guide"]},"180":{"title":"7. Querying for Domains, Accounts and Assets","titles":["JavaScript/TypeScript Guide"]},"181":{"title":"8. Visualizing outputs in Web UI","titles":["JavaScript/TypeScript Guide"]},"182":{"title":"Demo","titles":["JavaScript/TypeScript Guide","8. Visualizing outputs in Web UI"]},"183":{"title":"9. Subscribing to Block Stream","titles":["JavaScript/TypeScript Guide"]},"184":{"title":"Kotlin/Java Guide","titles":[]},"185":{"title":"1. Iroha 2 Client Setup","titles":["Kotlin/Java Guide"]},"186":{"title":"2. Configuring Iroha 2","titles":["Kotlin/Java Guide"]},"187":{"title":"3. Querying and Registering Domains","titles":["Kotlin/Java Guide"]},"188":{"title":"4. Registering an Account","titles":["Kotlin/Java Guide"]},"189":{"title":"5. Registering and minting assets","titles":["Kotlin/Java Guide"]},"190":{"title":"6. Transferring assets","titles":["Kotlin/Java Guide"]},"191":{"title":"7. Burning assets","titles":["Kotlin/Java Guide"]},"192":{"title":"8. Visualizing outputs","titles":["Kotlin/Java Guide"]},"193":{"title":"9. Samples in pure Java","titles":["Kotlin/Java Guide"]},"194":{"title":"Launch Iroha 2","titles":[]},"195":{"title":"1. Prerequisites","titles":["Launch Iroha 2"]},"196":{"title":"2. Launch Iroha Network","titles":["Launch Iroha 2"]},"197":{"title":"Docker Options","titles":["Launch Iroha 2","2. Launch Iroha Network"]},"198":{"title":"Operate Iroha 2 via CLI","titles":[]},"199":{"title":"1. Set Up Iroha Client CLI","titles":["Operate Iroha 2 via CLI"]},"200":{"title":"2. Configure Iroha Client CLI","titles":["Operate Iroha 2 via CLI"]},"201":{"title":"3. Register a Domain","titles":["Operate Iroha 2 via CLI"]},"202":{"title":"4. Register an Account","titles":["Operate Iroha 2 via CLI"]},"203":{"title":"5. Transfer a Domain","titles":["Operate Iroha 2 via CLI"]},"204":{"title":"6. Register and Mint Assets","titles":["Operate Iroha 2 via CLI"]},"205":{"title":"7. Transfer Assets","titles":["Operate Iroha 2 via CLI"]},"206":{"title":"8. Burn Assets","titles":["Operate Iroha 2 via CLI"]},"207":{"title":"9. Visualize Outputs","titles":["Operate Iroha 2 via CLI"]},"208":{"title":"What\'s Next","titles":["Operate Iroha 2 via CLI"]},"209":{"title":"Python 3 Guide","titles":[]},"210":{"title":"1. Iroha 2 Client Setup","titles":["Python 3 Guide"]},"211":{"title":"2. Configuring Iroha 2","titles":["Python 3 Guide"]},"212":{"title":"3. Registering a Domain","titles":["Python 3 Guide"]},"213":{"title":"4. Registering an Account","titles":["Python 3 Guide"]},"214":{"title":"5. Registering and minting assets","titles":["Python 3 Guide"]},"215":{"title":"6. Visualizing outputs","titles":["Python 3 Guide"]},"216":{"title":"Rust Guide","titles":[]},"217":{"title":"1. Iroha 2 Client Setup","titles":["Rust Guide"]},"218":{"title":"2. Configuring Iroha 2","titles":["Rust Guide"]},"219":{"title":"3. Registering a Domain","titles":["Rust Guide"]},"220":{"title":"4. Registering an Account","titles":["Rust Guide"]},"221":{"title":"5. Registering and minting assets","titles":["Rust Guide"]},"222":{"title":"6. Transferring assets","titles":["Rust Guide"]},"223":{"title":"7. Burning assets","titles":["Rust Guide"]},"224":{"title":"8. Visualising outputs","titles":["Rust Guide"]},"225":{"title":"Introduction","titles":[]},"226":{"title":"Preamble","titles":["Introduction"]},"227":{"title":"Navigation","titles":["Introduction"]},"228":{"title":"Tutorial Updates","titles":["Introduction"]},"229":{"title":"Iroha 2 vs. Iroha 1","titles":[]},"230":{"title":"Fault Tolerance","titles":["Iroha 2 vs. Iroha 1"]},"231":{"title":"Minimalist Code Base","titles":["Iroha 2 vs. Iroha 1"]},"232":{"title":"Flexibility","titles":["Iroha 2 vs. Iroha 1"]},"233":{"title":"Smart Contracts","titles":["Iroha 2 vs. Iroha 1"]},"234":{"title":"Static and Dynamic Linking","titles":["Iroha 2 vs. Iroha 1"]},"235":{"title":"Testing","titles":["Iroha 2 vs. Iroha 1"]},"236":{"title":"CSD/RTGS linkages Proof of concept","titles":[]},"237":{"title":"Generating Cryptographic Keys","titles":[]},"238":{"title":"Generating Cryptographic Keys with Kagami","titles":["Generating Cryptographic Keys"]},"239":{"title":"Examples","titles":["Generating Cryptographic Keys","Generating Cryptographic Keys with Kagami"]},"240":{"title":"Other Operations with Kagami","titles":["Generating Cryptographic Keys"]},"241":{"title":"1. Building kagami","titles":["Generating Cryptographic Keys","Other Operations with Kagami"]},"242":{"title":"2. Installing the source-built kagami into /bin","titles":["Generating Cryptographic Keys","Other Operations with Kagami"]},"243":{"title":"3. Moving kagami to the .local/bin directory","titles":["Generating Cryptographic Keys","Other Operations with Kagami"]},"244":{"title":"Making the <username>/.local/bin directory available to the shell","titles":["Generating Cryptographic Keys","Other Operations with Kagami","3. Moving kagami to the .local/bin directory"]},"245":{"title":"Security","titles":[]},"246":{"title":"Navigation","titles":["Security",null]},"247":{"title":"Operational Security","titles":[]},"248":{"title":"Recommended OPSEC Measures","titles":["Operational Security"]},"249":{"title":"Using Browsers","titles":["Operational Security"]},"250":{"title":"Recovery Plan","titles":["Operational Security"]},"251":{"title":"Password Security","titles":[]},"252":{"title":"Password Strength","titles":["Password Security"]},"253":{"title":"Password Vulnerabilities","titles":["Password Security"]},"254":{"title":"Public Key Cryptography","titles":[]},"255":{"title":"Encryption and Signatures","titles":["Public Key Cryptography"]},"256":{"title":"Keys on the Client Side","titles":["Public Key Cryptography"]},"257":{"title":"Security Principles","titles":[]},"258":{"title":"General Security Principles","titles":["Security Principles"]},"259":{"title":"Security Principles for Individual Users","titles":["Security Principles"]},"260":{"title":"Security Principles for Organisations","titles":["Security Principles"]},"261":{"title":"Storing Cryptographic Keys","titles":[]},"262":{"title":"Storing Cryptographic Keys Digitally","titles":["Storing Cryptographic Keys"]},"263":{"title":"Using SSH and SSH Agent","titles":["Storing Cryptographic Keys","Storing Cryptographic Keys Digitally"]},"264":{"title":"Adding a Password Manager Program","titles":["Storing Cryptographic Keys","Storing Cryptographic Keys Digitally"]},"265":{"title":"Configuring KeePassXC","titles":["Storing Cryptographic Keys","Storing Cryptographic Keys Digitally","Adding a Password Manager Program"]},"266":{"title":"Expected Results","titles":["Storing Cryptographic Keys","Storing Cryptographic Keys Digitally","Adding a Password Manager Program","Configuring KeePassXC"]},"267":{"title":"Storing Cryptographic Keys Physically","titles":["Storing Cryptographic Keys"]},"268":{"title":"Using a Hardware Key","titles":["Storing Cryptographic Keys","Storing Cryptographic Keys Physically"]},"269":{"title":"Using a Mnemonic Phrase","titles":["Storing Cryptographic Keys","Storing Cryptographic Keys Physically"]},"270":{"title":"Receive support","titles":[]},"271":{"title":"Troubleshooting Configuration Issues","titles":[]},"272":{"title":"Outdated genesis on a Docker-compose setup","titles":["Troubleshooting Configuration Issues"]},"273":{"title":"Multihash Format of Private and Public Keys","titles":["Troubleshooting Configuration Issues"]},"274":{"title":"Troubleshooting Deployment Issues","titles":[]},"275":{"title":"Docker","titles":["Troubleshooting Deployment Issues"]},"276":{"title":"Kubernetes","titles":["Troubleshooting Deployment Issues"]},"277":{"title":"Troubleshooting Installation Issues","titles":[]},"278":{"title":"Troubleshooting Rust Toolchain","titles":["Troubleshooting Installation Issues"]},"279":{"title":"Check Rust version","titles":["Troubleshooting Installation Issues","Troubleshooting Rust Toolchain"]},"280":{"title":"Check installation location","titles":["Troubleshooting Installation Issues","Troubleshooting Rust Toolchain"]},"281":{"title":"Check the default Rust version","titles":["Troubleshooting Installation Issues","Troubleshooting Rust Toolchain"]},"282":{"title":"Check if there are other Rust versions","titles":["Troubleshooting Installation Issues","Troubleshooting Rust Toolchain"]},"283":{"title":"Troubleshooting Python toolchain","titles":["Troubleshooting Installation Issues"]},"284":{"title":"Troubleshooting Integration Issues","titles":[]},"285":{"title":"Troubleshooting","titles":[]},"286":{"title":"Check the keys","titles":["Troubleshooting"]},"287":{"title":"Compatibility Matrix","titles":[]},"288":{"title":"Data Model Schema","titles":[]},"289":{"title":"Account","titles":["Data Model Schema"]},"290":{"title":"AccountEvent","titles":["Data Model Schema"]},"291":{"title":"AccountEventFilter","titles":["Data Model Schema"]},"292":{"title":"AccountEventSet","titles":["Data Model Schema"]},"293":{"title":"AccountId","titles":["Data Model Schema"]},"294":{"title":"AccountMintBox","titles":["Data Model Schema"]},"295":{"title":"AccountPermissionChanged","titles":["Data Model Schema"]},"296":{"title":"AccountRoleChanged","titles":["Data Model Schema"]},"297":{"title":"Action","titles":["Data Model Schema"]},"298":{"title":"Algorithm","titles":["Data Model Schema"]},"299":{"title":"Array<u16, 8>","titles":["Data Model Schema"]},"300":{"title":"Array<u8, 32>","titles":["Data Model Schema"]},"301":{"title":"Array<u8, 4>","titles":["Data Model Schema"]},"302":{"title":"Asset","titles":["Data Model Schema"]},"303":{"title":"AssetChanged","titles":["Data Model Schema"]},"304":{"title":"AssetDefinition","titles":["Data Model Schema"]},"305":{"title":"AssetDefinitionEvent","titles":["Data Model Schema"]},"306":{"title":"AssetDefinitionEventFilter","titles":["Data Model Schema"]},"307":{"title":"AssetDefinitionEventSet","titles":["Data Model Schema"]},"308":{"title":"AssetDefinitionId","titles":["Data Model Schema"]},"309":{"title":"AssetDefinitionOwnerChanged","titles":["Data Model Schema"]},"310":{"title":"AssetDefinitionTotalQuantityChanged","titles":["Data Model Schema"]},"311":{"title":"AssetEvent","titles":["Data Model Schema"]},"312":{"title":"AssetEventFilter","titles":["Data Model Schema"]},"313":{"title":"AssetEventSet","titles":["Data Model Schema"]},"314":{"title":"AssetId","titles":["Data Model Schema"]},"315":{"title":"AssetTransferBox","titles":["Data Model Schema"]},"316":{"title":"AssetValue","titles":["Data Model Schema"]},"317":{"title":"AssetValueType","titles":["Data Model Schema"]},"318":{"title":"AtIndex","titles":["Data Model Schema"]},"319":{"title":"BatchedResponse<QueryOutputBox>","titles":["Data Model Schema"]},"320":{"title":"BatchedResponseV1<QueryOutputBox>","titles":["Data Model Schema"]},"321":{"title":"BlockEvent","titles":["Data Model Schema"]},"322":{"title":"BlockEventFilter","titles":["Data Model Schema"]},"323":{"title":"BlockHeader","titles":["Data Model Schema"]},"324":{"title":"BlockMessage","titles":["Data Model Schema"]},"325":{"title":"BlockPayload","titles":["Data Model Schema"]},"326":{"title":"BlockRejectionReason","titles":["Data Model Schema"]},"327":{"title":"BlockStatus","titles":["Data Model Schema"]},"328":{"title":"BlockSubscriptionRequest","titles":["Data Model Schema"]},"329":{"title":"Burn<Numeric, Asset>","titles":["Data Model Schema"]},"330":{"title":"Burn<PublicKey, Account>","titles":["Data Model Schema"]},"331":{"title":"Burn<u32, Trigger>","titles":["Data Model Schema"]},"332":{"title":"BurnBox","titles":["Data Model Schema"]},"333":{"title":"ChainId","titles":["Data Model Schema"]},"334":{"title":"Compact<u128>","titles":["Data Model Schema"]},"335":{"title":"Compact<u32>","titles":["Data Model Schema"]},"336":{"title":"ConfigurationEvent","titles":["Data Model Schema"]},"337":{"title":"ConfigurationEventFilter","titles":["Data Model Schema"]},"338":{"title":"ConfigurationEventSet","titles":["Data Model Schema"]},"339":{"title":"Container","titles":["Data Model Schema"]},"340":{"title":"DataEvent","titles":["Data Model Schema"]},"341":{"title":"DataEventFilter","titles":["Data Model Schema"]},"342":{"title":"Domain","titles":["Data Model Schema"]},"343":{"title":"DomainEvent","titles":["Data Model Schema"]},"344":{"title":"DomainEventFilter","titles":["Data Model Schema"]},"345":{"title":"DomainEventSet","titles":["Data Model Schema"]},"346":{"title":"DomainId","titles":["Data Model Schema"]},"347":{"title":"DomainOwnerChanged","titles":["Data Model Schema"]},"348":{"title":"Duration","titles":["Data Model Schema"]},"349":{"title":"EventBox","titles":["Data Model Schema"]},"350":{"title":"EventFilterBox","titles":["Data Model Schema"]},"351":{"title":"EventMessage","titles":["Data Model Schema"]},"352":{"title":"EventSubscriptionRequest","titles":["Data Model Schema"]},"353":{"title":"Executable","titles":["Data Model Schema"]},"354":{"title":"ExecuteTrigger","titles":["Data Model Schema"]},"355":{"title":"ExecuteTriggerEvent","titles":["Data Model Schema"]},"356":{"title":"ExecuteTriggerEventFilter","titles":["Data Model Schema"]},"357":{"title":"ExecutionTime","titles":["Data Model Schema"]},"358":{"title":"Executor","titles":["Data Model Schema"]},"359":{"title":"ExecutorEvent","titles":["Data Model Schema"]},"360":{"title":"ExecutorEventFilter","titles":["Data Model Schema"]},"361":{"title":"ExecutorEventSet","titles":["Data Model Schema"]},"362":{"title":"Fail","titles":["Data Model Schema"]},"363":{"title":"FindAccountById","titles":["Data Model Schema"]},"364":{"title":"FindAccountKeyValueByIdAndKey","titles":["Data Model Schema"]},"365":{"title":"FindAccountsByDomainId","titles":["Data Model Schema"]},"366":{"title":"FindAccountsByName","titles":["Data Model Schema"]},"367":{"title":"FindAccountsWithAsset","titles":["Data Model Schema"]},"368":{"title":"FindAllAccounts","titles":["Data Model Schema"]},"369":{"title":"FindAllActiveTriggerIds","titles":["Data Model Schema"]},"370":{"title":"FindAllAssets","titles":["Data Model Schema"]},"371":{"title":"FindAllAssetsDefinitions","titles":["Data Model Schema"]},"372":{"title":"FindAllBlockHeaders","titles":["Data Model Schema"]},"373":{"title":"FindAllBlocks","titles":["Data Model Schema"]},"374":{"title":"FindAllDomains","titles":["Data Model Schema"]},"375":{"title":"FindAllParameters","titles":["Data Model Schema"]},"376":{"title":"FindAllPeers","titles":["Data Model Schema"]},"377":{"title":"FindAllRoleIds","titles":["Data Model Schema"]},"378":{"title":"FindAllRoles","titles":["Data Model Schema"]},"379":{"title":"FindAllTransactions","titles":["Data Model Schema"]},"380":{"title":"FindAssetById","titles":["Data Model Schema"]},"381":{"title":"FindAssetDefinitionById","titles":["Data Model Schema"]},"382":{"title":"FindAssetDefinitionKeyValueByIdAndKey","titles":["Data Model Schema"]},"383":{"title":"FindAssetKeyValueByIdAndKey","titles":["Data Model Schema"]},"384":{"title":"FindAssetQuantityById","titles":["Data Model Schema"]},"385":{"title":"FindAssetsByAccountId","titles":["Data Model Schema"]},"386":{"title":"FindAssetsByAssetDefinitionId","titles":["Data Model Schema"]},"387":{"title":"FindAssetsByDomainId","titles":["Data Model Schema"]},"388":{"title":"FindAssetsByDomainIdAndAssetDefinitionId","titles":["Data Model Schema"]},"389":{"title":"FindAssetsByName","titles":["Data Model Schema"]},"390":{"title":"FindBlockHeaderByHash","titles":["Data Model Schema"]},"391":{"title":"FindDomainById","titles":["Data Model Schema"]},"392":{"title":"FindDomainKeyValueByIdAndKey","titles":["Data Model Schema"]},"393":{"title":"FindError","titles":["Data Model Schema"]},"394":{"title":"FindPermissionTokenSchema","titles":["Data Model Schema"]},"395":{"title":"FindPermissionTokensByAccountId","titles":["Data Model Schema"]},"396":{"title":"FindRoleByRoleId","titles":["Data Model Schema"]},"397":{"title":"FindRolesByAccountId","titles":["Data Model Schema"]},"398":{"title":"FindTotalAssetQuantityByAssetDefinitionId","titles":["Data Model Schema"]},"399":{"title":"FindTransactionByHash","titles":["Data Model Schema"]},"400":{"title":"FindTransactionsByAccountId","titles":["Data Model Schema"]},"401":{"title":"FindTriggerById","titles":["Data Model Schema"]},"402":{"title":"FindTriggerKeyValueByIdAndKey","titles":["Data Model Schema"]},"403":{"title":"FindTriggersByDomainId","titles":["Data Model Schema"]},"404":{"title":"ForwardCursor","titles":["Data Model Schema"]},"405":{"title":"GenericPredicateBox<QueryOutputPredicate>","titles":["Data Model Schema"]},"406":{"title":"Grant<PermissionToken, Account>","titles":["Data Model Schema"]},"407":{"title":"Grant<PermissionToken, Role>","titles":["Data Model Schema"]},"408":{"title":"Grant<RoleId, Account>","titles":["Data Model Schema"]},"409":{"title":"GrantBox","titles":["Data Model Schema"]},"410":{"title":"Hash","titles":["Data Model Schema"]},"411":{"title":"HashOf<MerkleTree<SignedTransaction>>","titles":["Data Model Schema"]},"412":{"title":"HashOf<SignedBlock>","titles":["Data Model Schema"]},"413":{"title":"HashOf<SignedTransaction>","titles":["Data Model Schema"]},"414":{"title":"IdBox","titles":["Data Model Schema"]},"415":{"title":"IdentifiableBox","titles":["Data Model Schema"]},"416":{"title":"InstructionBox","titles":["Data Model Schema"]},"417":{"title":"InstructionEvaluationError","titles":["Data Model Schema"]},"418":{"title":"InstructionExecutionError","titles":["Data Model Schema"]},"419":{"title":"InstructionExecutionFail","titles":["Data Model Schema"]},"420":{"title":"InstructionType","titles":["Data Model Schema"]},"421":{"title":"InvalidParameterError","titles":["Data Model Schema"]},"422":{"title":"IpfsPath","titles":["Data Model Schema"]},"423":{"title":"Ipv4Addr","titles":["Data Model Schema"]},"424":{"title":"Ipv6Addr","titles":["Data Model Schema"]},"425":{"title":"JsonString","titles":["Data Model Schema"]},"426":{"title":"LengthLimits","titles":["Data Model Schema"]},"427":{"title":"Level","titles":["Data Model Schema"]},"428":{"title":"Limits","titles":["Data Model Schema"]},"429":{"title":"Log","titles":["Data Model Schema"]},"430":{"title":"MathError","titles":["Data Model Schema"]},"431":{"title":"MerkleTree<SignedTransaction>","titles":["Data Model Schema"]},"432":{"title":"Metadata","titles":["Data Model Schema"]},"433":{"title":"MetadataChanged<AccountId>","titles":["Data Model Schema"]},"434":{"title":"MetadataChanged<AssetDefinitionId>","titles":["Data Model Schema"]},"435":{"title":"MetadataChanged<AssetId>","titles":["Data Model Schema"]},"436":{"title":"MetadataChanged<DomainId>","titles":["Data Model Schema"]},"437":{"title":"MetadataChanged<TriggerId>","titles":["Data Model Schema"]},"438":{"title":"MetadataError","titles":["Data Model Schema"]},"439":{"title":"MetadataValueBox","titles":["Data Model Schema"]},"440":{"title":"Mint<Numeric, Asset>","titles":["Data Model Schema"]},"441":{"title":"Mint<PublicKey, Account>","titles":["Data Model Schema"]},"442":{"title":"Mint<SignatureCheckCondition, Account>","titles":["Data Model Schema"]},"443":{"title":"Mint<u32, Trigger>","titles":["Data Model Schema"]},"444":{"title":"MintBox","titles":["Data Model Schema"]},"445":{"title":"MintabilityError","titles":["Data Model Schema"]},"446":{"title":"Mintable","titles":["Data Model Schema"]},"447":{"title":"Mismatch<AssetValueType>","titles":["Data Model Schema"]},"448":{"title":"Name","titles":["Data Model Schema"]},"449":{"title":"NewAccount","titles":["Data Model Schema"]},"450":{"title":"NewAssetDefinition","titles":["Data Model Schema"]},"451":{"title":"NewDomain","titles":["Data Model Schema"]},"452":{"title":"NewParameter","titles":["Data Model Schema"]},"453":{"title":"NewRole","titles":["Data Model Schema"]},"454":{"title":"NonTrivial<GenericPredicateBox<QueryOutputPredicate>>","titles":["Data Model Schema"]},"455":{"title":"NonZero<u32>","titles":["Data Model Schema"]},"456":{"title":"NonZero<u64>","titles":["Data Model Schema"]},"457":{"title":"Numeric","titles":["Data Model Schema"]},"458":{"title":"NumericSpec","titles":["Data Model Schema"]},"459":{"title":"Option<AccountId>","titles":["Data Model Schema"]},"460":{"title":"Option<AssetDefinitionId>","titles":["Data Model Schema"]},"461":{"title":"Option<AssetId>","titles":["Data Model Schema"]},"462":{"title":"Option<BlockStatus>","titles":["Data Model Schema"]},"463":{"title":"Option<DomainId>","titles":["Data Model Schema"]},"464":{"title":"Option<Duration>","titles":["Data Model Schema"]},"465":{"title":"Option<HashOf<MerkleTree<SignedTransaction>>>","titles":["Data Model Schema"]},"466":{"title":"Option<HashOf<SignedBlock>>","titles":["Data Model Schema"]},"467":{"title":"Option<HashOf<SignedTransaction>>","titles":["Data Model Schema"]},"468":{"title":"Option<IpfsPath>","titles":["Data Model Schema"]},"469":{"title":"Option<NonZero<u32>>","titles":["Data Model Schema"]},"470":{"title":"Option<NonZero<u64>>","titles":["Data Model Schema"]},"471":{"title":"Option<Option<u64>>","titles":["Data Model Schema"]},"472":{"title":"Option<ParameterId>","titles":["Data Model Schema"]},"473":{"title":"Option<PeerId>","titles":["Data Model Schema"]},"474":{"title":"Option<RoleId>","titles":["Data Model Schema"]},"475":{"title":"Option<String>","titles":["Data Model Schema"]},"476":{"title":"Option<TimeInterval>","titles":["Data Model Schema"]},"477":{"title":"Option<TransactionRejectionReason>","titles":["Data Model Schema"]},"478":{"title":"Option<TransactionStatus>","titles":["Data Model Schema"]},"479":{"title":"Option<TriggerCompletedOutcomeType>","titles":["Data Model Schema"]},"480":{"title":"Option<TriggerId>","titles":["Data Model Schema"]},"481":{"title":"Option<u32>","titles":["Data Model Schema"]},"482":{"title":"Option<u64>","titles":["Data Model Schema"]},"483":{"title":"Parameter","titles":["Data Model Schema"]},"484":{"title":"ParameterId","titles":["Data Model Schema"]},"485":{"title":"ParameterValueBox","titles":["Data Model Schema"]},"486":{"title":"Peer","titles":["Data Model Schema"]},"487":{"title":"PeerEvent","titles":["Data Model Schema"]},"488":{"title":"PeerEventFilter","titles":["Data Model Schema"]},"489":{"title":"PeerEventSet","titles":["Data Model Schema"]},"490":{"title":"PeerId","titles":["Data Model Schema"]},"491":{"title":"PermissionToken","titles":["Data Model Schema"]},"492":{"title":"PermissionTokenSchema","titles":["Data Model Schema"]},"493":{"title":"PermissionTokenSchemaUpdateEvent","titles":["Data Model Schema"]},"494":{"title":"PipelineEventBox","titles":["Data Model Schema"]},"495":{"title":"PipelineEventFilterBox","titles":["Data Model Schema"]},"496":{"title":"PublicKey","titles":["Data Model Schema"]},"497":{"title":"QueryBox","titles":["Data Model Schema"]},"498":{"title":"QueryExecutionFail","titles":["Data Model Schema"]},"499":{"title":"QueryOutputBox","titles":["Data Model Schema"]},"500":{"title":"QueryOutputPredicate","titles":["Data Model Schema"]},"501":{"title":"QueryPayload","titles":["Data Model Schema"]},"502":{"title":"Register<Account>","titles":["Data Model Schema"]},"503":{"title":"Register<Asset>","titles":["Data Model Schema"]},"504":{"title":"Register<AssetDefinition>","titles":["Data Model Schema"]},"505":{"title":"Register<Domain>","titles":["Data Model Schema"]},"506":{"title":"Register<Peer>","titles":["Data Model Schema"]},"507":{"title":"Register<Role>","titles":["Data Model Schema"]},"508":{"title":"Register<Trigger>","titles":["Data Model Schema"]},"509":{"title":"RegisterBox","titles":["Data Model Schema"]},"510":{"title":"RemoveKeyValue<Account>","titles":["Data Model Schema"]},"511":{"title":"RemoveKeyValue<Asset>","titles":["Data Model Schema"]},"512":{"title":"RemoveKeyValue<AssetDefinition>","titles":["Data Model Schema"]},"513":{"title":"RemoveKeyValue<Domain>","titles":["Data Model Schema"]},"514":{"title":"RemoveKeyValue<Trigger>","titles":["Data Model Schema"]},"515":{"title":"RemoveKeyValueBox","titles":["Data Model Schema"]},"516":{"title":"Repeats","titles":["Data Model Schema"]},"517":{"title":"RepetitionError","titles":["Data Model Schema"]},"518":{"title":"Revoke<PermissionToken, Account>","titles":["Data Model Schema"]},"519":{"title":"Revoke<PermissionToken, Role>","titles":["Data Model Schema"]},"520":{"title":"Revoke<RoleId, Account>","titles":["Data Model Schema"]},"521":{"title":"RevokeBox","titles":["Data Model Schema"]},"522":{"title":"Role","titles":["Data Model Schema"]},"523":{"title":"RoleEvent","titles":["Data Model Schema"]},"524":{"title":"RoleEventFilter","titles":["Data Model Schema"]},"525":{"title":"RoleEventSet","titles":["Data Model Schema"]},"526":{"title":"RoleId","titles":["Data Model Schema"]},"527":{"title":"RolePermissionChanged","titles":["Data Model Schema"]},"528":{"title":"Schedule","titles":["Data Model Schema"]},"529":{"title":"SemiInterval<Numeric>","titles":["Data Model Schema"]},"530":{"title":"SemiInterval<u128>","titles":["Data Model Schema"]},"531":{"title":"SemiRange","titles":["Data Model Schema"]},"532":{"title":"SetKeyValue<Account>","titles":["Data Model Schema"]},"533":{"title":"SetKeyValue<Asset>","titles":["Data Model Schema"]},"534":{"title":"SetKeyValue<AssetDefinition>","titles":["Data Model Schema"]},"535":{"title":"SetKeyValue<Domain>","titles":["Data Model Schema"]},"536":{"title":"SetKeyValue<Trigger>","titles":["Data Model Schema"]},"537":{"title":"SetKeyValueBox","titles":["Data Model Schema"]},"538":{"title":"SetParameter","titles":["Data Model Schema"]},"539":{"title":"Signature","titles":["Data Model Schema"]},"540":{"title":"SignatureCheckCondition","titles":["Data Model Schema"]},"541":{"title":"SignatureOf<BlockPayload>","titles":["Data Model Schema"]},"542":{"title":"SignatureOf<QueryPayload>","titles":["Data Model Schema"]},"543":{"title":"SignatureOf<TransactionPayload>","titles":["Data Model Schema"]},"544":{"title":"SignaturesOf<BlockPayload>","titles":["Data Model Schema"]},"545":{"title":"SignaturesOf<TransactionPayload>","titles":["Data Model Schema"]},"546":{"title":"SignedBlock","titles":["Data Model Schema"]},"547":{"title":"SignedBlockV1","titles":["Data Model Schema"]},"548":{"title":"SignedQuery","titles":["Data Model Schema"]},"549":{"title":"SignedQueryV1","titles":["Data Model Schema"]},"550":{"title":"SignedTransaction","titles":["Data Model Schema"]},"551":{"title":"SignedTransactionV1","titles":["Data Model Schema"]},"552":{"title":"SizeError","titles":["Data Model Schema"]},"553":{"title":"SocketAddr","titles":["Data Model Schema"]},"554":{"title":"SocketAddrHost","titles":["Data Model Schema"]},"555":{"title":"SocketAddrV4","titles":["Data Model Schema"]},"556":{"title":"SocketAddrV6","titles":["Data Model Schema"]},"557":{"title":"SortedMap<AccountId, Account>","titles":["Data Model Schema"]},"558":{"title":"SortedMap<AssetDefinitionId, AssetDefinition>","titles":["Data Model Schema"]},"559":{"title":"SortedMap<AssetDefinitionId, Numeric>","titles":["Data Model Schema"]},"560":{"title":"SortedMap<AssetId, Asset>","titles":["Data Model Schema"]},"561":{"title":"SortedMap<Name, MetadataValueBox>","titles":["Data Model Schema"]},"562":{"title":"SortedVec<PermissionToken>","titles":["Data Model Schema"]},"563":{"title":"SortedVec<PublicKey>","titles":["Data Model Schema"]},"564":{"title":"SortedVec<SignatureOf<BlockPayload>>","titles":["Data Model Schema"]},"565":{"title":"SortedVec<SignatureOf<TransactionPayload>>","titles":["Data Model Schema"]},"566":{"title":"String","titles":["Data Model Schema"]},"567":{"title":"StringPredicate","titles":["Data Model Schema"]},"568":{"title":"TimeEvent","titles":["Data Model Schema"]},"569":{"title":"TimeEventFilter","titles":["Data Model Schema"]},"570":{"title":"TimeInterval","titles":["Data Model Schema"]},"571":{"title":"TransactionEvent","titles":["Data Model Schema"]},"572":{"title":"TransactionEventFilter","titles":["Data Model Schema"]},"573":{"title":"TransactionLimitError","titles":["Data Model Schema"]},"574":{"title":"TransactionLimits","titles":["Data Model Schema"]},"575":{"title":"TransactionPayload","titles":["Data Model Schema"]},"576":{"title":"TransactionQueryOutput","titles":["Data Model Schema"]},"577":{"title":"TransactionRejectionReason","titles":["Data Model Schema"]},"578":{"title":"TransactionStatus","titles":["Data Model Schema"]},"579":{"title":"TransactionValue","titles":["Data Model Schema"]},"580":{"title":"Transfer<Account, AssetDefinitionId, Account>","titles":["Data Model Schema"]},"581":{"title":"Transfer<Account, DomainId, Account>","titles":["Data Model Schema"]},"582":{"title":"Transfer<Asset, Metadata, Account>","titles":["Data Model Schema"]},"583":{"title":"Transfer<Asset, Numeric, Account>","titles":["Data Model Schema"]},"584":{"title":"TransferBox","titles":["Data Model Schema"]},"585":{"title":"Trigger","titles":["Data Model Schema"]},"586":{"title":"TriggerCompletedEvent","titles":["Data Model Schema"]},"587":{"title":"TriggerCompletedEventFilter","titles":["Data Model Schema"]},"588":{"title":"TriggerCompletedOutcome","titles":["Data Model Schema"]},"589":{"title":"TriggerCompletedOutcomeType","titles":["Data Model Schema"]},"590":{"title":"TriggerEvent","titles":["Data Model Schema"]},"591":{"title":"TriggerEventFilter","titles":["Data Model Schema"]},"592":{"title":"TriggerEventSet","titles":["Data Model Schema"]},"593":{"title":"TriggerId","titles":["Data Model Schema"]},"594":{"title":"TriggerNumberOfExecutionsChanged","titles":["Data Model Schema"]},"595":{"title":"TriggeringEventFilterBox","titles":["Data Model Schema"]},"596":{"title":"TypeError","titles":["Data Model Schema"]},"597":{"title":"Unregister<Account>","titles":["Data Model Schema"]},"598":{"title":"Unregister<Asset>","titles":["Data Model Schema"]},"599":{"title":"Unregister<AssetDefinition>","titles":["Data Model Schema"]},"600":{"title":"Unregister<Domain>","titles":["Data Model Schema"]},"601":{"title":"Unregister<Peer>","titles":["Data Model Schema"]},"602":{"title":"Unregister<Role>","titles":["Data Model Schema"]},"603":{"title":"Unregister<Trigger>","titles":["Data Model Schema"]},"604":{"title":"UnregisterBox","titles":["Data Model Schema"]},"605":{"title":"Upgrade","titles":["Data Model Schema"]},"606":{"title":"ValidationFail","titles":["Data Model Schema"]},"607":{"title":"Vec<EventBox>","titles":["Data Model Schema"]},"608":{"title":"Vec<EventFilterBox>","titles":["Data Model Schema"]},"609":{"title":"Vec<GenericPredicateBox<QueryOutputPredicate>>","titles":["Data Model Schema"]},"610":{"title":"Vec<InstructionBox>","titles":["Data Model Schema"]},"611":{"title":"Vec<MetadataValueBox>","titles":["Data Model Schema"]},"612":{"title":"Vec<Name>","titles":["Data Model Schema"]},"613":{"title":"Vec<PeerId>","titles":["Data Model Schema"]},"614":{"title":"Vec<PublicKey>","titles":["Data Model Schema"]},"615":{"title":"Vec<QueryOutputBox>","titles":["Data Model Schema"]},"616":{"title":"Vec<TransactionValue>","titles":["Data Model Schema"]},"617":{"title":"Vec<u8>","titles":["Data Model Schema"]},"618":{"title":"WasmExecutionFail","titles":["Data Model Schema"]},"619":{"title":"WasmSmartContract","titles":["Data Model Schema"]},"620":{"title":"bool","titles":["Data Model Schema"]},"621":{"title":"u128","titles":["Data Model Schema"]},"622":{"title":"u16","titles":["Data Model Schema"]},"623":{"title":"u32","titles":["Data Model Schema"]},"624":{"title":"u64","titles":["Data Model Schema"]},"625":{"title":"u8","titles":["Data Model Schema"]},"626":{"title":"Glossary","titles":[]},"627":{"title":"Blockchain ledgers","titles":["Glossary"]},"628":{"title":"Peer","titles":["Glossary"]},"629":{"title":"Asset","titles":["Glossary"]},"630":{"title":"Fungible assets","titles":["Glossary","Asset"]},"631":{"title":"Non-fungible assets","titles":["Glossary","Asset"]},"632":{"title":"Mintable assets","titles":["Glossary","Asset"]},"633":{"title":"Non-mintable assets","titles":["Glossary","Asset"]},"634":{"title":"Byzantine fault-tolerance (BFT)","titles":["Glossary"]},"635":{"title":"Iroha Components","titles":["Glossary"]},"636":{"title":"Sumeragi (Emperor)","titles":["Glossary","Iroha Components"]},"637":{"title":"Torii (Gate)","titles":["Glossary","Iroha Components"]},"638":{"title":"Kura (Warehouse)","titles":["Glossary","Iroha Components"]},"639":{"title":"Kagami(Teacher and Exemplar and/or looking glass)","titles":["Glossary","Iroha Components"]},"640":{"title":"Merkle tree (hash tree)","titles":["Glossary","Iroha Components"]},"641":{"title":"Smart contracts","titles":["Glossary","Iroha Components"]},"642":{"title":"Triggers","titles":["Glossary","Iroha Components"]},"643":{"title":"Versioning","titles":["Glossary","Iroha Components"]},"644":{"title":"Hijiri (peer reputation system)","titles":["Glossary","Iroha Components"]},"645":{"title":"Iroha Modules","titles":["Glossary"]},"646":{"title":"Iroha Special Instructions (ISI)","titles":["Glossary"]},"647":{"title":"Utility Iroha Special Instructions","titles":["Glossary","Iroha Special Instructions (ISI)","Hijiri (peer reputation system)"]},"648":{"title":"Core Iroha Special Instructions","titles":["Glossary","Iroha Special Instructions (ISI)"]},"649":{"title":"Domain-specific Iroha Special Instructions","titles":["Glossary","Iroha Special Instructions (ISI)"]},"650":{"title":"Custom Iroha Special Instruction","titles":["Glossary","Iroha Special Instructions (ISI)"]},"651":{"title":"Iroha Query","titles":["Glossary"]},"652":{"title":"View change","titles":["Glossary"]},"653":{"title":"World state view (WSV)","titles":["Glossary"]},"654":{"title":"Leader","titles":["Glossary"]},"655":{"title":"Foreign Function Interfaces (FFI)","titles":[]},"656":{"title":"Why FFI","titles":["Foreign Function Interfaces (FFI)"]},"657":{"title":"Example","titles":["Foreign Function Interfaces (FFI)"]},"658":{"title":"FFI Binding Generation","titles":["Foreign Function Interfaces (FFI)"]},"659":{"title":"Name Mangling","titles":["Foreign Function Interfaces (FFI)","FFI Binding Generation"]},"660":{"title":"Naming Conventions","titles":[]},"661":{"title":"Iroha Special Instructions","titles":[]},"662":{"title":"Permissions","titles":[]},"663":{"title":"Permission Tokens","titles":["Permissions"]},"664":{"title":"General example","titles":["Permissions","Permission Tokens"]},"665":{"title":"Queries","titles":[]},"666":{"title":"Conventions","titles":["Queries"]},"667":{"title":"Role","titles":["Queries"]},"668":{"title":"FindAllRoles","titles":["Queries","Role"]},"669":{"title":"FindAllRoleIds","titles":["Queries","Role"]},"670":{"title":"FindRoleByRoleId","titles":["Queries","Role"]},"671":{"title":"FindRolesByAccountId","titles":["Queries","Role"]},"672":{"title":"Permission","titles":["Queries"]},"673":{"title":"FindAllPermissionTokenDefinitions","titles":["Queries","Permission"]},"674":{"title":"FindPermissionTokensByAccountId","titles":["Queries","Permission"]},"675":{"title":"Account","titles":["Queries"]},"676":{"title":"FindAllAccounts","titles":["Queries","Account"]},"677":{"title":"FindAccountById","titles":["Queries","Account"]},"678":{"title":"FindAccountKeyValueByIdAndKey","titles":["Queries","Account"]},"679":{"title":"FindAccountsByName","titles":["Queries","Account"]},"680":{"title":"FindAccountsByDomainId","titles":["Queries","Account"]},"681":{"title":"FindAccountsWithAsset","titles":["Queries","Account"]},"682":{"title":"Asset","titles":["Queries"]},"683":{"title":"FindAllAssets","titles":["Queries","Asset"]},"684":{"title":"FindAllAssetDefinitions","titles":["Queries","Asset"]},"685":{"title":"FindAssetById","titles":["Queries","Asset"]},"686":{"title":"FindAssetsByName","titles":["Queries","Asset"]},"687":{"title":"FindAssetsByAccountId","titles":["Queries","Asset"]},"688":{"title":"FindAssetsByAssetDefinitionId","titles":["Queries","Asset"]},"689":{"title":"FindAssetsByDomainId","titles":["Queries","Asset"]},"690":{"title":"FindAssetsByDomainIdAndAssetDefinitionId","titles":["Queries","Asset"]},"691":{"title":"FindAssetQuantityById","titles":["Queries","Asset"]},"692":{"title":"FindAssetKeyValueByIdAndKey","titles":["Queries","Asset"]},"693":{"title":"FindAssetDefinitionKeyValueByIdAndKey","titles":["Queries","Asset"]},"694":{"title":"FindTotalAssetQuantityByAssetDefinitionId","titles":["Queries","Asset"]},"695":{"title":"Block","titles":["Queries"]},"696":{"title":"FindAllBlocks","titles":["Queries","Block"]},"697":{"title":"FindAllBlockHeaders","titles":["Queries","Block"]},"698":{"title":"FindBlockHeaderByHash","titles":["Queries","Block"]},"699":{"title":"Domain","titles":["Queries"]},"700":{"title":"FindAllDomains","titles":["Queries","Domain"]},"701":{"title":"FindDomainById","titles":["Queries","Domain"]},"702":{"title":"FindDomainKeyValueByIdAndKey","titles":["Queries","Domain"]},"703":{"title":"Peer","titles":["Queries"]},"704":{"title":"FindAllPeers","titles":["Queries","Peer"]},"705":{"title":"FindAllParameters","titles":["Queries","Peer"]},"706":{"title":"Transaction","titles":["Queries"]},"707":{"title":"FindTransactionsByAccountId","titles":["Queries","Transaction"]},"708":{"title":"FindTransactionByHash","titles":["Queries","Transaction"]},"709":{"title":"Trigger","titles":["Queries"]},"710":{"title":"FindAllActiveTriggerIds","titles":["Queries","Trigger"]},"711":{"title":"FindTriggerById","titles":["Queries","Trigger"]},"712":{"title":"FindTriggerKeyValueByIdAndKey","titles":["Queries","Trigger"]},"713":{"title":"FindTriggersByDomainId","titles":["Queries","Trigger"]},"714":{"title":"Torii Endpoints","titles":[]},"715":{"title":"API Version","titles":["Torii Endpoints"]},"716":{"title":"Requests","titles":["Torii Endpoints","API Version",null]},"717":{"title":"Responses","titles":["Torii Endpoints","API Version",null]},"718":{"title":"Blocks Stream","titles":["Torii Endpoints"]},"719":{"title":"Handshake","titles":["Torii Endpoints","Blocks Stream",null]},"720":{"title":"Data Exchange","titles":["Torii Endpoints","Blocks Stream",null]},"721":{"title":"Configuration / Retrieve","titles":["Torii Endpoints"]},"722":{"title":"Requests","titles":["Torii Endpoints","Configuration / Retrieve",null]},"723":{"title":"Responses","titles":["Torii Endpoints","Configuration / Retrieve",null]},"724":{"title":"Configuration / Update","titles":["Torii Endpoints"]},"725":{"title":"Requests","titles":["Torii Endpoints","Configuration / Update",null]},"726":{"title":"Responses","titles":["Torii Endpoints","Configuration / Update",null]},"727":{"title":"Events","titles":["Torii Endpoints"]},"728":{"title":"Transaction Events","titles":["Torii Endpoints","Events"]},"729":{"title":"Handshake","titles":["Torii Endpoints","Events","Transaction Events"]},"730":{"title":"Data Exchange","titles":["Torii Endpoints","Events","Transaction Events"]},"731":{"title":"Health","titles":["Torii Endpoints"]},"732":{"title":"Requests","titles":["Torii Endpoints","Health","Transaction Events"]},"733":{"title":"Responses","titles":["Torii Endpoints","Health","Transaction Events"]},"734":{"title":"Metrics","titles":["Torii Endpoints"]},"735":{"title":"Responses","titles":["Torii Endpoints","Metrics","Transaction Events"]},"736":{"title":"Pending Transactions","titles":["Torii Endpoints"]},"737":{"title":"Requests","titles":["Torii Endpoints","Pending Transactions","Transaction Events"]},"738":{"title":"Responses","titles":["Torii Endpoints","Pending Transactions","Transaction Events"]},"739":{"title":"Query","titles":["Torii Endpoints"]},"740":{"title":"Requests","titles":["Torii Endpoints","Query","Transaction Events"]},"741":{"title":"Responses","titles":["Torii Endpoints","Query","Transaction Events"]},"742":{"title":"Account Not Found 404","titles":["Torii Endpoints","Query"]},"743":{"title":"Asset Not Found 404","titles":["Torii Endpoints","Query"]},"744":{"title":"Schema","titles":["Torii Endpoints"]},"745":{"title":"Requests","titles":["Torii Endpoints","Schema","Asset Not Found 404"]},"746":{"title":"Responses","titles":["Torii Endpoints","Schema","Asset Not Found 404"]},"747":{"title":"Status","titles":["Torii Endpoints"]},"748":{"title":"Requests","titles":["Torii Endpoints","Status","Asset Not Found 404"]},"749":{"title":"Responses","titles":["Torii Endpoints","Status","Asset Not Found 404"]},"750":{"title":"Sub-routing","titles":["Torii Endpoints","Status"]},"751":{"title":"Transaction","titles":["Torii Endpoints"]},"752":{"title":"Requests","titles":["Torii Endpoints","Transaction","Sub-routing"]},"753":{"title":"Responses","titles":["Torii Endpoints","Transaction","Sub-routing"]}},"dirtCount":0,"index":[["鳥居",{"2":{"714":1}}],["߀",{"2":{"249":1}}],["ዐ",{"2":{"249":1}}],["о",{"2":{"249":1}}],["θ",{"2":{"249":1}}],["qtwebengine",{"2":{"249":2}}],["qt",{"2":{"249":2}}],["qutebrowser",{"2":{"249":1}}],["quit",{"2":{"215":1}}],["quite",{"2":{"125":1,"191":1,"206":1,"223":1,"656":1}}],["quickly",{"2":{"197":1,"258":1,"270":1}}],["quick",{"2":{"88":1,"231":1,"286":1}}],["quantities",{"2":{"137":1,"342":1,"694":1}}],["quantity=33",{"2":{"205":1}}],["quantity=",{"2":{"204":1,"206":1}}],["quantity>",{"2":{"190":1}}],["quantity",{"2":{"24":1,"25":1,"40":1,"178":1,"180":1,"189":2,"190":1,"193":2,"214":2,"221":2,"223":1,"663":5,"691":2,"694":1}}],["quadratically",{"2":{"82":1}}],["questions",{"2":{"270":1}}],["question",{"2":{"219":1,"268":1}}],["queried",{"2":{"64":1,"741":1}}],["queries",{"0":{"54":1,"64":1,"65":1,"99":1,"665":1},"1":{"66":1,"67":1,"68":1,"69":1,"70":1,"666":1,"667":1,"668":1,"669":1,"670":1,"671":1,"672":1,"673":1,"674":1,"675":1,"676":1,"677":1,"678":1,"679":1,"680":1,"681":1,"682":1,"683":1,"684":1,"685":1,"686":1,"687":1,"688":1,"689":1,"690":1,"691":1,"692":1,"693":1,"694":1,"695":1,"696":1,"697":1,"698":1,"699":1,"700":1,"701":1,"702":1,"703":1,"704":1,"705":1,"706":1,"707":1,"708":1,"709":1,"710":1,"711":1,"712":1,"713":1},"2":{"36":1,"39":4,"54":1,"62":1,"64":2,"65":3,"67":1,"69":1,"70":1,"97":1,"99":2,"104":1,"137":5,"167":1,"175":4,"181":1,"192":1,"224":1,"637":1,"651":1,"665":2,"666":4,"675":2,"699":1,"714":1}}],["queryfailed",{"2":{"606":1}}],["queryfilter",{"2":{"187":2,"188":2,"189":2}}],["querypayload",{"0":{"501":1,"542":1},"2":{"549":2}}],["queryexecutionfail",{"0":{"498":1},"2":{"418":1,"606":1,"741":7}}],["queryoutputbox",{"0":{"319":1,"320":1,"499":1,"615":1},"2":{"319":1,"320":1,"499":1,"615":1,"741":1}}],["queryoutputpredicate",{"0":{"405":1,"454":1,"500":1,"609":1},"2":{"318":1,"339":2,"405":4,"454":1,"501":1,"609":1}}],["queryandextractor",{"2":{"193":6}}],["querybuilder",{"2":{"187":2,"188":1,"189":1,"190":1,"193":6}}],["querybox",{"0":{"497":1},"2":{"66":3,"104":1,"176":2,"180":4,"501":1}}],["querying",{"0":{"180":1,"187":1},"2":{"161":1,"187":1,"678":1}}],["query",{"0":{"66":1,"651":1,"739":1},"1":{"740":1,"741":1,"742":1,"743":1},"2":{"62":1,"66":5,"67":3,"68":1,"69":2,"83":1,"104":2,"143":1,"172":1,"174":1,"175":3,"176":2,"187":5,"188":2,"189":2,"190":5,"191":1,"193":8,"200":1,"204":1,"221":1,"404":1,"418":1,"501":1,"626":1,"666":6,"684":1,"691":2,"700":2,"706":1,"710":1,"739":1,"740":3,"741":7}}],["queued",{"2":{"578":1}}],["queue",{"2":{"28":3,"143":2,"215":1,"749":3,"750":1}}],["queen",{"2":{"24":1,"86":1}}],["quot",{"2":{"0":2,"3":2,"6":2,"12":2,"45":2,"67":2,"88":2,"150":4,"153":4,"154":2,"163":2,"175":4,"214":2,"221":2,"283":4,"287":6}}],["✔",{"2":{"196":14}}],["937000000",{"2":{"749":1,"750":2}}],["96^",{"2":{"252":1}}],["96",{"2":{"252":2,"253":1}}],["99d30f9dd159a397a76e4a37143433bd302264f7509b6e154ca9c18263543857",{"2":{"207":2}}],["90",{"2":{"190":1,"191":1}}],["9ac47abf59b356e0bd7dcbbbb4dec080e302156a48ca907e47cb6aea1d32719e",{"2":{"187":1}}],["9ac47abf59b356e0bd7dcbbbb4dec080e302156a48ca907e47cb6aea1d32719e7233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0",{"2":{"20":1,"181":1,"218":1}}],["9",{"0":{"183":1,"193":1,"207":1},"2":{"196":2,"290":1,"341":1,"393":1,"415":1,"416":1,"418":1,"420":1,"497":1,"499":1}}],["╰───┴──────────────────────────────╯",{"2":{"181":1}}],["╰───┴───────────────────┴──────╯",{"2":{"174":1}}],["├───┼──────────────────────────────┤",{"2":{"181":1}}],["├───┼───────────────────┼──────┤",{"2":{"174":1}}],["╭───┬──────────────────────────────╮",{"2":{"181":1}}],["╭───┬───────────────────┬──────╮",{"2":{"174":1}}],["│",{"2":{"174":28,"181":27}}],["^5",{"2":{"173":1}}],["^^^^^^^^^^^^^^^^^^^",{"2":{"5":1}}],["zsh",{"2":{"244":1}}],["zshrc",{"2":{"16":1,"143":1,"244":3}}],["zero",{"2":{"84":1,"368":1,"369":1,"370":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"378":1,"379":1,"394":1}}],["z",{"2":{"67":2,"89":1,"105":2,"108":2,"666":2}}],["−1",{"2":{"43":1}}],[">>",{"2":{"244":2}}],[">new",{"2":{"181":1}}],[">",{"2":{"53":2,"114":1,"130":1,"144":1,"174":1,"181":15,"187":1,"188":1,"189":1,"190":2,"193":3,"657":1,"659":2,"714":2}}],[">asset",{"2":{"29":1}}],[">signatories|",{"2":{"29":1}}],["|world|",{"2":{"29":1}}],["||",{"2":{"29":1}}],["||account",{"2":{"29":1}}],["||asset",{"2":{"29":1}}],["||definition",{"2":{"29":1}}],["|domain",{"2":{"29":1}}],["|",{"2":{"29":44,"181":1,"196":19}}],["↩︎",{"2":{"28":1,"99":2,"110":3,"141":1,"183":1}}],["£1",{"2":{"24":4}}],["+inf",{"2":{"735":1}}],["+nightly",{"2":{"108":1}}],["+",{"2":{"20":2,"29":29,"180":4,"186":1,"196":2}}],["887",{"2":{"253":3}}],["835",{"2":{"253":3}}],["83",{"2":{"253":1}}],["834",{"2":{"253":2}}],["896",{"2":{"252":1}}],["899",{"2":{"252":1}}],["874",{"2":{"252":1}}],["86e58c28036c",{"2":{"196":1}}],["802620cbd3d701b561fe98463767729176404dc757d690f78980b8fdd40c171ccb8eb5",{"2":{"202":1,"203":1}}],["80",{"2":{"191":1,"235":1}}],["808x",{"2":{"18":1}}],["8083",{"2":{"18":3}}],["8082",{"2":{"18":3}}],["8081",{"2":{"18":3,"175":3,"181":1}}],["8080",{"2":{"18":3,"20":1,"119":1,"148":1,"175":4,"181":1,"187":1,"196":1}}],["818x",{"2":{"18":1}}],["8183",{"2":{"18":3}}],["8182",{"2":{"18":3}}],["8181",{"2":{"18":3}}],["8180",{"2":{"12":1,"18":3,"20":1,"120":3,"150":3,"187":1}}],["8",{"0":{"181":1,"192":1,"206":1,"224":1,"299":1},"1":{"182":1},"2":{"18":1,"253":1,"273":1,"290":1,"299":1,"341":1,"393":1,"414":1,"415":1,"416":1,"418":1,"420":1,"424":1,"497":1,"499":1,"660":1,"735":1}}],["yield",{"2":{"273":1}}],["yields",{"2":{"252":1}}],["yubikey",{"2":{"250":1,"268":5}}],["yac",{"2":{"230":2}}],["yarn",{"2":{"174":2}}],["yamlversion",{"2":{"18":1}}],["yaml",{"2":{"18":1,"174":1}}],["year",{"2":{"253":2}}],["years",{"2":{"238":1,"253":2}}],["yes",{"2":{"103":1,"253":1}}],["yet",{"2":{"88":1,"103":1,"212":1,"753":1}}],["yellow",{"2":{"52":1}}],["y",{"2":{"39":1,"89":1,"666":5,"742":1,"743":5}}],["yml",{"2":{"18":2,"21":1,"143":1,"196":2,"197":2,"217":1,"272":1}}],["you",{"2":{"6":6,"10":1,"12":1,"13":3,"14":4,"16":14,"17":2,"18":9,"19":1,"20":2,"21":3,"22":4,"24":2,"27":1,"28":2,"29":2,"36":6,"39":3,"40":2,"41":8,"42":5,"43":2,"44":1,"47":1,"52":2,"54":1,"58":1,"62":1,"65":1,"67":3,"68":2,"69":3,"72":3,"78":5,"79":1,"80":1,"83":3,"84":2,"85":1,"88":9,"89":3,"90":6,"97":4,"98":1,"99":1,"101":10,"103":2,"104":1,"105":3,"106":3,"108":1,"109":2,"110":1,"114":1,"116":2,"118":1,"119":1,"120":5,"121":1,"123":1,"124":1,"125":1,"128":5,"129":2,"130":1,"131":1,"132":1,"134":2,"135":4,"136":3,"137":14,"138":2,"141":6,"143":4,"144":1,"146":4,"148":2,"150":4,"151":4,"153":3,"154":6,"155":1,"156":2,"160":1,"161":2,"162":1,"163":2,"164":1,"165":1,"166":5,"167":1,"168":1,"169":1,"170":2,"171":3,"172":2,"173":1,"174":16,"175":10,"176":3,"177":8,"178":2,"179":1,"181":4,"183":1,"185":7,"186":3,"187":1,"188":1,"196":3,"198":2,"200":4,"201":1,"202":5,"204":4,"205":1,"207":2,"208":2,"210":4,"211":5,"212":2,"213":8,"214":3,"215":1,"217":12,"218":5,"219":3,"220":8,"221":6,"222":8,"223":1,"224":1,"225":1,"226":4,"227":2,"232":1,"233":2,"234":1,"237":1,"238":3,"242":1,"244":2,"245":1,"246":1,"248":1,"249":6,"250":2,"252":1,"253":3,"254":1,"256":4,"258":3,"259":2,"261":3,"263":4,"265":3,"268":1,"269":1,"270":4,"271":2,"272":11,"273":6,"274":1,"277":1,"278":1,"279":5,"280":5,"281":2,"282":7,"283":4,"284":1,"285":2,"286":2,"626":1,"656":6,"658":2,"660":2,"663":1,"665":2,"666":3,"667":1,"672":1,"679":1,"683":3,"684":2}}],["yourself",{"2":{"177":1,"202":1,"213":1,"217":1,"219":1,"220":1}}],["your",{"2":{"6":2,"10":3,"16":5,"17":1,"18":1,"22":4,"42":1,"65":1,"79":1,"82":1,"84":1,"88":7,"89":2,"100":1,"101":1,"103":1,"106":2,"109":2,"110":1,"128":1,"132":2,"135":2,"136":1,"137":4,"138":1,"141":2,"143":2,"154":1,"157":1,"161":1,"162":1,"169":1,"174":1,"185":3,"187":1,"188":1,"189":2,"196":3,"203":3,"205":1,"210":1,"214":1,"215":1,"217":3,"218":3,"219":1,"225":1,"230":1,"237":1,"238":1,"242":1,"244":2,"245":1,"246":3,"247":2,"248":8,"249":9,"250":4,"251":1,"252":3,"253":2,"254":2,"255":2,"258":4,"259":1,"260":1,"261":4,"262":2,"263":10,"264":2,"265":2,"268":3,"270":1,"272":1,"278":1,"279":1,"280":1,"282":3,"283":4,"656":2,"658":1}}],["3rd",{"2":{"650":1}}],["38",{"2":{"497":1}}],["37",{"2":{"497":1,"749":1}}],["36",{"2":{"497":1}}],["35",{"2":{"497":1}}],["35940",{"2":{"252":1}}],["31",{"2":{"253":1,"497":1,"749":1,"750":1}}],["30",{"2":{"497":1}}],["300∗109300",{"2":{"253":1}}],["300",{"2":{"253":1}}],["30s",{"2":{"143":1}}],["33",{"2":{"230":1,"497":1,"634":1}}],["332824z",{"2":{"196":1}}],["34",{"2":{"221":2,"497":1}}],["349409z",{"2":{"196":1}}],["39",{"2":{"196":11,"497":1}}],["392",{"2":{"12":1,"725":1}}],["3s",{"2":{"196":5}}],["32",{"0":{"300":1},"2":{"25":1,"84":1,"101":1,"214":1,"273":1,"300":1,"410":1,"497":1}}],["3bac34cda9e3763fa069c1198312d1ec73b53023b8180c822ac355435edc4a24cc25624d62896d3a0bfd8940f928dc2abf27cc57cefeb442aa96d9081aae58a1",{"2":{"18":1}}],["3",{"0":{"94":1,"136":1,"162":1,"172":1,"176":1,"187":1,"201":1,"209":1,"212":1,"219":1,"243":1},"1":{"210":1,"211":1,"212":1,"213":1,"214":1,"215":1,"244":1},"2":{"18":1,"108":1,"174":1,"180":2,"181":3,"185":2,"290":1,"298":1,"305":1,"311":1,"327":1,"340":1,"341":1,"343":1,"349":1,"350":1,"393":1,"405":1,"414":1,"415":1,"416":1,"418":1,"420":1,"427":1,"430":1,"438":1,"439":1,"485":1,"497":1,"498":1,"499":1,"500":1,"509":1,"515":1,"523":1,"537":1,"567":1,"577":1,"578":1,"590":1,"595":1,"604":1,"606":1,"749":1,"750":1}}],["3f+1",{"2":{"18":1,"146":1}}],["662",{"2":{"253":3}}],["65",{"2":{"185":1}}],["65536",{"2":{"143":2}}],["602",{"2":{"252":1}}],["608",{"2":{"252":1,"253":3}}],["60",{"2":{"170":1,"279":2}}],["60s",{"2":{"143":1}}],["6",{"0":{"179":1,"190":1,"204":1,"215":1,"222":1},"2":{"16":1,"181":1,"185":3,"196":4,"253":1,"290":1,"305":1,"340":1,"341":1,"343":1,"393":1,"414":1,"415":1,"416":1,"418":1,"420":1,"430":1,"439":1,"497":1,"499":1,"509":1,"604":1}}],["647",{"2":{"252":1}}],["64",{"2":{"6":3,"25":1,"252":1,"273":1,"749":1}}],["~",{"2":{"16":8,"17":4,"22":1,"171":2,"196":1,"210":2,"217":6,"243":1,"244":5,"280":1,"282":2}}],["57",{"2":{"279":2}}],["5c",{"2":{"268":4}}],["54572974",{"2":{"735":1}}],["549",{"2":{"253":3}}],["540",{"2":{"253":3}}],["52∗103052",{"2":{"252":1}}],["52",{"2":{"196":4,"252":2}}],["51",{"2":{"196":15}}],["5s",{"2":{"196":3}}],["500",{"2":{"143":1}}],["56",{"2":{"88":2}}],["59",{"2":{"88":1}}],["55",{"2":{"88":2}}],["5",{"0":{"96":1,"178":1,"189":1,"203":1,"214":1,"221":1},"2":{"12":1,"174":1,"180":1,"181":1,"193":2,"196":2,"290":1,"305":1,"311":1,"340":1,"341":1,"343":1,"393":1,"414":1,"415":1,"416":1,"418":1,"420":1,"430":1,"439":1,"497":1,"499":1,"500":1,"509":1,"590":1,"604":1,"735":3,"749":2,"750":3}}],["7c",{"2":{"749":2}}],["7737e0b5c",{"2":{"279":1}}],["776",{"2":{"252":1}}],["742",{"2":{"252":1}}],["7687b1433fb6731e6dc635a376b3eb3b5fcd1e02c9775c1642e7fd5da035ec75",{"2":{"239":1}}],["7f2091d887bf9dbf6100dfea696b06ae269c288ae55f1d281d9fddad93d1b8f1",{"2":{"207":3}}],["7233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0",{"2":{"187":1}}],["7",{"0":{"180":1,"191":1,"205":1,"223":1},"2":{"12":1,"18":1,"146":1,"181":1,"290":1,"341":1,"393":1,"414":1,"415":1,"416":1,"418":1,"420":1,"497":1,"499":1}}],["08",{"2":{"749":1}}],["085585z",{"2":{"196":1}}],["085522z",{"2":{"196":1}}],["0c",{"2":{"749":1}}],["025",{"2":{"735":1}}],["0x80",{"2":{"292":1}}],["0x8",{"2":{"292":1,"307":1,"313":1,"345":1,"525":1,"592":1}}],["0x400",{"2":{"292":1}}],["0x40",{"2":{"292":1,"307":1,"345":1}}],["0x4",{"2":{"292":1,"307":1,"313":1,"338":1,"345":1,"525":1,"592":1}}],["0x200",{"2":{"292":1}}],["0x20",{"2":{"292":1,"307":1,"313":1,"345":1,"592":1}}],["0x2",{"2":{"292":1,"307":1,"313":1,"338":1,"345":1,"489":1,"525":1,"592":1}}],["0x100",{"2":{"292":1}}],["0x10",{"2":{"292":1,"307":1,"313":1,"345":1,"592":1}}],["0x1",{"2":{"292":1,"307":1,"313":1,"338":1,"345":1,"361":1,"489":1,"525":1,"592":1}}],["04",{"2":{"279":2}}],["040",{"2":{"252":1}}],["01",{"2":{"279":1,"735":1}}],["015",{"2":{"252":1}}],["06",{"2":{"221":1}}],["07",{"2":{"196":19}}],["0d3b3367a826",{"2":{"196":1}}],["0s",{"2":{"196":1}}],["0n",{"2":{"183":1}}],["037",{"2":{"252":1}}],["03",{"2":{"88":3,"279":1}}],["038ae16b219da35aa036335ed0a43c28a2cc737150112c78a7b8034b9d99c9023f4e3e98571b55514edc5ccf7e53ca7509d89b2868e62921180a6f57c2f4e255",{"2":{"18":1}}],["059",{"2":{"252":1}}],["05",{"2":{"88":2,"735":1}}],["005",{"2":{"735":1}}],["00",{"2":{"88":2}}],["00031",{"2":{"253":2}}],["0000000000000000000000000000000035d9120a174e35e966dd92de90b2446d4b060c8b72018b3917a1c97d7e93eaec",{"2":{"239":1}}],["000000000000",{"2":{"196":1}}],["0000",{"2":{"196":3}}],["000",{"2":{"53":1,"61":1,"71":1,"253":1}}],["0−1",{"2":{"43":1}}],["0",{"2":{"12":2,"18":4,"20":8,"21":2,"43":2,"53":1,"84":1,"92":4,"103":2,"119":2,"120":6,"150":6,"170":1,"173":3,"174":1,"175":14,"181":6,"185":6,"186":1,"187":4,"190":1,"196":55,"217":10,"249":1,"279":2,"290":1,"294":1,"298":1,"305":1,"311":1,"315":1,"316":1,"317":1,"326":1,"327":1,"332":1,"336":1,"339":1,"340":1,"341":1,"343":1,"349":1,"350":1,"353":1,"357":1,"359":1,"393":1,"405":1,"409":1,"414":1,"415":1,"416":1,"417":1,"418":1,"420":1,"421":1,"427":1,"430":1,"438":1,"439":1,"444":1,"445":1,"446":1,"485":1,"487":1,"494":1,"495":1,"497":1,"498":1,"499":1,"500":1,"509":1,"515":1,"516":1,"521":1,"523":1,"531":1,"537":1,"540":1,"553":1,"567":1,"577":1,"578":1,"584":1,"588":1,"589":1,"590":1,"595":1,"596":1,"604":1,"606":1,"657":1,"660":1,"735":21}}],["29",{"2":{"497":1}}],["292",{"2":{"252":1}}],["28",{"2":{"497":1}}],["282ed9f3cf92811c3818dbc4ae594ed59dc1a2f78e4241e31924e101d6b1fb831c61faf8fe94e253b93114240394f79a607b7fa55f9e5a41ebec74b88055768b",{"2":{"18":1}}],["23",{"2":{"497":1}}],["238596z",{"2":{"196":1}}],["22",{"2":{"497":1}}],["25",{"2":{"269":1,"497":1,"735":1}}],["2fa",{"2":{"259":2}}],["27",{"2":{"497":1}}],["270",{"2":{"253":3}}],["276634z",{"2":{"196":1}}],["249",{"2":{"253":3}}],["24",{"2":{"253":1,"497":1}}],["248",{"2":{"252":1}}],["269",{"2":{"252":1}}],["26^",{"2":{"252":1}}],["26",{"2":{"252":2,"253":1,"497":1,"735":1}}],["2669bb1099477b970e1d7d7c54e345a64a54213fcfba2465cbcd6d4e5091a71db678073cfae6e247a58b442661c7da0e13bac5031cbc6343ef566b8718d47d04",{"2":{"239":5}}],["266902z",{"2":{"196":1}}],["215234z",{"2":{"196":1}}],["214759z",{"2":{"196":1}}],["210006z",{"2":{"196":1}}],["21",{"2":{"196":1,"497":1}}],["216499",{"2":{"12":1}}],["20",{"2":{"497":1}}],["200∗103200",{"2":{"253":1}}],["200",{"2":{"253":1,"717":1,"723":1,"733":1,"735":2,"738":1,"741":2,"746":1,"749":1,"753":1}}],["2080",{"2":{"253":1}}],["20703",{"2":{"252":1}}],["209730z",{"2":{"196":1}}],["2048",{"2":{"239":1}}],["204729z",{"2":{"196":1}}],["204411z",{"2":{"196":1}}],["202",{"2":{"726":1}}],["2022",{"2":{"279":2}}],["2024",{"2":{"196":19}}],["2021",{"2":{"103":1}}],["2",{"0":{"93":1,"104":1,"135":1,"161":1,"165":1,"169":1,"171":1,"175":1,"185":1,"186":2,"194":1,"196":1,"198":1,"200":1,"210":1,"211":2,"217":1,"218":2,"229":1,"242":1},"1":{"166":1,"167":1,"168":1,"170":1,"171":1,"172":2,"195":1,"196":1,"197":2,"199":1,"200":1,"201":1,"202":1,"203":1,"204":1,"205":1,"206":1,"207":1,"208":1,"230":1,"231":1,"232":1,"233":1,"234":1,"235":1},"2":{"12":1,"13":1,"16":1,"17":1,"19":1,"28":1,"52":1,"55":1,"62":1,"63":1,"69":1,"72":1,"89":1,"107":1,"132":1,"134":1,"143":1,"158":1,"164":1,"165":2,"166":8,"168":2,"169":1,"170":1,"173":2,"174":4,"178":1,"181":3,"185":5,"186":1,"187":1,"189":1,"192":1,"193":1,"194":1,"195":1,"196":4,"198":1,"208":2,"210":2,"217":4,"219":1,"224":1,"225":2,"227":2,"228":1,"229":4,"230":5,"231":1,"232":2,"233":3,"234":1,"235":1,"237":2,"241":1,"245":1,"246":2,"247":2,"249":1,"252":5,"262":2,"270":1,"271":1,"274":1,"277":1,"284":1,"290":1,"298":1,"305":1,"311":1,"327":1,"332":1,"336":1,"339":1,"340":1,"341":1,"343":1,"349":1,"350":1,"393":1,"405":1,"409":1,"414":1,"415":1,"416":1,"417":1,"418":1,"420":1,"427":1,"430":1,"438":1,"439":1,"444":1,"446":1,"485":1,"497":1,"498":1,"499":1,"500":1,"509":1,"515":1,"521":1,"523":1,"537":1,"553":1,"567":1,"577":1,"578":1,"584":1,"590":1,"595":1,"596":1,"604":1,"606":1,"660":1,"661":1,"662":1,"663":3,"667":1,"714":3,"717":1,"725":1,"734":1,"735":4,"744":1,"747":1,"749":1,"750":1}}],["48",{"2":{"749":1}}],["456",{"2":{"253":1}}],["4568",{"2":{"253":2}}],["466",{"2":{"252":1}}],["43∗102143",{"2":{"252":1}}],["43",{"2":{"252":2}}],["478761z",{"2":{"196":1}}],["478714z",{"2":{"196":1}}],["404",{"0":{"742":1,"743":1},"1":{"745":1,"746":1,"748":1,"749":1},"2":{"741":1}}],["403",{"2":{"741":1}}],["401",{"2":{"741":1,"753":1}}],["400",{"2":{"741":4,"753":1}}],["4000",{"2":{"207":3}}],["4090",{"2":{"253":3}}],["4096",{"2":{"121":1,"128":5,"164":5}}],["40",{"2":{"196":2,"749":1}}],["4s",{"2":{"196":3}}],["428",{"2":{"252":1}}],["42u32",{"2":{"221":1}}],["42",{"2":{"178":1,"196":6,"214":2}}],["44",{"2":{"128":1,"164":1,"204":1}}],["4194304",{"2":{"121":1,"128":1,"164":1}}],["4",{"0":{"95":1,"177":1,"188":1,"202":1,"213":1,"220":1,"301":1},"2":{"6":1,"18":2,"88":1,"143":2,"146":1,"174":1,"181":1,"221":1,"253":1,"272":1,"290":1,"301":1,"305":1,"311":1,"340":1,"341":1,"343":1,"349":1,"350":1,"393":1,"414":1,"415":1,"416":1,"418":1,"420":1,"423":1,"427":1,"430":1,"438":1,"439":1,"497":1,"498":1,"499":1,"500":1,"509":1,"515":1,"537":1,"577":1,"590":1,"604":1,"606":1,"749":1,"750":1}}],["`iroha",{"2":{"220":1,"664":1}}],["```",{"2":{"189":1}}],["`api",{"2":{"714":1}}],["`at",{"2":{"180":1}}],["`asset",{"2":{"180":1}}],["`account",{"2":{"180":1}}],["`http",{"2":{"181":2}}],["`https",{"2":{"5":1}}],["`has",{"2":{"180":2}}],["`domain",{"2":{"180":1}}],["`versionedsignedtransaction`",{"2":{"175":1}}],["`executable`",{"2":{"175":1}}],["`configs",{"2":{"714":2}}],["`client`",{"2":{"175":1}}],["`cargo",{"2":{"6":1}}],["`",{"2":{"175":1,"180":5}}],["`window`",{"2":{"175":1}}],["`fetch`",{"2":{"175":1}}],["`undicifetch`",{"2":{"175":1}}],["`telemetry",{"2":{"714":1}}],["`typeerror",{"2":{"175":1}}],["`typical",{"2":{"141":1}}],["`torii`",{"2":{"714":1}}],["`torii",{"2":{"113":1,"164":1,"714":1}}],["`store`",{"2":{"52":1}}],["vpn",{"2":{"249":1,"258":2}}],["vulnerabilities",{"0":{"253":1},"2":{"246":1,"248":2,"249":1,"260":2}}],["vulnerability",{"2":{"234":2,"268":2}}],["vueuse",{"2":{"181":1}}],["vuemain",{"2":{"181":1}}],["vueapp",{"2":{"181":1}}],["vuecomponents",{"2":{"181":2}}],["vue",{"2":{"181":18}}],["v2",{"2":{"217":1,"248":1}}],["v1",{"2":{"170":1,"183":1,"319":1,"546":1,"548":1,"550":1}}],["vs",{"0":{"229":1},"1":{"230":1,"231":1,"232":1,"233":1,"234":1,"235":1},"2":{"105":1,"166":1,"273":1}}],["void",{"2":{"193":6}}],["voting",{"2":{"28":2}}],["volumes",{"2":{"18":4}}],["vary",{"2":{"631":1}}],["varying",{"2":{"287":1}}],["var",{"2":{"113":1,"164":1,"186":13,"196":1}}],["variety",{"2":{"65":1,"86":1,"94":1,"134":1,"138":1,"249":1,"264":1}}],["variations",{"2":{"238":1}}],["variants",{"2":{"241":1,"290":1,"294":1,"298":1,"305":1,"311":1,"315":1,"316":1,"317":1,"319":1,"326":1,"327":1,"332":1,"336":1,"339":1,"340":1,"341":1,"343":1,"349":1,"350":1,"353":1,"357":1,"359":1,"393":1,"405":1,"409":1,"414":1,"415":1,"416":1,"417":1,"418":1,"420":1,"421":1,"427":1,"430":1,"438":1,"439":1,"444":1,"445":1,"446":1,"485":1,"487":1,"494":1,"495":1,"497":1,"498":1,"499":1,"500":1,"509":1,"515":1,"516":1,"521":1,"523":1,"531":1,"537":1,"540":1,"546":1,"548":1,"550":1,"553":1,"567":1,"577":1,"578":1,"584":1,"588":1,"589":1,"590":1,"595":1,"596":1,"604":1,"606":1}}],["variant",{"2":{"38":1,"89":1,"94":1,"219":1,"238":1,"244":1,"290":2,"294":2,"298":2,"305":2,"311":2,"315":2,"316":2,"317":2,"319":2,"326":2,"327":2,"332":2,"336":2,"339":2,"340":2,"341":2,"343":2,"349":2,"350":2,"353":2,"357":2,"359":2,"393":2,"405":2,"409":2,"414":2,"415":2,"416":2,"417":2,"418":2,"420":2,"421":2,"427":2,"430":2,"438":2,"439":2,"444":2,"445":2,"446":2,"485":2,"487":2,"494":2,"495":2,"497":2,"498":2,"499":2,"500":2,"509":2,"515":2,"516":2,"521":2,"523":2,"531":2,"537":2,"540":2,"546":2,"548":2,"550":2,"553":2,"567":2,"577":2,"578":2,"584":2,"588":2,"589":2,"590":2,"595":2,"596":2,"604":2,"606":2}}],["variable",{"2":{"12":1,"16":1,"126":2,"127":1,"146":1,"244":4,"256":1,"283":1,"750":1}}],["variables",{"0":{"9":1,"16":1,"20":1},"2":{"6":1,"9":1,"13":2,"16":1,"125":4,"135":2,"143":1,"151":1,"186":1,"188":1,"286":1,"666":1}}],["various",{"2":{"13":1,"29":1,"56":1,"57":1,"94":2,"129":1,"246":1,"249":1}}],["vast",{"2":{"86":1}}],["valuable",{"2":{"629":1,"631":1}}],["valuing",{"2":{"249":1}}],["valuetype",{"2":{"214":1}}],["value>",{"2":{"187":1,"188":1,"189":1,"193":5}}],["valuepredicate>",{"2":{"187":1,"188":1,"189":1}}],["valuepredicate",{"2":{"187":1}}],["values",{"0":{"127":1},"2":{"25":1,"50":1,"55":1,"57":2,"62":2,"122":1,"124":1,"125":3,"127":2,"137":1,"143":2,"178":1,"348":1,"669":1,"725":2,"726":1,"750":1}}],["value",{"0":{"25":1},"2":{"25":1,"46":1,"50":1,"51":1,"52":2,"53":4,"54":1,"92":4,"93":1,"97":2,"125":4,"128":5,"134":1,"137":3,"164":5,"176":2,"177":2,"178":9,"179":3,"180":1,"181":10,"187":2,"189":3,"190":5,"191":2,"193":20,"196":1,"200":1,"202":2,"204":3,"212":2,"213":1,"214":9,"221":1,"222":3,"238":1,"252":1,"272":1,"289":1,"290":1,"291":1,"292":1,"293":1,"294":1,"295":1,"296":1,"297":1,"298":1,"299":1,"300":1,"301":1,"302":2,"303":1,"304":2,"305":1,"306":1,"307":1,"308":1,"309":1,"310":1,"311":1,"312":1,"313":1,"314":1,"315":1,"316":1,"317":1,"318":1,"319":1,"320":1,"321":1,"322":1,"323":1,"325":1,"326":1,"327":1,"329":1,"330":1,"331":1,"332":1,"336":1,"337":1,"338":1,"339":1,"340":1,"341":1,"342":1,"343":1,"344":1,"345":1,"346":1,"347":1,"349":1,"350":1,"353":1,"354":1,"355":1,"356":1,"357":1,"358":1,"359":1,"360":1,"361":1,"362":1,"363":1,"364":1,"365":1,"366":1,"367":1,"380":1,"381":1,"382":1,"383":1,"384":1,"385":1,"386":1,"387":1,"388":1,"389":1,"390":1,"391":1,"392":1,"393":1,"395":1,"396":1,"397":1,"398":1,"399":1,"400":1,"401":1,"402":1,"403":1,"404":1,"405":1,"406":1,"407":1,"408":1,"409":1,"414":1,"415":1,"416":1,"417":1,"418":1,"419":1,"420":1,"421":1,"426":1,"427":1,"428":1,"429":1,"430":1,"431":1,"433":2,"434":2,"435":2,"436":2,"437":2,"438":1,"439":1,"440":1,"441":1,"442":1,"443":1,"444":1,"445":1,"446":1,"447":1,"449":1,"450":2,"451":1,"452":1,"453":1,"457":1,"458":1,"483":1,"484":1,"485":1,"486":1,"487":1,"488":1,"489":1,"490":1,"491":1,"492":1,"493":1,"494":1,"495":1,"496":1,"497":1,"498":1,"499":1,"500":1,"501":1,"502":1,"503":1,"504":1,"505":1,"506":1,"507":1,"508":1,"509":1,"510":1,"511":1,"512":1,"513":1,"514":1,"515":1,"516":1,"517":1,"518":1,"519":1,"520":1,"521":1,"522":1,"523":1,"524":1,"525":1,"526":1,"527":1,"528":1,"529":1,"530":1,"531":1,"532":2,"533":2,"534":2,"535":2,"536":2,"537":1,"538":1,"539":1,"540":1,"544":1,"545":1,"546":1,"547":1,"548":1,"549":1,"550":1,"551":1,"552":1,"553":1,"554":1,"555":1,"556":1,"557":1,"558":1,"559":1,"560":1,"561":1,"562":1,"563":1,"564":1,"565":1,"567":1,"568":1,"570":1,"571":1,"572":1,"573":1,"574":1,"575":1,"576":1,"577":1,"578":1,"579":2,"580":1,"581":1,"582":1,"583":1,"584":1,"585":1,"586":1,"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"593":1,"594":1,"595":1,"596":1,"597":1,"598":1,"599":1,"600":1,"601":1,"602":1,"603":1,"604":1,"605":1,"606":1,"607":1,"608":1,"609":1,"610":1,"611":1,"612":1,"613":1,"614":1,"615":1,"616":1,"617":1,"618":1,"630":1,"631":2,"657":2,"663":8,"666":1,"678":2,"682":1,"683":2,"684":1,"692":2,"693":2,"694":1,"702":2,"712":1,"720":1}}],["val",{"2":{"185":1,"186":3,"187":14,"188":2,"189":2,"190":3,"192":2,"483":1}}],["validity",{"2":{"167":1,"255":1,"627":1,"656":1}}],["valid",{"2":{"53":1,"63":1,"220":1,"221":1,"238":1,"273":1}}],["validated",{"2":{"728":2}}],["validate",{"2":{"63":1,"640":1}}],["validator",{"2":{"62":2,"63":2,"141":1,"628":1,"660":1}}],["validators",{"0":{"62":1,"63":1},"1":{"63":1},"2":{"33":1,"62":4,"63":6,"89":1,"111":1,"141":2}}],["validationfail",{"0":{"606":1},"2":{"577":1}}],["validation",{"2":{"32":1,"63":2,"577":1,"703":1,"728":1}}],["validating",{"2":{"32":1,"181":2,"728":4}}],["v",{"2":{"20":1,"181":3,"200":2,"279":1}}],["vfr",{"2":{"17":2,"210":1,"217":1}}],["viruses",{"2":{"258":1}}],["virtual",{"2":{"258":1,"263":1}}],["victim",{"2":{"253":1}}],["vivaldi",{"2":{"249":1}}],["violations",{"2":{"249":1}}],["vigilant",{"2":{"248":1}}],["vital",{"2":{"237":1}}],["vite",{"2":{"181":1}}],["vitepress",{"2":{"4":1}}],["visit",{"2":{"185":1}}],["visualize",{"0":{"207":1},"2":{"212":1,"227":1}}],["visualizing",{"0":{"181":1,"192":1,"215":1},"1":{"182":1}}],["visualising",{"0":{"224":1},"2":{"181":1,"192":1,"224":1}}],["viewing",{"2":{"627":1}}],["views",{"2":{"181":1}}],["viewer",{"2":{"154":1}}],["view",{"0":{"112":1,"652":1,"653":1},"2":{"28":4,"34":1,"65":1,"69":1,"98":1,"112":1,"207":3,"323":1,"626":2,"649":1,"651":2,"654":1,"700":1,"705":1,"735":4,"749":3,"750":1}}],["via",{"0":{"198":1},"1":{"199":1,"200":1,"201":1,"202":1,"203":1,"204":1,"205":1,"206":1,"207":1,"208":1},"2":{"16":1,"36":1,"39":1,"45":1,"50":1,"56":1,"71":1,"97":1,"113":1,"125":1,"126":1,"127":2,"143":1,"151":1,"164":1,"166":1,"174":1,"183":1,"217":2,"236":1,"248":1,"263":1,"268":1,"271":1,"274":1,"277":1,"284":1,"285":1,"286":1,"646":1,"654":1,"658":2}}],["vet",{"2":{"231":1}}],["vecpublickey",{"2":{"177":2}}],["vecinstruction",{"2":{"176":2,"181":2}}],["vec",{"0":{"607":1,"608":1,"609":1,"610":1,"611":1,"612":1,"613":1,"614":1,"615":1,"616":1,"617":1},"2":{"53":2,"61":1,"67":1,"71":1,"72":1,"76":1,"92":1,"93":1,"104":7,"107":2,"176":1,"180":3,"219":2,"325":3,"352":1,"353":1,"431":1,"439":3,"454":1,"492":1,"496":1,"499":2,"539":1,"540":2,"562":1,"563":1,"564":1,"565":1,"607":1,"608":1,"609":1,"610":1,"611":1,"612":1,"613":1,"614":1,"615":1,"616":1,"617":1,"619":1,"658":1,"666":3,"668":1,"669":1,"670":1,"671":1,"673":1,"674":1,"676":1,"679":1,"680":1,"681":1,"683":1,"684":1,"686":1,"687":1,"688":1,"689":1,"690":1,"696":1,"697":1,"700":1,"704":1,"705":1,"707":1,"710":1,"713":1}}],["vectorization",{"2":{"105":1}}],["vectors",{"2":{"50":1}}],["vector",{"2":{"49":1}}],["versatile",{"2":{"268":1}}],["versionedrejectedtransaction>",{"2":{"707":1}}],["versionedcommittedblock",{"2":{"696":1}}],["versionedsignedtransaction>",{"2":{"707":1}}],["versionedsignedtransaction",{"2":{"193":10}}],["versionedsignedqueryrequest",{"2":{"175":2}}],["versioning",{"0":{"643":1},"2":{"626":1}}],["version=",{"2":{"196":1}}],["versions",{"0":{"282":1},"2":{"21":1,"127":1,"185":1,"210":1,"227":1,"229":1,"272":1,"279":3,"282":2,"643":1}}],["version",{"0":{"279":1,"281":1,"715":1},"1":{"716":1,"717":1},"2":{"6":1,"103":1,"161":1,"166":1,"173":1,"185":2,"200":2,"210":2,"217":4,"229":1,"242":1,"248":1,"249":5,"272":2,"279":3,"280":2,"281":2,"282":1,"283":4,"643":1,"715":1,"717":3}}],["verifying",{"2":{"255":1}}],["verify",{"2":{"248":1,"249":1,"255":1,"256":2,"259":2,"273":1,"640":1}}],["verification",{"2":{"211":1,"627":1}}],["verbose",{"2":{"100":1,"120":1,"150":1,"200":2}}],["verdict",{"2":{"62":6,"63":2}}],["verdicts",{"2":{"62":2}}],["very",{"2":{"18":1,"42":1,"50":1,"100":1,"104":1,"175":1,"203":1,"221":1,"229":1,"233":1,"656":1}}],["ve",{"2":{"18":1,"40":2,"65":1,"91":1,"94":1,"101":1,"107":1,"135":1,"174":2,"181":1,"217":1,"273":1}}],["vendored",{"2":{"6":2,"234":1}}],["xkcd",{"2":{"253":2,"278":1}}],["xdg",{"2":{"218":1}}],["x26",{"2":{"53":2,"175":5,"219":1,"657":2,"659":2,"664":1}}],["x",{"2":{"16":2,"39":1,"89":1,"176":4,"180":6,"666":5,"748":1}}],["x86",{"2":{"6":3}}],["x3c",{"2":{"4":6,"5":3,"9":1,"53":3,"104":1,"181":64,"186":3,"187":3,"188":3,"189":2,"190":1,"193":14,"200":3,"219":1,"282":1,"707":2}}],["$$",{"2":{"252":2}}],["$$entropy=log",{"2":{"252":2}}],["$it",{"2":{"190":2,"191":1}}],["$whiterabbitasset",{"2":{"190":3}}],["$whiterabbit",{"2":{"190":1}}],["$madhatterasset",{"2":{"189":1,"190":2,"191":1}}],["$madhatter",{"2":{"188":1,"190":1}}],["$assetdefinition$asset",{"2":{"189":1,"190":1}}],["$assetdefinition",{"2":{"189":1}}],["$asset",{"2":{"189":1}}],["$account",{"2":{"188":1,"190":1}}],["$alias",{"2":{"186":1}}],["$domain",{"2":{"187":1}}],["$default",{"2":{"186":1}}],["$path",{"2":{"16":2}}],["$",{"2":{"5":1,"16":10,"20":4,"74":1,"83":1,"174":7,"180":11,"181":2,"187":2,"188":2,"189":2,"190":1,"191":1,"210":3,"239":7,"244":6,"279":2,"280":1,"282":2,"660":1}}],["=105",{"2":{"252":1}}],["=75",{"2":{"252":1}}],["=log",{"2":{"252":2}}],["=2",{"2":{"217":4}}],["=>",{"2":{"176":2,"179":1,"180":6,"181":5,"183":1,"224":2}}],["===",{"2":{"176":1}}],["==",{"2":{"94":1,"215":2}}],["=",{"2":{"5":3,"52":6,"53":12,"60":3,"61":2,"66":3,"67":3,"71":2,"92":4,"93":6,"94":3,"95":2,"103":6,"104":3,"105":5,"113":10,"143":37,"164":10,"175":7,"176":3,"177":3,"178":3,"179":7,"180":6,"181":15,"183":2,"185":3,"186":16,"187":16,"188":7,"189":11,"190":5,"191":2,"192":1,"193":41,"203":3,"211":2,"212":3,"213":4,"214":4,"215":2,"217":12,"218":6,"219":5,"220":4,"221":4,"222":9,"223":1,"224":1,"657":1,"664":5,"666":1}}],["k8s",{"2":{"286":1}}],["kubernetes",{"0":{"276":1},"2":{"628":1}}],["kura",{"0":{"155":1,"638":1},"2":{"6":1,"143":1,"155":1,"196":3,"626":1}}],["kde",{"2":{"249":1}}],["kp",{"2":{"218":2}}],["kwargs",{"2":{"214":1}}],["kt",{"2":{"187":1,"188":1}}],["kts",{"2":{"185":1}}],["kanji",{"2":{"238":1}}],["kakuyaku",{"2":{"181":2}}],["kagami",{"0":{"238":1,"240":1,"241":1,"242":1,"243":1,"639":1},"1":{"239":1,"241":1,"242":1,"243":1,"244":2},"2":{"114":2,"130":4,"134":5,"144":2,"172":3,"202":7,"237":1,"238":5,"239":7,"241":3,"242":2,"243":2,"244":3,"246":1,"626":1}}],["kotlinopen",{"2":{"187":1}}],["kotlinval",{"2":{"187":1}}],["kotlinfun",{"2":{"187":1}}],["kotlinimport",{"2":{"187":1,"192":1}}],["kotlinpackage",{"2":{"186":1}}],["kotlinplugins",{"2":{"185":1}}],["kotlinx",{"2":{"185":4,"187":2}}],["kotlin",{"0":{"184":1},"1":{"185":1,"186":1,"187":1,"188":1,"189":1,"190":1,"191":1,"192":1,"193":1},"2":{"27":1,"29":1,"42":1,"43":1,"166":1,"185":3,"186":1,"188":3,"189":7,"190":3,"191":2,"192":1,"227":1,"287":1}}],["kotlincargo",{"2":{"14":2}}],["kind",{"2":{"32":1,"40":1,"65":2,"79":1,"80":1,"81":1,"94":1,"181":2,"219":1,"273":1,"334":1,"335":1,"621":1,"622":1,"623":1,"624":1,"625":1,"666":1}}],["kinds",{"2":{"10":1,"100":1,"148":1}}],["king",{"2":{"24":1}}],["kept",{"2":{"256":1}}],["kevin",{"2":{"253":1}}],["keen",{"2":{"97":1,"221":1}}],["keeping",{"2":{"627":1}}],["keepassx",{"2":{"264":1}}],["keepassxc",{"0":{"265":1},"1":{"266":1},"2":{"252":2,"264":6,"265":6,"266":3,"268":4,"269":1}}],["keepass",{"2":{"264":2}}],["keeps",{"2":{"252":1,"254":1}}],["keep",{"2":{"5":2,"16":1,"212":1,"228":1,"230":1,"235":1,"248":1,"249":2,"250":1,"252":4,"258":3,"263":2,"627":1,"660":1}}],["keyed",{"2":{"678":1,"692":1,"693":1,"702":1}}],["keyvaluetx",{"2":{"193":4}}],["keys",{"0":{"115":1,"132":1,"133":1,"135":1,"145":1,"237":1,"238":1,"256":1,"261":1,"262":1,"267":1,"273":1,"286":1},"1":{"133":1,"134":2,"135":2,"136":1,"238":1,"239":2,"240":1,"241":1,"242":1,"243":1,"244":1,"262":1,"263":2,"264":2,"265":2,"266":2,"267":1,"268":2,"269":2},"2":{"57":2,"65":1,"115":2,"125":1,"126":1,"132":2,"134":5,"135":4,"137":2,"143":2,"145":2,"146":1,"151":3,"161":1,"167":1,"172":1,"175":1,"200":1,"202":4,"203":1,"218":2,"229":1,"237":4,"238":2,"239":1,"246":4,"248":4,"250":4,"254":1,"256":4,"261":2,"262":3,"263":4,"264":4,"266":3,"267":2,"268":3,"271":1,"273":1,"285":1,"286":6}}],["keypairfromhex",{"2":{"187":1}}],["keypair",{"2":{"53":1,"175":5,"181":1,"186":4,"187":10,"188":5,"189":9,"190":5,"191":4,"193":14,"218":1}}],["keyboard",{"2":{"39":1,"249":1}}],["key>",{"2":{"9":1}}],["key=",{"2":{"9":1,"20":2,"181":1}}],["key",{"0":{"134":1,"254":1,"268":1},"1":{"255":1,"256":1},"2":{"9":1,"18":30,"20":1,"21":2,"22":2,"25":1,"41":1,"46":1,"50":1,"51":1,"52":2,"53":7,"54":1,"55":1,"61":1,"69":2,"71":1,"97":1,"113":2,"115":3,"126":2,"127":4,"128":5,"132":1,"134":6,"135":8,"137":2,"141":2,"143":9,"145":3,"146":4,"151":5,"164":5,"167":1,"175":6,"177":5,"181":2,"188":4,"193":2,"200":1,"202":10,"203":4,"211":1,"213":7,"217":2,"218":4,"220":8,"238":11,"239":13,"246":2,"248":1,"249":1,"250":4,"254":8,"255":9,"256":9,"261":2,"263":8,"264":2,"265":7,"266":3,"268":5,"269":1,"273":9,"286":2,"364":1,"382":1,"383":1,"392":1,"402":1,"433":1,"434":1,"435":1,"436":1,"437":1,"490":1,"510":1,"511":1,"512":1,"513":1,"514":1,"532":1,"533":1,"534":1,"535":1,"536":1,"539":1,"557":1,"558":1,"559":1,"560":1,"561":1,"639":1,"663":10,"682":1,"704":1,"712":1}}],["knowing",{"2":{"252":1}}],["known",{"2":{"101":1,"135":1,"146":1,"238":1,"249":4,"269":1,"683":1,"684":1,"700":1,"704":1}}],["knowledge",{"2":{"79":1,"185":1,"217":1,"225":1}}],["know",{"2":{"5":1,"18":1,"28":1,"135":1,"146":1,"153":1,"163":1,"175":1,"177":1,"185":2,"211":1,"213":1,"214":1,"215":1,"217":2,"220":1,"221":2,"222":2,"256":1,"684":1}}],["jewellery",{"2":{"631":1}}],["jetbrains",{"2":{"185":2}}],["j",{"2":{"238":1,"239":1}}],["jdk15on",{"2":{"185":1}}],["jitpack",{"2":{"185":1}}],["jp",{"2":{"185":1,"186":8,"187":12,"192":4,"193":20}}],["jvm",{"2":{"185":3}}],["janek",{"2":{"268":1}}],["japanese",{"2":{"155":1,"238":1,"714":1}}],["javatest",{"2":{"193":1}}],["javapackage",{"2":{"193":1}}],["java",{"0":{"184":1,"193":1},"1":{"185":1,"186":1,"187":1,"188":1,"189":1,"190":1,"191":1,"192":1,"193":1},"2":{"27":1,"29":1,"42":1,"43":1,"136":1,"166":1,"185":7,"186":4,"187":2,"193":6,"227":1,"287":1}}],["javascript",{"0":{"173":1},"1":{"174":1,"175":1,"176":1,"177":1,"178":1,"179":1,"180":1,"181":1,"182":1,"183":1},"2":{"5":3,"27":1,"29":1,"42":1,"43":1,"136":1,"166":1,"174":3,"175":1,"176":3,"181":1,"227":1,"249":1,"287":1,"666":1,"749":1}}],["joining",{"2":{"157":1}}],["join",{"2":{"140":1,"146":1,"156":1,"158":1,"181":1}}],["jupiter",{"2":{"193":2}}],["junit",{"2":{"193":2}}],["judge",{"2":{"62":7}}],["justice",{"2":{"224":1}}],["just",{"2":{"16":1,"18":1,"67":1,"72":1,"81":1,"88":2,"97":2,"101":4,"102":1,"128":1,"146":1,"154":1,"163":1,"166":1,"175":1,"203":3,"204":1,"214":1,"217":1,"219":1,"221":2,"224":1,"232":1,"242":1,"250":1,"256":1,"272":1,"280":1,"282":1,"666":2}}],["json4",{"2":{"750":1}}],["jsonscale",{"2":{"749":1}}],["jsonstring",{"0":{"425":1},"2":{"491":1}}],["json`",{"2":{"714":2}}],["jsonlistening",{"2":{"207":1}}],["json5",{"2":{"200":1,"750":1}}],["jsoncrypto",{"2":{"181":1}}],["jsonclient",{"2":{"164":1}}],["json",{"2":{"8":2,"13":2,"16":4,"17":1,"21":1,"22":1,"42":1,"57":3,"114":1,"117":1,"119":1,"120":2,"121":1,"122":1,"125":1,"128":3,"130":5,"131":1,"132":1,"134":3,"135":1,"136":1,"138":1,"141":1,"143":3,"144":1,"145":1,"146":1,"150":1,"154":2,"161":1,"164":3,"174":1,"181":3,"186":1,"200":3,"201":1,"202":1,"204":1,"210":3,"211":5,"217":2,"218":1,"231":1,"238":3,"239":1,"272":1,"663":1,"664":1,"715":1,"717":2,"721":1,"723":2,"724":1,"725":2,"731":1,"733":1,"734":1,"744":1,"746":1,"747":1,"748":3,"749":5,"750":3}}],["js",{"2":{"5":3,"173":1,"174":2,"175":2,"178":1}}],["ntlm",{"2":{"253":3}}],["nvidia®",{"2":{"253":2}}],["npmrc",{"2":{"174":1}}],["npm",{"2":{"173":1,"174":11}}],["nfts",{"2":{"137":2}}],["nuances",{"2":{"251":1}}],["numerous",{"2":{"204":1}}],["numericassetvaluetypeexpected",{"2":{"596":1}}],["numerical",{"2":{"221":1,"500":1}}],["numericspec",{"0":{"458":1},"2":{"317":1}}],["numericvalue",{"2":{"178":2,"179":2,"691":1,"694":1}}],["numeric",{"0":{"329":1,"440":1,"457":1,"529":1,"559":1,"583":1},"2":{"128":2,"164":2,"178":1,"179":1,"204":5,"221":4,"223":1,"238":1,"310":1,"315":2,"316":2,"317":1,"329":1,"332":1,"342":1,"439":2,"440":1,"444":1,"485":2,"499":2,"529":2,"531":2,"559":1,"583":1}}],["numbers",{"2":{"50":1,"88":1,"253":3,"273":1,"280":1,"682":1}}],["number",{"2":{"12":17,"25":1,"28":2,"43":1,"57":1,"84":1,"98":6,"121":2,"137":6,"146":4,"151":2,"181":1,"183":2,"202":1,"214":1,"217":1,"230":1,"238":1,"246":1,"249":1,"252":7,"272":1,"273":1,"574":1,"660":2,"720":1,"735":3,"749":7}}],["null",{"0":{"127":1},"2":{"125":3,"126":1,"127":1,"128":5,"164":5,"176":1,"180":3,"181":3,"187":1,"188":1,"189":1,"200":3,"201":1,"368":1,"369":1,"370":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"378":1,"379":1,"394":1,"656":1}}],["nginx",{"2":{"117":1}}],["n",{"2":{"84":3,"130":2,"742":2,"743":4}}],["nanos",{"2":{"749":2,"750":2}}],["navigation",{"0":{"227":1,"246":1}}],["navigate",{"2":{"196":1,"200":1,"250":1}}],["nature",{"2":{"728":1}}],["naturally",{"2":{"157":1}}],["natural",{"2":{"28":1,"273":2}}],["natively",{"2":{"175":1}}],["native",{"2":{"174":1,"175":3,"181":1,"666":1,"749":1}}],["nailed",{"2":{"104":1}}],["narrow",{"2":{"65":1}}],["naming",{"0":{"660":1},"2":{"42":1,"660":1}}],["namelength",{"2":{"421":1}}],["namely",{"2":{"127":1,"215":1}}],["name=",{"2":{"214":2}}],["named",{"2":{"50":1,"104":1,"171":1,"176":1,"177":1,"220":1,"221":1,"627":1}}],["names",{"2":{"42":1,"57":3,"67":1,"74":1,"659":1}}],["name",{"0":{"448":1,"561":1,"612":1,"659":1},"2":{"36":1,"52":1,"53":1,"74":2,"84":1,"90":1,"93":1,"103":1,"104":2,"106":1,"143":1,"171":1,"174":1,"175":3,"176":2,"177":3,"178":6,"179":4,"180":7,"181":6,"186":1,"187":3,"188":1,"189":1,"193":10,"217":2,"219":1,"220":1,"221":1,"256":1,"289":1,"290":1,"291":1,"292":1,"293":3,"294":1,"295":2,"296":1,"297":1,"298":1,"302":1,"303":1,"304":1,"305":1,"306":1,"307":1,"308":3,"309":1,"310":1,"311":1,"312":1,"313":1,"314":1,"315":1,"316":1,"317":1,"318":1,"319":1,"320":1,"321":1,"322":1,"323":1,"325":1,"326":1,"327":1,"329":1,"330":1,"331":1,"332":1,"336":1,"337":1,"338":1,"339":1,"340":1,"341":1,"342":1,"343":1,"344":1,"345":1,"346":3,"347":1,"349":1,"350":1,"353":1,"354":1,"355":1,"356":1,"357":1,"358":1,"359":1,"360":1,"361":1,"362":1,"363":1,"364":2,"365":1,"366":3,"367":1,"380":1,"381":1,"382":2,"383":2,"384":1,"385":1,"386":1,"387":1,"388":1,"389":3,"390":1,"391":1,"392":2,"393":3,"395":1,"396":1,"397":1,"398":1,"399":1,"400":1,"401":1,"402":2,"403":1,"404":1,"405":1,"406":1,"407":1,"408":1,"409":1,"414":2,"415":1,"416":1,"417":1,"418":1,"419":1,"420":1,"421":1,"426":1,"427":1,"428":1,"429":1,"430":1,"432":1,"433":2,"434":2,"435":2,"436":2,"437":2,"438":3,"439":3,"440":1,"441":1,"442":1,"443":1,"444":1,"445":1,"446":1,"447":1,"449":1,"450":1,"451":1,"452":1,"453":1,"457":1,"458":1,"483":1,"484":3,"485":1,"486":1,"487":1,"488":1,"489":1,"490":1,"491":2,"492":2,"493":1,"494":1,"495":1,"496":1,"497":1,"498":1,"499":1,"500":1,"501":1,"502":1,"503":1,"504":1,"505":1,"506":1,"507":1,"508":1,"509":1,"510":2,"511":2,"512":2,"513":2,"514":2,"515":1,"516":1,"517":1,"518":1,"519":1,"520":1,"521":1,"522":1,"523":1,"524":1,"525":1,"526":3,"527":2,"528":1,"529":1,"530":1,"531":1,"532":2,"533":2,"534":2,"535":2,"536":2,"537":1,"538":1,"539":1,"540":1,"544":1,"545":1,"546":1,"547":1,"548":1,"549":1,"550":1,"551":1,"552":1,"553":1,"554":1,"555":1,"556":1,"561":1,"567":1,"568":1,"570":1,"571":1,"572":1,"573":1,"574":1,"575":2,"576":1,"577":1,"578":1,"579":1,"580":1,"581":1,"582":1,"583":1,"584":1,"585":1,"586":1,"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"593":3,"594":1,"595":1,"596":1,"597":1,"598":1,"599":1,"600":1,"601":1,"602":1,"603":1,"604":1,"605":1,"606":1,"612":1,"618":1,"658":1,"659":18,"660":1,"670":1,"678":2,"679":4,"686":2,"692":2,"693":2,"702":2,"712":1}}],["nightly",{"2":{"281":1}}],["nightmare",{"2":{"158":1}}],["nine",{"2":{"25":1}}],["nice",{"2":{"21":1,"88":1,"92":1,"224":1,"273":1}}],["necessity",{"2":{"263":1}}],["necessary",{"2":{"72":1,"101":1,"110":1,"166":1,"167":1,"169":1,"172":1,"176":1,"187":1,"218":1,"247":1,"249":1,"253":1,"260":1,"265":1,"268":1,"649":1,"656":1,"706":1}}],["necessarily",{"2":{"65":1,"137":1,"187":1,"233":1,"243":1}}],["net",{"2":{"185":1,"187":1}}],["networking",{"2":{"200":1}}],["networktojoin",{"2":{"186":1}}],["networks",{"2":{"65":1,"136":1,"208":1,"254":1,"258":2,"263":1,"267":1,"654":1}}],["network",{"0":{"19":1,"132":1,"133":1,"196":1},"1":{"20":1,"21":1,"133":1,"134":2,"135":2,"136":1,"197":1},"2":{"10":1,"18":1,"20":1,"21":3,"22":3,"28":1,"39":1,"42":1,"65":2,"106":1,"132":1,"135":4,"137":2,"138":1,"143":1,"156":1,"159":1,"160":2,"161":2,"162":1,"163":2,"166":2,"167":1,"172":2,"178":1,"186":4,"194":1,"195":1,"196":8,"197":2,"198":2,"199":1,"200":1,"202":1,"204":1,"207":2,"217":2,"221":1,"226":1,"230":3,"246":2,"256":2,"258":2,"263":1,"628":1,"634":2,"643":1,"654":1,"684":1,"685":1,"686":1,"705":1,"714":1,"728":2,"734":1,"735":1,"744":1,"747":1,"749":1}}],["nexus",{"2":{"174":2}}],["next",{"0":{"208":1},"2":{"88":2,"89":1,"94":1,"97":2,"99":1,"108":1,"187":1,"196":4,"215":1,"221":1,"243":1,"654":1,"740":1}}],["near",{"2":{"103":1}}],["never",{"2":{"43":1,"88":1,"127":1,"128":1,"214":1,"248":1,"256":2,"259":1,"273":1}}],["negligent",{"2":{"260":1}}],["negligible",{"2":{"39":1}}],["negativevalue",{"2":{"430":1}}],["negative",{"2":{"43":2,"178":1,"214":2}}],["neither",{"2":{"16":1,"89":1,"666":1}}],["needless",{"2":{"224":1}}],["needs",{"2":{"20":1,"21":1,"28":1,"57":3,"94":1,"135":1,"141":1,"146":1,"174":1,"203":1,"217":1,"218":2,"238":1,"256":1,"260":1,"267":1,"268":1}}],["needed",{"2":{"18":1,"126":1,"137":1,"272":1}}],["need",{"2":{"6":1,"14":1,"18":2,"20":1,"21":1,"22":1,"24":1,"39":1,"41":2,"42":1,"43":1,"56":1,"65":1,"67":1,"69":1,"83":1,"93":1,"94":4,"97":1,"100":1,"101":2,"102":1,"103":2,"110":1,"116":1,"128":1,"138":1,"141":2,"160":2,"170":1,"172":1,"174":7,"175":6,"176":2,"177":2,"178":3,"181":1,"189":1,"202":1,"203":1,"210":1,"214":2,"215":2,"219":1,"220":1,"221":2,"222":3,"226":1,"252":1,"256":2,"257":1,"263":2,"272":2,"283":1,"656":3,"658":1,"666":1,"684":1}}],["news",{"2":{"627":1}}],["newrole",{"0":{"453":1},"2":{"415":2,"507":1}}],["newassetdefinition",{"0":{"450":1},"2":{"415":2,"504":1}}],["newaccount",{"0":{"449":1},"2":{"42":1,"92":3,"104":1,"177":3,"220":1,"415":2,"502":1}}],["newly",{"2":{"203":1,"228":1}}],["newnetwork",{"2":{"186":2}}],["newdomain",{"0":{"451":1},"2":{"176":3,"181":3,"415":2,"505":1}}],["newparameter",{"0":{"47":1,"452":1},"2":{"40":1,"41":1,"47":1,"128":14,"164":14,"416":2,"420":1,"661":1}}],["newer",{"2":{"6":1,"170":1,"229":1}}],["new",{"0":{"60":1,"103":1,"133":1,"134":1},"1":{"134":1,"135":1},"2":{"5":1,"7":1,"9":1,"12":1,"16":1,"17":1,"21":1,"28":1,"31":1,"40":1,"42":1,"52":6,"53":10,"57":1,"60":5,"61":2,"66":1,"67":1,"71":3,"72":1,"78":2,"84":1,"92":20,"93":6,"94":2,"95":1,"96":2,"97":2,"101":1,"103":2,"104":5,"128":7,"129":1,"134":2,"136":1,"137":2,"141":1,"143":1,"146":1,"160":1,"161":1,"162":1,"166":1,"171":1,"175":2,"176":6,"177":4,"178":2,"181":5,"185":1,"187":2,"188":4,"189":5,"190":1,"193":18,"196":4,"199":2,"201":4,"202":4,"203":2,"207":1,"213":1,"217":1,"218":2,"219":1,"220":4,"221":2,"222":2,"223":1,"229":3,"230":1,"238":1,"256":3,"265":4,"272":2,"286":1,"309":1,"347":1,"493":1,"652":1,"658":1,"661":1,"663":2,"664":2,"666":1,"720":1}}],["nobody",{"2":{"163":1,"215":1}}],["nontrivial",{"0":{"454":1},"2":{"405":2}}],["nonzero",{"0":{"455":1,"456":1,"469":1,"470":1},"2":{"328":1,"404":1,"469":1,"470":1,"575":2}}],["nonillion",{"2":{"252":1}}],["nonce",{"0":{"123":1},"2":{"113":2,"123":1,"164":2,"575":1}}],["none",{"2":{"28":1,"176":1,"181":2,"207":2}}],["non",{"0":{"136":1,"631":1,"633":1},"2":{"24":2,"25":1,"39":1,"43":2,"103":1,"136":1,"141":1,"165":1,"178":3,"189":3,"200":1,"214":2,"215":1,"221":2,"253":1,"631":1,"633":1}}],["no",{"0":{"107":1},"2":{"18":1,"22":1,"39":2,"62":3,"74":2,"103":1,"104":3,"106":1,"107":1,"125":2,"146":1,"178":1,"183":1,"212":1,"219":2,"220":1,"221":2,"229":1,"231":2,"238":3,"239":1,"252":1,"259":1,"263":1,"282":1,"658":1,"748":1}}],["now",{"2":{"18":1,"20":1,"22":1,"78":1,"91":1,"94":2,"97":2,"99":1,"104":1,"156":1,"175":2,"176":1,"177":1,"200":1,"203":1,"204":1,"208":1,"210":1,"213":1,"215":2,"218":2,"220":1,"221":2,"253":2,"655":1,"723":1}}],["normally",{"2":{"88":1,"106":1}}],["normal",{"2":{"87":1,"97":1,"197":1,"238":1,"239":2}}],["nor",{"2":{"16":1,"89":1,"666":1}}],["nodefetch",{"2":{"175":3}}],["nodeniesandatleastoneallow",{"2":{"62":1}}],["nodenies",{"2":{"62":1}}],["nodes",{"2":{"21":2,"230":3}}],["node",{"2":{"5":1,"106":1,"157":1,"173":1,"174":7,"175":8,"241":1,"628":1,"703":2,"715":1,"717":1}}],["notation",{"2":{"666":2}}],["notable",{"2":{"105":1}}],["notably",{"2":{"103":1}}],["notpermitted",{"2":{"606":1}}],["nothing",{"2":{"256":1}}],["notices",{"2":{"221":1}}],["notice",{"2":{"221":1,"273":1}}],["noticed",{"2":{"97":1}}],["notify",{"2":{"211":1,"260":1,"647":1}}],["not",{"0":{"742":1,"743":1},"1":{"745":1,"746":1,"748":1,"749":1},"2":{"4":1,"20":1,"21":1,"24":1,"28":2,"39":1,"42":4,"46":1,"56":2,"62":1,"63":2,"65":2,"87":2,"88":1,"89":2,"94":1,"97":2,"100":1,"104":1,"105":1,"106":1,"116":1,"125":1,"126":2,"128":1,"136":1,"137":4,"139":1,"146":1,"150":1,"154":1,"155":1,"162":1,"171":2,"174":1,"175":2,"176":1,"178":1,"187":1,"189":1,"190":1,"196":1,"201":1,"203":2,"211":1,"212":3,"215":1,"217":1,"219":2,"220":1,"221":3,"229":1,"230":1,"238":3,"243":2,"247":3,"248":1,"249":3,"250":1,"254":1,"255":1,"256":2,"259":4,"260":1,"263":1,"264":1,"266":1,"271":1,"273":1,"274":1,"277":1,"281":1,"282":2,"283":2,"284":1,"285":1,"286":2,"405":1,"446":1,"650":2,"659":1,"663":1,"666":1,"669":1,"671":1,"672":1,"679":1,"680":1,"683":2,"710":1,"726":1,"728":2,"741":3,"753":1}}],["notenoughquantity",{"2":{"430":1}}],["notes",{"2":{"247":1}}],["noted",{"2":{"110":1,"211":1}}],["note",{"2":{"4":1,"6":2,"12":1,"14":1,"16":1,"20":1,"21":1,"22":2,"42":1,"69":1,"78":1,"103":1,"116":1,"127":1,"128":1,"134":3,"135":1,"143":1,"170":1,"174":3,"175":1,"177":1,"181":1,"187":1,"197":1,"201":1,"203":1,"212":1,"214":1,"215":2,"218":2,"219":2,"220":1,"221":1,"229":1,"241":1,"249":1,"253":1,"263":1,"266":1,"282":1,"658":2,"659":1,"669":1,"671":1,"680":1,"683":1,"691":1,"709":1}}],["19",{"2":{"497":1}}],["1933∗109",{"2":{"252":1}}],["1933∗1091",{"2":{"252":1}}],["1933",{"2":{"252":1}}],["18",{"2":{"497":1,"749":1,"750":1}}],["185ef76",{"2":{"196":1}}],["17",{"2":{"497":1}}],["1729",{"2":{"239":1}}],["1721132667162",{"2":{"207":3}}],["1cc6256356418d02f19b17487ad4f7f105ae6cd3fd129760c575066484f3ef97",{"2":{"207":1}}],["15",{"2":{"206":1,"497":1}}],["15t05",{"2":{"196":19}}],["15000",{"2":{"122":1}}],["1b1d5514cbbf",{"2":{"196":1}}],["1684843456091",{"2":{"191":1}}],["1684843453085",{"2":{"191":1}}],["1684843454049",{"2":{"191":2}}],["1684843451130",{"2":{"191":5}}],["1684843348692",{"2":{"191":1}}],["1684843345604",{"2":{"191":1}}],["1684843344208",{"2":{"191":3}}],["1684843516303",{"2":{"191":5}}],["1684843514251",{"2":{"191":10}}],["1684843513272",{"2":{"191":7}}],["1684843511587",{"2":{"191":24}}],["1684843205383",{"2":{"190":4}}],["1684843203337",{"2":{"190":8}}],["1684843202389",{"2":{"190":7}}],["1684843200289",{"2":{"190":21,"191":1}}],["1684842998891",{"2":{"189":3}}],["1684842997930",{"2":{"189":4,"190":1}}],["1684842996549",{"2":{"189":9,"190":2,"191":1}}],["1684835733686",{"2":{"188":2,"189":1,"190":1,"191":1}}],["1684835731653",{"2":{"188":4,"189":2,"190":2,"191":2}}],["16px",{"2":{"181":1}}],["16",{"2":{"181":1,"252":4,"253":1,"497":1}}],["16mb",{"2":{"143":1}}],["1min",{"2":{"143":1}}],["1day",{"2":{"143":1}}],["1s",{"2":{"143":3,"196":2}}],["111",{"2":{"221":1}}],["117083z",{"2":{"196":1}}],["117040z",{"2":{"196":1}}],["11",{"2":{"88":5,"393":1,"415":1,"416":1,"420":1,"497":1}}],["123",{"2":{"221":1}}],["12",{"2":{"88":7,"221":2,"393":1,"416":1,"420":1,"497":1}}],["128",{"2":{"25":1,"128":1,"164":1,"214":1,"252":1}}],["1261a436d36779223d7d6cf20e8b644510e488e6a50bafd77a7485264d27197dfaca9e8aa83225cb4d16d67f27dd4f93fc30ffa11adc1f5c88fd5495ecc91020",{"2":{"18":1}}],["127",{"2":{"12":1,"18":1,"20":4,"21":1,"119":1,"120":3,"150":3,"175":7,"181":2,"187":2,"252":1}}],["13",{"2":{"128":1,"164":1,"173":1,"204":1,"217":4,"416":1,"420":1,"497":1}}],["1340",{"2":{"18":7,"146":1,"196":2}}],["133x",{"2":{"18":1}}],["1339",{"2":{"18":7,"146":1,"196":3}}],["1338",{"2":{"18":7,"146":1,"196":2}}],["1337",{"2":{"18":7,"20":1,"146":1,"196":4}}],["135543",{"2":{"12":1}}],["10^3200∗103",{"2":{"253":1}}],["10^3052∗1030",{"2":{"252":1}}],["10^9300∗109",{"2":{"253":1}}],["10^91",{"2":{"252":1}}],["10^2143∗1021",{"2":{"252":1}}],["10u32",{"2":{"223":1}}],["109858z",{"2":{"196":1}}],["109788z",{"2":{"196":1}}],["10s",{"2":{"143":1}}],["10000",{"2":{"187":1}}],["100000",{"2":{"122":1}}],["1000",{"2":{"181":1}}],["100s",{"2":{"113":2,"164":2}}],["100",{"2":{"53":1,"61":1,"71":1,"92":1,"175":1,"179":2,"189":1,"204":2}}],["10",{"2":{"16":1,"18":1,"146":1,"185":1,"186":1,"190":4,"191":3,"193":4,"214":1,"290":1,"341":1,"393":1,"415":1,"416":1,"418":1,"420":1,"497":1,"735":2,"749":1}}],["14",{"2":{"12":1,"207":3,"416":1,"420":1,"497":1,"749":2}}],["1",{"0":{"92":1,"103":1,"134":1,"160":1,"170":1,"174":1,"185":1,"195":1,"199":1,"210":1,"217":1,"229":1,"241":1},"1":{"230":1,"231":1,"232":1,"233":1,"234":1,"235":1},"2":{"5":5,"6":1,"12":1,"18":1,"20":4,"21":1,"28":1,"43":1,"72":1,"88":1,"92":3,"93":1,"103":2,"105":1,"119":1,"120":3,"141":1,"143":1,"150":3,"166":2,"168":1,"174":1,"175":8,"181":3,"185":6,"186":1,"187":2,"196":28,"207":3,"210":1,"222":1,"229":2,"230":1,"252":1,"279":4,"290":1,"294":1,"298":1,"305":1,"311":1,"315":1,"316":1,"317":1,"319":1,"327":1,"332":1,"336":1,"339":1,"340":1,"341":1,"343":1,"349":1,"350":1,"353":1,"357":1,"393":1,"405":1,"409":1,"414":1,"415":1,"416":1,"417":1,"418":1,"420":1,"421":1,"427":1,"430":1,"438":1,"439":1,"444":1,"445":1,"446":1,"485":1,"487":1,"494":1,"495":1,"497":1,"498":1,"499":1,"500":1,"509":1,"515":1,"516":1,"521":1,"523":1,"537":1,"540":1,"546":1,"548":1,"550":1,"553":1,"567":1,"577":1,"578":1,"584":1,"588":1,"589":1,"590":1,"595":1,"596":1,"604":1,"606":1,"717":1,"735":7}}],["u64",{"0":{"456":1,"470":1,"471":1,"482":1,"624":1},"2":{"322":1,"323":4,"328":1,"348":1,"404":1,"456":1,"470":1,"471":1,"482":1,"552":1,"571":1,"572":1,"574":2,"575":2,"749":8}}],["u8",{"0":{"300":1,"301":1,"617":1,"625":1},"2":{"300":1,"301":1,"410":1,"423":1,"439":1,"496":1,"539":1,"617":1,"619":1,"657":2}}],["u16",{"0":{"299":1,"622":1},"2":{"299":1,"424":1,"554":1,"555":1,"556":1}}],["u128",{"0":{"334":1,"530":1,"621":1},"2":{"57":1,"457":1,"500":1,"530":2,"705":3}}],["utf",{"2":{"273":1,"660":1}}],["utility",{"0":{"647":1},"2":{"626":1,"648":1}}],["utilities",{"2":{"175":1}}],["utilise",{"2":{"259":1}}],["utilises",{"2":{"238":1}}],["utilized",{"2":{"264":1}}],["utilize",{"2":{"250":1}}],["utilizes",{"2":{"231":1}}],["utilizing",{"2":{"245":1,"252":1,"268":1,"714":1}}],["util",{"2":{"186":1,"193":6}}],["ul>",{"2":{"181":2}}],["ul",{"2":{"181":2}}],["ui",{"0":{"181":1},"1":{"182":1},"2":{"249":2,"265":1}}],["uint8array",{"2":{"177":1}}],["ux",{"2":{"177":1,"213":1,"220":1,"224":1}}],["ubuntu",{"2":{"170":1}}],["ugly",{"2":{"100":1,"273":1}}],["u32",{"0":{"331":1,"335":1,"443":1,"455":1,"469":1,"481":1,"623":1},"2":{"57":1,"67":2,"77":1,"98":2,"178":2,"179":1,"190":1,"214":2,"222":1,"292":1,"307":1,"313":1,"318":1,"331":1,"332":1,"338":1,"345":1,"348":1,"361":1,"426":2,"428":2,"443":1,"444":1,"455":1,"457":1,"458":1,"469":1,"481":1,"489":1,"516":1,"525":1,"575":1,"592":1,"594":1,"657":2,"660":1,"705":1,"749":1}}],["unmatched",{"2":{"286":1}}],["unverified",{"2":{"259":1}}],["unfamiliar",{"2":{"259":1}}],["unfathomable",{"2":{"253":1}}],["unfortunately",{"2":{"108":1,"110":1,"176":1,"214":1,"273":1}}],["unexpected",{"2":{"250":1}}],["unencrypted",{"2":{"247":1,"256":1}}],["ungoogled",{"2":{"249":1}}],["unattended",{"2":{"247":1,"248":2}}],["unauthorized",{"2":{"247":1,"248":1,"251":1,"258":1,"260":2,"262":1,"267":1}}],["unavailable",{"2":{"176":1,"725":1}}],["unlocked",{"2":{"265":1}}],["unlocks",{"2":{"255":1}}],["unlimitedmetadata",{"2":{"219":3}}],["unlikely",{"2":{"234":1}}],["unlike",{"2":{"210":1,"211":1,"671":1}}],["unless",{"2":{"22":1,"56":1,"63":1,"139":1,"153":1,"200":1,"249":1,"273":1,"672":1}}],["unnecessary",{"2":{"187":1}}],["unnamed",{"2":{"50":1}}],["unusual",{"2":{"185":1,"217":1,"260":1}}],["undefined",{"2":{"656":1,"658":1}}],["underscores",{"2":{"267":1,"659":1}}],["understandable",{"2":{"250":1}}],["understanding",{"2":{"185":1,"217":1}}],["understand",{"2":{"39":1,"97":1,"100":1,"137":1,"141":1,"166":1,"175":1,"208":2}}],["underway",{"2":{"175":1}}],["under",{"0":{"107":1},"2":{"99":1,"107":1,"157":1,"160":1,"174":1,"211":1,"256":1}}],["underlying",{"2":{"24":1,"25":1,"124":1,"143":1,"178":1,"189":1,"214":1,"221":2}}],["undici",{"2":{"175":4}}],["undicifetch",{"2":{"175":1}}],["unchanged",{"2":{"125":1}}],["unwrap",{"2":{"104":2,"218":1,"222":3,"664":5}}],["unsupported",{"2":{"417":1}}],["unstable",{"2":{"108":1}}],["unsafe",{"2":{"103":1,"231":1,"656":1,"658":1}}],["unsigned",{"2":{"25":2,"178":1,"214":3}}],["un",{"0":{"42":1},"2":{"41":5,"42":1,"82":3,"83":2,"84":1,"111":1,"146":1,"281":1}}],["unrecognised",{"2":{"57":1}}],["unregisterbox",{"0":{"604":1},"2":{"416":1}}],["unregistered",{"2":{"111":1}}],["unregistering",{"0":{"163":1},"2":{"42":1,"163":1}}],["unregister",{"0":{"597":1,"598":1,"599":1,"600":1,"601":1,"602":1,"603":1},"2":{"40":1,"41":1,"98":1,"136":1,"163":1,"416":1,"420":1,"604":7,"661":1,"663":4}}],["unreliable",{"2":{"16":1}}],["until",{"2":{"16":1,"89":1,"141":1,"157":1,"161":1,"211":1,"215":1,"725":1}}],["universe",{"2":{"253":1}}],["universal",{"2":{"77":1,"252":1}}],["universally",{"2":{"16":1}}],["unicode",{"2":{"238":2}}],["unit",{"2":{"105":1,"187":1,"368":1,"369":1,"370":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"378":1,"379":1,"394":1,"699":1,"703":1}}],["units",{"2":{"105":1,"179":1,"630":1}}],["uniquely",{"2":{"243":1}}],["unique",{"2":{"42":2,"132":1,"141":1,"202":1,"249":1,"252":1,"253":1,"255":1,"259":1,"268":1,"631":1}}],["unix",{"2":{"16":1,"57":1,"90":1,"242":1,"266":1}}],["unknowncursor",{"2":{"498":1,"741":1}}],["unknown",{"2":{"6":3,"108":2,"259":1,"430":1}}],["urls",{"2":{"125":1,"175":1}}],["url`",{"2":{"113":1,"164":1,"714":3}}],["url=",{"2":{"20":2}}],["url",{"0":{"119":1,"120":1,"148":1,"150":1},"2":{"12":1,"18":9,"21":2,"113":1,"118":2,"119":3,"120":3,"143":3,"148":2,"150":2,"164":1,"175":2,"185":1,"187":3,"218":2}}],["uri",{"2":{"2":1,"218":1}}],["uppercase",{"2":{"252":1,"253":1}}],["uppermost",{"2":{"127":1}}],["upholding",{"2":{"237":1}}],["upgrades",{"2":{"643":1}}],["upgraded",{"2":{"232":1,"359":1,"361":1,"718":1,"727":1}}],["upgrade",{"0":{"605":1},"2":{"229":1,"234":2,"278":1,"283":2,"416":2,"420":1}}],["updating",{"2":{"228":1,"248":1,"283":1,"725":1}}],["updates",{"0":{"228":1},"2":{"248":1,"249":1,"283":1,"637":1}}],["updatekeyvalueinstructioncommitted",{"2":{"193":1}}],["update",{"0":{"135":1,"724":1},"1":{"725":1,"726":1},"2":{"40":1,"41":4,"249":1,"250":1,"252":1,"270":1,"272":2,"279":2,"280":1,"283":2,"657":2,"661":1,"723":1,"726":3}}],["updated",{"2":{"12":1,"146":1,"203":1,"248":1,"260":2,"280":1,"726":2}}],["uptime",{"2":{"181":1,"735":3,"749":5,"750":3}}],["upon",{"2":{"7":1,"8":1,"9":1,"128":1,"650":1,"720":1,"728":1}}],["up",{"0":{"161":1,"199":1},"2":{"6":1,"16":1,"17":1,"20":1,"21":1,"36":1,"42":1,"65":1,"94":1,"97":1,"104":1,"118":1,"135":1,"141":2,"160":1,"161":1,"170":1,"174":2,"175":1,"183":1,"196":2,"198":1,"199":1,"207":1,"210":1,"215":1,"217":1,"219":1,"224":2,"227":1,"228":1,"230":1,"249":2,"252":1,"253":1,"258":1,"259":3,"260":2,"264":1,"272":1,"281":1,"634":1,"720":1,"726":1,"735":1}}],["usb",{"2":{"247":1,"249":1,"268":1}}],["usable",{"2":{"238":1}}],["usage",{"2":{"36":1,"182":1,"200":2,"685":1}}],["usual",{"2":{"187":1,"221":1}}],["usually",{"2":{"20":1,"43":1,"100":1,"146":1,"258":1,"280":1,"282":1,"652":1,"699":1}}],["usr",{"2":{"17":1}}],["us",{"2":{"5":1,"95":1,"107":1,"175":1,"215":1,"230":1,"252":1,"271":1,"274":1,"277":1,"283":1,"284":1,"285":1,"725":1}}],["usetask",{"2":{"181":4}}],["useintervalfn",{"2":{"181":2}}],["usestalestate",{"2":{"181":2}}],["uses",{"2":{"37":1,"181":1,"219":1,"230":1,"270":1,"658":1}}],["useful",{"2":{"21":1,"90":1,"141":1,"152":1,"154":2,"160":1,"175":1,"212":1,"214":1,"217":1,"218":1,"233":1,"679":1,"705":1}}],["username",{"0":{"244":1},"2":{"244":1,"283":1}}],["users",{"0":{"259":1},"2":{"16":1,"39":1,"56":2,"89":1,"136":1,"137":4,"174":1,"202":1,"226":1,"229":1,"243":1,"249":2,"250":1,"257":1,"270":1}}],["user",{"0":{"116":1,"160":1},"2":{"13":1,"45":1,"57":1,"89":1,"104":1,"115":1,"126":1,"128":1,"137":5,"143":1,"145":1,"160":2,"165":1,"172":1,"177":1,"178":1,"190":2,"192":1,"202":1,"203":4,"213":1,"220":1,"243":3,"256":4,"264":1,"265":3,"266":1,"280":1,"283":1,"663":7,"706":1,"735":1,"741":1}}],["used",{"2":{"6":1,"25":1,"33":1,"36":1,"37":1,"39":1,"42":1,"45":3,"46":1,"48":1,"50":1,"52":1,"57":1,"62":1,"63":1,"69":1,"79":1,"81":1,"85":1,"104":1,"106":1,"110":1,"117":1,"120":1,"124":1,"134":1,"143":1,"149":1,"150":1,"153":1,"175":1,"185":1,"192":1,"211":1,"214":1,"215":1,"217":1,"218":1,"231":1,"236":1,"238":4,"241":1,"248":1,"250":1,"253":1,"255":1,"256":1,"264":3,"265":1,"266":2,"269":1,"627":1,"630":1,"637":1,"639":1,"640":1,"647":1,"656":2,"658":3,"660":2,"666":1,"682":1,"700":1,"705":1,"714":2,"717":1,"748":1}}],["use",{"0":{"8":1,"9":1,"12":1,"109":1},"2":{"4":1,"5":3,"6":4,"8":1,"9":1,"12":1,"16":1,"17":1,"22":2,"28":1,"39":3,"40":1,"42":1,"46":1,"52":1,"63":1,"66":1,"67":1,"68":1,"69":1,"78":1,"82":1,"83":1,"85":1,"88":3,"90":3,"97":2,"100":1,"101":3,"104":3,"105":2,"109":2,"110":1,"114":1,"117":1,"128":1,"130":1,"131":1,"134":2,"136":1,"137":6,"138":2,"141":2,"143":1,"144":1,"146":1,"148":1,"153":1,"154":2,"165":2,"171":1,"172":2,"174":4,"175":7,"176":2,"181":1,"183":1,"185":2,"187":1,"197":2,"200":1,"202":2,"203":1,"210":1,"214":1,"217":4,"218":1,"219":2,"221":1,"231":2,"232":2,"233":1,"234":1,"238":2,"242":1,"246":2,"247":1,"248":2,"249":6,"250":1,"253":1,"258":3,"268":2,"272":4,"273":1,"280":1,"282":1,"627":1,"655":1,"656":2,"659":1,"661":1,"666":4,"672":1,"706":1,"741":1}}],["using",{"0":{"4":1,"20":1,"21":1,"249":1,"263":1,"268":1,"269":1},"2":{"6":2,"10":1,"13":1,"16":1,"19":1,"28":1,"36":1,"54":1,"56":1,"59":2,"65":3,"83":1,"88":1,"97":6,"100":1,"101":5,"107":1,"109":1,"110":1,"117":1,"120":2,"127":1,"134":2,"137":3,"150":2,"166":1,"170":1,"174":1,"175":1,"176":1,"188":1,"196":1,"198":1,"202":1,"208":1,"210":2,"217":2,"218":3,"219":2,"221":1,"226":1,"229":1,"233":1,"237":1,"238":1,"241":1,"244":5,"247":1,"249":3,"252":3,"253":5,"256":1,"259":1,"260":1,"263":2,"272":1,"283":1,"641":1,"650":1,"656":1}}],["lynn",{"2":{"238":2}}],["luckily",{"2":{"268":1}}],["luck",{"2":{"221":1}}],["lll",{"2":{"252":1}}],["ll",{"2":{"101":1,"103":1,"128":1,"137":2,"161":1,"164":1,"174":1,"203":1,"215":1}}],["lts",{"2":{"272":1}}],["lto",{"2":{"105":1}}],["lt",{"0":{"125":1,"126":2,"244":1,"299":1,"300":1,"301":1,"319":1,"320":1,"329":1,"330":1,"331":1,"334":1,"335":1,"405":1,"406":1,"407":1,"408":1,"411":2,"412":1,"413":1,"431":1,"433":1,"434":1,"435":1,"436":1,"437":1,"440":1,"441":1,"442":1,"443":1,"447":1,"454":2,"455":1,"456":1,"459":1,"460":1,"461":1,"462":1,"463":1,"464":1,"465":3,"466":2,"467":2,"468":1,"469":2,"470":2,"471":2,"472":1,"473":1,"474":1,"475":1,"476":1,"477":1,"478":1,"479":1,"480":1,"481":1,"482":1,"502":1,"503":1,"504":1,"505":1,"506":1,"507":1,"508":1,"510":1,"511":1,"512":1,"513":1,"514":1,"518":1,"519":1,"520":1,"529":1,"530":1,"532":1,"533":1,"534":1,"535":1,"536":1,"541":1,"542":1,"543":1,"544":1,"545":1,"557":1,"558":1,"559":1,"560":1,"561":1,"562":1,"563":1,"564":2,"565":2,"580":1,"581":1,"582":1,"583":1,"597":1,"598":1,"599":1,"600":1,"601":1,"602":1,"603":1,"607":1,"608":1,"609":2,"610":1,"611":1,"612":1,"613":1,"614":1,"615":1,"616":1,"617":1},"2":{"36":1,"40":2,"41":1,"67":1,"72":1,"76":1,"94":3,"98":4,"124":6,"125":2,"126":6,"141":1,"143":3,"162":1,"219":1,"244":1,"282":1,"289":2,"290":2,"291":1,"294":2,"304":1,"305":2,"306":1,"311":2,"312":1,"315":2,"319":1,"321":1,"322":2,"323":5,"325":3,"328":1,"332":3,"337":1,"342":4,"343":2,"344":1,"352":1,"353":1,"356":2,"390":1,"393":2,"399":1,"404":3,"405":5,"409":3,"410":1,"423":1,"424":1,"431":1,"432":1,"439":2,"444":2,"449":1,"450":1,"451":1,"454":2,"457":2,"458":1,"465":2,"466":1,"467":1,"469":1,"470":1,"471":1,"488":1,"492":1,"496":1,"499":1,"500":1,"501":1,"509":7,"515":5,"521":3,"522":1,"524":1,"528":1,"531":1,"537":5,"539":1,"540":2,"544":2,"545":2,"547":1,"549":1,"551":1,"564":1,"565":1,"568":1,"571":2,"572":5,"575":5,"576":1,"579":1,"584":2,"587":2,"590":2,"591":1,"593":1,"596":1,"604":7,"609":1,"619":1,"658":1,"666":2,"668":1,"669":1,"670":1,"671":1,"673":1,"674":1,"676":1,"679":1,"680":1,"681":1,"683":1,"684":1,"686":1,"687":1,"688":1,"689":1,"690":1,"696":1,"697":1,"700":1,"704":1,"705":1,"707":1,"710":1,"713":1,"741":1}}],["le=",{"2":{"735":12}}],["legitimacy",{"2":{"259":1}}],["leisure",{"2":{"158":1}}],["ledgers",{"0":{"627":1},"2":{"627":1}}],["ledger",{"2":{"146":1,"165":1,"233":1,"245":1,"247":1,"627":1}}],["lengthlimits",{"0":{"426":1},"2":{"485":2}}],["lengthy",{"2":{"253":1}}],["length",{"2":{"252":4,"299":1,"300":1,"301":1,"570":1}}],["len",{"2":{"143":1,"428":1}}],["left",{"2":{"125":1,"137":1,"265":3}}],["leftover",{"2":{"108":1}}],["levels",{"2":{"631":1}}],["level",{"0":{"153":1,"427":1},"2":{"104":1,"105":1,"120":1,"137":1,"143":1,"150":1,"152":1,"153":2,"175":1,"226":1,"267":1,"429":2,"656":1,"670":1,"723":2,"725":2}}],["less",{"2":{"97":1,"101":1,"234":1}}],["lesser",{"2":{"14":1}}],["lexicographically",{"2":{"65":1,"69":1}}],["leap",{"2":{"253":1}}],["leaving",{"2":{"248":1}}],["leaves",{"2":{"89":1}}],["leave",{"2":{"39":1,"78":1,"224":1,"248":1,"272":1}}],["leaks",{"2":{"250":1}}],["leaked",{"2":{"250":1,"268":1}}],["leaking",{"2":{"249":1}}],["leakage",{"2":{"247":1}}],["leak",{"2":{"246":1}}],["lead",{"2":{"245":1}}],["leader",{"0":{"654":1},"2":{"20":2,"21":2,"626":1,"652":1,"705":1}}],["learning",{"2":{"247":1,"260":1}}],["learn",{"0":{"168":1},"2":{"29":1,"42":1,"80":1,"98":1,"101":1,"120":1,"132":1,"134":1,"150":1,"151":1,"166":1,"167":1,"202":1,"208":1,"226":1,"227":1,"233":1,"238":4,"246":2,"247":1,"259":1,"665":1,"666":1,"667":1,"714":1,"735":1}}],["learned",{"2":{"13":1,"167":1,"230":1}}],["least",{"2":{"18":2,"20":1,"22":1,"62":2,"215":1,"256":1,"717":1,"728":1}}],["letters",{"2":{"252":2,"253":2}}],["lets",{"2":{"137":1,"200":1}}],["let",{"2":{"5":1,"37":1,"39":1,"40":1,"50":1,"52":6,"53":12,"60":3,"61":1,"66":1,"67":2,"71":1,"72":1,"88":1,"91":1,"92":3,"93":5,"94":1,"104":4,"105":2,"113":1,"137":3,"141":1,"152":1,"159":1,"175":2,"176":3,"181":1,"187":1,"188":1,"189":1,"190":3,"191":1,"210":1,"215":1,"217":1,"218":6,"219":5,"220":2,"221":3,"222":5,"223":1,"224":2,"251":1,"252":1,"253":2,"280":1,"655":1,"664":5,"666":1}}],["layers",{"2":{"262":1}}],["layout",{"2":{"239":1}}],["landscapes",{"2":{"260":1}}],["landscape",{"2":{"250":1}}],["lang=",{"2":{"181":5}}],["languages",{"2":{"166":1,"656":3}}],["language",{"2":{"27":1,"29":3,"40":1,"42":2,"43":1,"100":1,"101":4,"108":1,"156":1,"166":2,"181":1,"192":1,"211":1,"224":2,"227":1,"656":1,"666":1}}],["laptop",{"2":{"248":1}}],["lacks",{"2":{"211":1}}],["labelled",{"2":{"643":1}}],["labeled",{"2":{"238":1}}],["label>",{"2":{"181":1}}],["label",{"2":{"181":1}}],["laborious",{"2":{"95":1}}],["larger",{"2":{"154":1}}],["large",{"2":{"90":1,"137":1,"231":1,"270":1,"741":1}}],["largest",{"2":{"86":1}}],["launched",{"2":{"199":1}}],["launch",{"0":{"194":1,"196":1},"1":{"195":1,"196":1,"197":2},"2":{"19":1,"166":1,"194":1,"195":1,"265":1}}],["latin",{"2":{"238":1}}],["latest",{"2":{"185":3,"247":1,"248":1,"249":1,"272":1,"287":1}}],["late",{"2":{"88":2,"178":3,"221":1}}],["later",{"2":{"16":1,"78":1,"103":1,"104":1,"127":1,"175":1,"247":1,"253":1,"655":1,"728":1}}],["latter",{"2":{"16":1,"126":1,"219":2,"282":1}}],["last",{"2":{"12":4,"84":1,"88":1,"90":1,"185":1}}],["lazy",{"2":{"3":1}}],["literal",{"2":{"273":3}}],["literals",{"2":{"221":1,"273":1}}],["little",{"2":{"16":1,"90":1,"100":1,"174":1}}],["li",{"2":{"181":1}}],["li>uptime",{"2":{"181":1}}],["li>",{"2":{"181":3}}],["li>blocks",{"2":{"181":1}}],["lifeline",{"2":{"250":2}}],["life",{"2":{"163":1}}],["live",{"2":{"113":1,"122":2,"128":4,"143":1,"164":5,"187":2,"188":2,"189":3,"190":3,"191":2,"200":1,"202":1,"204":1,"575":1}}],["limitcheck",{"2":{"577":1}}],["limits",{"0":{"121":1,"428":1},"2":{"101":1,"121":1,"485":1,"552":2}}],["limitations",{"2":{"82":1}}],["limit",{"2":{"67":2,"151":1,"252":2,"529":1,"530":1}}],["limitedmetadata",{"2":{"439":1,"499":1}}],["limited",{"2":{"43":1,"141":1,"259":1,"660":1}}],["lightweight",{"2":{"39":1}}],["listed",{"2":{"244":1,"264":1}}],["listens",{"2":{"215":1}}],["listening",{"2":{"181":1,"196":2,"215":1,"224":1,"714":1}}],["listeners",{"2":{"646":1,"709":2}}],["listener",{"2":{"181":2,"196":1,"207":1,"215":2}}],["listenforblocksstream",{"2":{"175":1,"183":1}}],["listenforevents",{"2":{"175":1,"181":1}}],["listen",{"2":{"18":2,"175":3,"181":1,"183":1,"196":1,"207":2,"215":2,"224":1}}],["listof",{"2":{"186":2,"188":1,"190":1}}],["list",{"2":{"38":1,"40":1,"41":1,"58":1,"70":1,"99":1,"111":1,"120":1,"146":2,"150":1,"175":1,"181":1,"186":2,"187":1,"188":1,"200":1,"201":1,"202":1,"203":1,"204":1,"260":1,"282":1,"725":1,"738":1}}],["librewolf",{"2":{"249":1}}],["libraries",{"2":{"101":2,"110":1,"136":1,"146":1,"217":3,"226":1,"234":1}}],["library",{"2":{"6":1,"101":1,"107":1,"108":2,"110":1,"174":2,"176":1,"210":1,"217":1,"234":1,"241":2,"646":1,"655":3}}],["libssl",{"2":{"170":1}}],["lib",{"2":{"103":3,"104":1}}],["libcore",{"0":{"108":1},"2":{"108":1}}],["libc",{"2":{"6":1}}],["lingua",{"2":{"103":1}}],["lines",{"2":{"16":1,"20":1,"187":1,"188":1,"189":2,"191":1,"238":1}}],["line",{"2":{"16":2,"172":1,"181":1,"189":1,"200":1,"218":1,"224":1,"235":2,"242":1}}],["linux",{"2":{"6":3,"16":3,"20":1,"170":1,"243":1,"264":1,"282":1}}],["linked",{"2":{"76":1,"103":1,"107":1,"127":1,"234":1,"241":1}}],["linkages",{"0":{"236":1},"2":{"236":1}}],["linkage",{"2":{"6":1,"90":1,"103":1}}],["linking",{"0":{"234":1},"2":{"6":3,"234":1,"658":1}}],["links",{"2":{"5":1,"101":1,"217":1,"241":1,"259":1}}],["link",{"2":{"5":1,"105":1,"143":1,"229":1,"241":1,"242":1,"655":1}}],["likely",{"2":{"16":1,"99":2,"104":1,"175":1,"219":1,"247":1,"248":1,"252":1,"266":1}}],["like",{"2":{"5":1,"16":1,"17":1,"39":2,"42":2,"65":2,"66":1,"72":1,"74":2,"75":1,"92":1,"100":1,"101":1,"102":1,"103":2,"107":1,"117":1,"120":1,"128":1,"137":1,"143":1,"166":1,"174":1,"175":4,"176":1,"181":1,"201":1,"219":1,"221":2,"224":1,"234":1,"238":1,"241":1,"249":1,"252":1,"253":2,"256":1,"265":1,"270":1,"278":1,"283":1,"647":3,"656":1}}],["loss",{"2":{"250":1}}],["lose",{"2":{"248":1,"258":1}}],["loses",{"2":{"135":1}}],["losing",{"2":{"230":1,"250":1}}],["lost",{"2":{"6":1,"250":2,"749":2}}],["lot",{"2":{"106":2,"137":1,"175":1,"221":1}}],["lower",{"2":{"279":1,"280":1}}],["lowercase",{"2":{"252":1}}],["low",{"2":{"104":1,"175":1}}],["longhand",{"2":{"220":2}}],["long",{"2":{"100":1,"101":2,"151":1,"160":1,"187":1,"190":1,"253":1}}],["longer",{"2":{"14":1,"97":1,"106":1,"238":1}}],["loops",{"2":{"100":1}}],["loop",{"2":{"97":1,"196":9,"215":1,"224":2,"260":1}}],["lookalike",{"2":{"249":1}}],["looks",{"2":{"74":2,"92":1,"94":1,"100":1,"143":1,"219":1}}],["looking",{"0":{"639":1},"2":{"41":1,"88":1,"116":2,"128":2,"176":3,"177":2,"178":3,"187":3,"188":5,"189":12,"190":26,"191":37,"201":3,"202":4,"203":7,"204":5,"205":1,"206":1,"212":1,"213":2,"214":3,"217":1,"219":7,"220":3,"221":2,"222":1,"626":1}}],["look",{"2":{"18":1,"37":1,"50":1,"72":1,"83":1,"88":1,"94":1,"99":1,"103":1,"105":1,"113":1,"128":1,"137":1,"175":4,"185":1,"186":1,"215":1,"249":1,"272":1,"273":1,"278":1}}],["loads",{"2":{"211":1}}],["loading",{"2":{"196":1,"259":1}}],["loaded",{"2":{"112":1,"653":1}}],["load",{"2":{"67":1,"137":1,"218":2,"684":1}}],["locked",{"2":{"265":1}}],["lock",{"2":{"39":1,"174":1,"215":1,"248":1,"255":1}}],["localstorage",{"2":{"181":1}}],["localhost",{"2":{"18":2}}],["locally",{"2":{"17":1,"106":1,"196":1}}],["local",{"0":{"243":1,"244":1},"1":{"244":1},"2":{"2":1,"3":1,"196":1,"197":2,"217":4,"219":1,"243":2,"244":4,"283":1}}],["locations",{"2":{"3":1,"282":1}}],["location",{"0":{"280":1},"2":{"2":1,"137":1,"148":1,"155":2,"181":1,"218":2,"248":1,"250":1,"253":1,"258":1,"282":1}}],["located",{"2":{"0":1,"2":1,"130":1,"200":1}}],["logconsumer",{"2":{"186":1}}],["logging",{"2":{"153":1,"154":1,"231":1}}],["logged",{"2":{"153":1}}],["loggerfactory",{"2":{"186":1}}],["logger",{"0":{"152":1},"1":{"153":1,"154":1},"2":{"126":1,"143":1,"152":1,"181":2,"723":2,"725":2}}],["log",{"0":{"153":1,"154":1,"429":1},"2":{"152":2,"153":4,"154":5,"176":1,"180":3,"183":1,"187":1,"416":2,"420":1,"638":1}}],["logographic",{"2":{"238":1}}],["logo",{"2":{"128":4,"164":4,"176":1,"181":1,"200":3,"201":1,"304":1,"342":1,"450":1,"451":1}}],["login",{"2":{"113":1,"117":3,"164":1,"263":1}}],["logically",{"2":{"201":1}}],["logical",{"2":{"65":1,"647":1}}],["logic",{"0":{"36":1},"2":{"36":1,"39":1,"90":1,"97":1,"101":1,"104":1,"126":1,"233":3,"282":1,"637":1,"638":1}}],["logs",{"2":{"21":1,"143":1,"154":1,"272":2}}],["lorem",{"2":{"2":1,"4":4}}],["gpus",{"2":{"252":1,"253":2}}],["gpg",{"2":{"249":1,"262":1}}],["gnu",{"2":{"243":1}}],["gnu+linux",{"2":{"241":1}}],["ghosting",{"2":{"163":1}}],["gate",{"0":{"637":1},"2":{"626":1}}],["gateway",{"2":{"263":2,"714":1}}],["gathering",{"2":{"120":1,"150":1}}],["gathered",{"2":{"120":1,"150":1}}],["gain",{"2":{"260":1}}],["gained",{"2":{"230":1,"248":1}}],["gapped",{"2":{"248":1}}],["gave",{"2":{"177":1,"213":1,"220":1}}],["garden",{"2":{"128":4,"164":4,"187":2,"188":2,"189":3,"190":3,"191":2,"200":1,"202":1,"204":1}}],["gas",{"2":{"89":1}}],["gauge",{"2":{"12":5,"735":5}}],["guesses",{"2":{"268":1}}],["guessable",{"2":{"253":1}}],["gui",{"2":{"249":1}}],["guidelines",{"2":{"247":1,"260":1}}],["guides",{"2":{"27":1,"29":2,"40":1,"42":1,"43":1,"156":1,"169":1,"198":1,"227":1}}],["guide",{"0":{"173":1,"184":1,"209":1,"216":1},"1":{"174":1,"175":1,"176":1,"177":1,"178":1,"179":1,"180":1,"181":1,"182":1,"183":1,"185":1,"186":1,"187":1,"188":1,"189":1,"190":1,"191":1,"192":1,"193":1,"210":1,"211":1,"212":1,"213":1,"214":1,"215":1,"217":1,"218":1,"219":1,"220":1,"221":1,"222":1,"223":1,"224":1},"2":{"16":1,"29":1,"42":1,"109":1,"168":1,"170":1,"173":2,"174":1,"181":2,"217":1,"226":2,"265":2,"662":1,"714":3}}],["guarantees",{"2":{"726":1}}],["guarantee",{"2":{"247":1,"259":1,"726":1}}],["guaranteed",{"2":{"65":1,"230":1,"243":1,"656":1,"728":1,"753":1}}],["gradle",{"2":{"185":1}}],["grantexpr",{"2":{"664":1}}],["granted",{"2":{"44":1,"45":1,"56":4,"59":1,"60":1,"139":1,"160":1,"161":1,"263":1,"654":1,"672":1,"674":1}}],["granting",{"2":{"59":1,"71":1,"160":1}}],["grantbox",{"0":{"409":1},"2":{"53":1,"61":1,"71":1,"416":1}}],["grants",{"2":{"53":1,"57":3,"249":1}}],["grant",{"0":{"45":1,"61":1,"160":1,"406":1,"407":1,"408":1},"2":{"40":1,"41":3,"45":3,"53":6,"56":1,"59":1,"61":4,"71":4,"128":1,"129":1,"160":2,"164":1,"409":3,"416":1,"420":1,"661":1,"663":2,"664":1}}],["gruelling",{"2":{"97":1}}],["grow",{"2":{"252":1}}],["grows",{"2":{"82":1}}],["grouped",{"2":{"201":1}}],["groups",{"0":{"59":1},"1":{"60":1,"61":1},"2":{"662":1}}],["group",{"2":{"45":1,"174":1,"185":1,"201":1,"750":1}}],["greater",{"2":{"98":1,"201":1}}],["great",{"2":{"42":1,"136":1,"174":1,"175":1,"230":1,"231":1,"666":1}}],["greeted",{"2":{"18":1,"21":1}}],["glossary",{"0":{"626":1},"1":{"627":1,"628":1,"629":1,"630":1,"631":1,"632":1,"633":1,"634":1,"635":1,"636":1,"637":1,"638":1,"639":1,"640":1,"641":1,"642":1,"643":1,"644":1,"645":1,"646":1,"647":1,"648":1,"649":1,"650":1,"651":1,"652":1,"653":1,"654":1}}],["globally",{"2":{"175":1,"656":1,"676":1}}],["global",{"2":{"98":1,"111":1,"137":1,"217":1,"243":1,"668":1,"669":1}}],["glue",{"2":{"137":1}}],["glued",{"2":{"39":1}}],["glass",{"0":{"639":1},"2":{"116":2,"128":2,"176":3,"177":2,"178":3,"187":3,"188":5,"189":12,"190":26,"191":37,"201":3,"202":4,"203":7,"204":5,"205":1,"206":1,"212":1,"213":2,"214":3,"219":7,"220":3,"221":2,"222":1,"626":1}}],["glibc",{"2":{"6":1}}],["gil",{"2":{"215":1}}],["giving",{"2":{"88":1,"248":1,"261":1}}],["give",{"2":{"40":2,"42":1,"120":2,"137":1,"150":2,"177":1,"185":1,"213":1,"220":1,"221":1,"249":1,"661":2,"663":1,"664":2}}],["given",{"2":{"18":2,"49":3,"62":1,"83":2,"135":1,"137":1,"178":1,"183":1,"200":1,"218":1,"233":1,"272":1,"273":3,"656":1,"658":2,"670":1,"671":1,"677":1,"678":2,"679":1,"681":1,"686":1,"687":1,"688":1,"689":1,"690":1,"691":1,"692":2,"693":2,"694":1,"701":1,"702":2,"711":1,"712":1,"713":1}}],["git",{"2":{"5":2,"16":10,"17":4,"22":1,"103":1,"170":1,"171":6,"172":4,"174":2,"185":1,"196":2,"210":3,"217":6,"272":1}}],["github",{"0":{"171":1},"1":{"172":1},"2":{"5":1,"12":1,"103":1,"166":1,"171":2,"172":2,"174":1,"185":4,"210":3,"217":1,"219":1,"270":2,"714":1,"725":1,"749":1}}],["githubusercontent",{"2":{"2":1,"5":3}}],["google",{"2":{"249":6,"259":1}}],["goods",{"2":{"137":1,"630":1}}],["good™",{"2":{"28":3}}],["good",{"2":{"16":1,"28":1,"94":1,"161":1,"644":1}}],["gold",{"2":{"165":1}}],["gossip",{"2":{"143":4}}],["gotten",{"2":{"91":1}}],["got",{"2":{"84":1,"86":2,"88":3,"92":1,"97":3,"183":1,"214":1,"219":1,"221":1,"282":1}}],["gone",{"2":{"84":1}}],["go",{"2":{"67":1,"81":1,"110":1,"116":1,"127":1,"128":1,"141":2,"143":1,"162":1,"217":1,"228":1,"265":1,"278":1}}],["goes",{"2":{"20":1,"21":1,"126":1,"258":1,"285":1,"286":1,"658":1}}],["going",{"2":{"13":3,"18":1,"88":1,"104":1,"110":1,"175":1,"214":1,"221":1}}],["gt",{"0":{"125":1,"126":2,"244":1,"299":1,"300":1,"301":1,"319":1,"320":1,"329":1,"330":1,"331":1,"334":1,"335":1,"405":1,"406":1,"407":1,"408":1,"411":2,"412":1,"413":1,"431":1,"433":1,"434":1,"435":1,"436":1,"437":1,"440":1,"441":1,"442":1,"443":1,"447":1,"454":2,"455":1,"456":1,"459":1,"460":1,"461":1,"462":1,"463":1,"464":1,"465":3,"466":2,"467":2,"468":1,"469":2,"470":2,"471":2,"472":1,"473":1,"474":1,"475":1,"476":1,"477":1,"478":1,"479":1,"480":1,"481":1,"482":1,"502":1,"503":1,"504":1,"505":1,"506":1,"507":1,"508":1,"510":1,"511":1,"512":1,"513":1,"514":1,"518":1,"519":1,"520":1,"529":1,"530":1,"532":1,"533":1,"534":1,"535":1,"536":1,"541":1,"542":1,"543":1,"544":1,"545":1,"557":1,"558":1,"559":1,"560":1,"561":1,"562":1,"563":1,"564":2,"565":2,"580":1,"581":1,"582":1,"583":1,"597":1,"598":1,"599":1,"600":1,"601":1,"602":1,"603":1,"607":1,"608":1,"609":2,"610":1,"611":1,"612":1,"613":1,"614":1,"615":1,"616":1,"617":1},"2":{"11":1,"12":1,"36":1,"40":2,"41":1,"67":1,"72":1,"76":1,"94":2,"98":4,"124":6,"125":2,"126":6,"132":1,"141":1,"143":3,"162":1,"168":1,"219":1,"238":1,"244":1,"265":3,"282":1,"289":2,"290":2,"291":1,"294":2,"304":1,"305":2,"306":1,"311":2,"312":1,"315":2,"319":1,"321":1,"322":2,"323":5,"325":3,"328":1,"332":3,"337":1,"342":4,"343":2,"344":1,"352":1,"353":1,"356":2,"390":1,"393":2,"399":1,"404":3,"405":5,"409":3,"410":1,"423":1,"424":1,"431":1,"432":1,"439":2,"444":2,"449":1,"450":1,"451":1,"454":2,"457":2,"458":1,"465":2,"466":1,"467":1,"469":1,"470":1,"471":1,"488":1,"492":1,"496":1,"499":1,"500":1,"501":1,"509":7,"515":5,"521":3,"522":1,"524":1,"528":1,"531":1,"537":5,"539":1,"540":2,"544":2,"545":2,"547":1,"549":1,"551":1,"564":1,"565":1,"568":1,"571":2,"572":5,"575":5,"576":1,"579":1,"584":2,"587":2,"590":2,"591":1,"593":1,"596":1,"604":7,"609":1,"619":1,"658":1,"666":2,"668":1,"669":1,"670":1,"671":1,"673":1,"674":1,"676":1,"679":1,"680":1,"681":1,"683":1,"684":1,"686":1,"687":1,"688":1,"689":1,"690":1,"696":1,"697":1,"700":1,"704":1,"705":1,"707":1,"710":1,"713":1,"725":1,"741":1}}],["g",{"2":{"9":1,"21":1,"31":1,"38":1,"39":1,"42":1,"56":1,"65":1,"81":1,"88":3,"108":1,"166":1,"174":1,"181":1,"215":1,"219":1,"238":2,"247":5,"249":1,"250":1,"256":1,"259":1,"273":2,"663":1,"666":1,"683":1,"728":1}}],["gear",{"2":{"265":1}}],["geforce",{"2":{"253":2}}],["genericpredicatebox",{"0":{"405":1,"454":1,"609":1},"2":{"405":3,"454":1,"501":1,"609":1}}],["genericvaluepredicatebox",{"2":{"187":2,"188":1,"189":1}}],["generic",{"2":{"137":1,"659":1}}],["generator",{"2":{"202":1,"639":1}}],["generating",{"0":{"237":1,"238":1},"1":{"238":1,"239":2,"240":1,"241":1,"242":1,"243":1,"244":1},"2":{"134":3,"202":2,"237":1,"246":1,"256":1,"273":1,"657":1}}],["generation",{"0":{"114":1,"129":1,"144":1,"658":1},"1":{"130":1,"659":1},"2":{"105":1,"175":1,"207":1,"238":3,"269":1,"658":1}}],["generatekeypair",{"2":{"186":2,"188":1,"190":1}}],["generates",{"2":{"172":1,"656":1}}],["generated",{"2":{"87":1,"97":1,"134":2,"177":1,"186":1,"187":10,"188":1,"192":4,"193":11,"202":2,"213":1,"220":1,"238":2,"658":1,"659":1}}],["generate",{"0":{"130":1,"134":1},"2":{"22":1,"53":1,"103":1,"114":1,"128":1,"130":4,"134":3,"141":1,"144":1,"167":1,"177":2,"202":2,"213":2,"218":1,"220":2,"229":1,"237":1,"238":3,"246":1,"252":1,"286":1,"639":1,"656":2,"657":1,"658":2}}],["generally",{"2":{"249":1,"252":1}}],["generalised",{"2":{"97":1}}],["general",{"0":{"258":1,"664":1},"2":{"18":1,"42":1,"160":1,"662":1}}],["genesis",{"0":{"7":1,"128":1,"130":1,"136":1,"151":1,"272":1},"1":{"129":1,"130":1,"131":1},"2":{"6":1,"7":2,"8":1,"13":1,"16":4,"18":6,"20":1,"21":6,"24":1,"42":2,"53":1,"126":3,"128":20,"129":1,"130":10,"131":2,"132":2,"135":2,"136":2,"138":1,"141":3,"143":2,"151":11,"164":6,"167":1,"178":3,"186":4,"187":2,"188":3,"189":3,"190":3,"191":3,"196":1,"200":4,"202":1,"214":1,"221":1,"272":8,"628":1,"633":1,"639":1,"663":4,"717":2,"735":5,"749":1}}],["getu32",{"2":{"193":1}}],["getvalue",{"2":{"193":1}}],["getassets",{"2":{"193":1}}],["getaccountamount",{"2":{"190":4,"191":1}}],["getid",{"2":{"193":2}}],["gettxtimeout",{"2":{"193":10}}],["getempty",{"2":{"186":1}}],["getlogger",{"2":{"186":2}}],["getproperties",{"2":{"185":1}}],["getstring",{"2":{"193":4}}],["getstatus",{"2":{"181":1}}],["getseconds",{"2":{"193":10}}],["gets",{"2":{"28":1,"89":1,"94":1,"98":2,"100":1,"157":1,"215":2,"666":3,"692":1,"693":1,"698":1,"701":1}}],["get",{"0":{"166":1},"2":{"3":3,"5":2,"6":1,"13":1,"28":2,"39":1,"43":1,"54":1,"67":1,"88":3,"89":1,"90":1,"92":1,"96":1,"97":5,"103":2,"104":1,"105":1,"120":2,"137":1,"150":2,"153":1,"170":1,"171":1,"172":1,"185":1,"187":1,"191":1,"193":15,"207":1,"213":1,"217":1,"220":1,"224":1,"225":1,"234":1,"258":1,"270":1,"273":1,"280":1,"659":2,"715":1,"716":1,"721":1,"722":1,"725":1,"731":1,"732":1,"734":1,"736":1,"737":1,"740":1,"744":1,"745":1,"747":1,"748":1}}],["circumvent",{"2":{"243":1}}],["circumstances",{"2":{"163":1,"256":1}}],["cyrillic",{"2":{"238":1}}],["csd",{"0":{"236":1},"2":{"236":1}}],["cfg",{"2":{"211":2}}],["centralized",{"2":{"229":1}}],["centric",{"2":{"141":1}}],["certain",{"2":{"31":1,"38":1,"39":1,"40":1,"41":1,"49":1,"62":2,"72":1,"82":1,"87":1,"97":1,"98":2,"148":1,"238":1,"252":1,"634":1,"661":1,"714":1}}],["c",{"2":{"103":3,"200":1,"238":1,"239":1,"241":1,"656":2,"658":2}}],["cross",{"2":{"658":2}}],["crucial",{"2":{"237":1}}],["critical",{"2":{"234":2,"249":1,"260":1}}],["criteria",{"2":{"138":1}}],["craft",{"2":{"253":1}}],["crafted",{"2":{"231":1}}],["cracking",{"2":{"252":1,"253":1}}],["crack",{"2":{"252":1,"253":5}}],["crashing",{"2":{"230":1}}],["crash",{"2":{"230":1}}],["crate",{"2":{"103":4,"104":1,"108":1,"136":1,"217":4,"656":2,"658":1}}],["crates",{"2":{"102":1,"107":1,"217":3}}],["cryotpgraphic",{"2":{"172":1}}],["cryptotypes",{"2":{"175":2}}],["cryptography",{"0":{"254":1},"1":{"255":1,"256":1},"2":{"115":1,"132":1,"145":1,"151":1,"174":1,"229":1,"246":2,"248":1,"254":2,"255":1,"256":1}}],["cryptographic",{"0":{"237":1,"238":1,"261":1,"262":1,"267":1},"1":{"238":1,"239":2,"240":1,"241":1,"242":1,"243":1,"244":1,"262":1,"263":2,"264":2,"265":2,"266":2,"267":1,"268":2,"269":2},"2":{"115":2,"132":2,"134":5,"145":2,"151":1,"167":1,"174":1,"202":4,"217":1,"237":1,"238":5,"246":4,"248":1,"250":1,"254":1,"261":2,"262":3,"263":1,"266":3,"267":1,"268":1,"639":1}}],["crypto",{"2":{"5":3,"22":1,"134":1,"174":17,"175":4,"181":10,"185":1,"187":1,"192":1,"202":1,"217":3,"238":2,"239":7}}],["credentials",{"0":{"117":1},"2":{"117":3,"203":1,"263":1}}],["creator",{"2":{"181":1}}],["creation",{"2":{"177":1,"207":3,"213":1,"214":1,"220":1,"575":1,"658":1,"663":1,"728":1,"735":1,"749":1}}],["creating",{"2":{"71":1,"90":1,"136":1,"174":1,"185":1,"196":1,"212":1,"217":1,"246":1,"250":1,"265":2}}],["createapp",{"2":{"181":2}}],["creates",{"2":{"154":1,"192":1,"221":1}}],["createdomain",{"2":{"181":5}}],["created",{"2":{"31":1,"66":1,"97":1,"137":1,"171":1,"174":1,"176":2,"187":3,"188":3,"189":6,"190":8,"191":6,"196":9,"201":1,"202":1,"203":3,"217":1,"255":1,"265":1,"290":1,"292":1,"305":1,"307":1,"311":1,"313":1,"336":1,"338":1,"343":1,"345":1,"523":1,"525":1,"590":1,"592":1,"663":1,"664":3}}],["create",{"0":{"66":1,"95":1,"96":1,"103":1},"2":{"17":1,"21":1,"40":2,"47":1,"68":1,"78":1,"88":1,"90":1,"94":1,"95":2,"96":1,"97":1,"98":1,"103":1,"123":1,"128":1,"135":1,"137":1,"143":2,"165":2,"171":3,"175":2,"176":1,"177":3,"178":2,"181":1,"185":1,"187":1,"190":1,"199":1,"210":1,"213":1,"215":1,"217":2,"218":2,"219":6,"220":5,"221":3,"222":1,"223":1,"224":1,"237":1,"249":1,"254":1,"265":1,"268":1,"270":1,"656":1,"661":2,"663":1,"664":2,"705":1}}],["cdylib",{"2":{"103":2}}],["cd",{"2":{"16":3,"171":1,"196":1,"210":2}}],["cheap",{"2":{"666":1}}],["checkout",{"2":{"272":1}}],["checkboxes",{"2":{"265":1}}],["checkbox",{"2":{"265":1}}],["checks",{"2":{"192":1,"260":1}}],["checker",{"2":{"181":1}}],["checked",{"2":{"57":1,"62":2,"214":1,"271":1}}],["checking",{"2":{"62":1}}],["check",{"0":{"279":1,"280":1,"281":1,"282":1,"286":1},"2":{"13":1,"21":1,"36":1,"41":1,"42":1,"51":1,"62":1,"63":1,"70":1,"71":1,"82":1,"83":1,"161":1,"170":1,"174":2,"177":1,"185":1,"189":1,"190":1,"200":1,"203":1,"213":1,"218":1,"220":2,"221":1,"244":1,"272":3,"283":2,"285":2,"286":2,"289":1,"627":1,"656":1,"663":1}}],["chromium",{"2":{"249":5}}],["chrome",{"2":{"249":2}}],["chunks",{"2":{"231":1}}],["chooses",{"2":{"234":1,"238":1}}],["choose",{"2":{"210":1,"246":1,"249":1,"265":1}}],["choosing",{"0":{"137":1},"2":{"28":1,"101":1,"137":1}}],["choice",{"2":{"89":1,"249":1}}],["chose",{"2":{"79":1,"215":1,"664":1}}],["chosen",{"2":{"28":1,"103":1,"238":1}}],["challenge",{"2":{"263":2,"268":1}}],["challenges",{"2":{"250":1,"260":1}}],["chatting",{"2":{"162":1}}],["charts",{"2":{"286":1}}],["charge",{"2":{"118":1,"147":1,"714":1}}],["character",{"2":{"220":1,"221":1,"252":6,"253":4}}],["characteristics",{"2":{"81":1,"178":1,"189":1,"214":1,"221":1,"631":1}}],["characters",{"2":{"74":1,"134":1,"238":4,"249":2,"252":3,"273":1,"660":3}}],["chance",{"2":{"246":1}}],["changing",{"2":{"72":1,"260":1}}],["changed",{"2":{"28":1,"203":1,"272":1,"336":1,"338":1}}],["change",{"0":{"652":1},"2":{"21":1,"28":2,"33":1,"47":1,"57":1,"99":1,"108":1,"120":1,"135":2,"137":2,"148":3,"150":1,"155":1,"200":1,"203":1,"207":3,"233":1,"323":1,"626":1,"633":1,"654":1,"663":1}}],["changes",{"2":{"6":1,"8":1,"9":1,"28":2,"94":1,"99":1,"229":1,"265":1,"649":1,"705":1,"735":4,"749":3,"750":1}}],["channels",{"2":{"270":2}}],["channel",{"2":{"18":1,"202":1,"250":1}}],["chapter",{"2":{"13":1,"25":1,"29":1,"58":1,"99":1,"160":1,"662":1,"672":1}}],["chainid",{"0":{"333":1},"2":{"575":1}}],["chain=00000000",{"2":{"196":1}}],["chain",{"2":{"12":1,"36":1,"39":1,"40":1,"47":1,"63":2,"88":1,"101":1,"106":2,"111":1,"113":1,"143":2,"164":1,"233":1,"575":1,"661":1}}],["culture",{"2":{"260":1}}],["cultivate",{"2":{"260":1}}],["cut",{"2":{"230":1,"256":1}}],["cumbersome",{"2":{"97":1,"214":1,"241":1}}],["cup",{"2":{"92":2,"93":1,"97":2}}],["cursor",{"2":{"320":1,"404":1,"740":2,"741":2}}],["curve",{"2":{"238":1}}],["curious",{"2":{"226":1}}],["curated",{"2":{"146":1}}],["currencies",{"2":{"165":1}}],["currency",{"2":{"39":1,"630":1}}],["currenttimemillis",{"2":{"187":1,"188":1,"189":1,"190":1}}],["currentlistener",{"2":{"181":6}}],["currently",{"2":{"42":1,"63":1,"82":1,"104":1,"112":1,"136":1,"181":1,"187":1,"192":1,"217":1,"224":1,"256":1,"270":1,"653":1,"660":1,"710":1,"725":2,"728":1,"735":1}}],["current",{"2":{"6":1,"39":1,"65":1,"87":1,"88":1,"94":1,"97":1,"112":2,"166":1,"176":1,"181":1,"183":1,"200":1,"214":1,"228":1,"272":1,"640":1,"653":2,"717":1,"733":1,"735":2,"749":1}}],["curl",{"2":{"12":1}}],["customized",{"2":{"203":1}}],["customize",{"2":{"202":1}}],["customizable",{"2":{"134":1,"197":1}}],["custom",{"0":{"8":1,"9":1,"650":1},"2":{"6":2,"7":1,"8":1,"9":1,"62":1,"103":1,"128":1,"155":1,"165":1,"626":1,"645":1,"647":1}}],["cp",{"2":{"6":1,"17":2,"199":1,"210":1,"217":1}}],["cluster",{"2":{"253":1}}],["clues",{"2":{"253":1}}],["cl",{"2":{"211":1,"212":1,"213":1,"214":1,"215":1}}],["clarity",{"2":{"264":1}}],["classes",{"2":{"186":1,"187":1}}],["class=",{"2":{"181":1}}],["classic",{"2":{"175":1,"253":1}}],["class",{"2":{"175":1,"186":2,"187":4,"188":2,"189":4,"190":2,"191":1,"193":8}}],["claim",{"2":{"141":1}}],["clear",{"2":{"137":1,"249":2,"250":2,"260":1,"287":1}}],["clean",{"2":{"5":1}}],["closed",{"2":{"148":1,"264":1,"265":1,"266":1}}],["closer",{"2":{"19":1,"50":1,"72":1,"105":1}}],["clock",{"2":{"88":1}}],["cloned",{"2":{"658":1}}],["clone",{"0":{"171":1},"1":{"172":1},"2":{"53":9,"92":12,"93":5,"94":2,"166":1,"171":2,"174":2,"185":1,"210":2,"218":1,"221":1,"659":6}}],["clinic",{"2":{"137":1}}],["cli",{"0":{"198":1,"199":1,"200":1},"1":{"199":1,"200":1,"201":1,"202":1,"203":1,"204":1,"205":1,"206":1,"207":1,"208":1},"2":{"22":1,"27":1,"29":1,"42":1,"43":2,"44":1,"164":1,"166":1,"172":1,"196":1,"198":1,"199":1,"200":2,"238":1,"714":1}}],["click=",{"2":{"181":2}}],["click",{"2":{"5":1}}],["clients",{"2":{"249":2,"256":1,"650":1}}],["clientconfiguration",{"2":{"218":4}}],["client",{"0":{"113":1,"174":1,"175":1,"185":1,"199":1,"200":1,"210":1,"217":1,"256":1},"1":{"114":1,"115":1,"116":1,"117":1,"118":1,"119":1,"120":1,"121":1,"122":1,"123":1},"2":{"5":6,"14":1,"18":1,"39":1,"53":8,"67":2,"97":1,"101":1,"113":2,"114":3,"115":2,"117":1,"118":1,"132":2,"136":4,"141":1,"146":1,"148":1,"164":3,"166":1,"167":1,"173":1,"174":5,"175":18,"176":7,"180":7,"181":21,"183":3,"185":2,"187":9,"188":2,"189":3,"190":2,"191":1,"193":15,"196":1,"198":1,"199":3,"200":11,"203":3,"210":2,"211":3,"215":1,"217":10,"218":10,"219":8,"220":2,"221":3,"222":1,"223":1,"224":1,"226":1,"249":1,"256":2,"259":2,"273":1,"283":1,"628":1,"643":1,"664":1,"714":3,"719":1,"720":1,"728":1,"729":1,"730":1,"738":1}}],["c4af68c4f7959b154eb5380aa93c894e2e63fe4e",{"2":{"5":1,"173":1}}],["caveats",{"2":{"642":1}}],["calculations",{"2":{"253":1}}],["calculate",{"2":{"252":1}}],["callable",{"2":{"658":1}}],["calltrigger",{"2":{"90":1}}],["call",{"0":{"90":1},"2":{"39":1,"67":1,"85":1,"210":1,"273":1,"656":1}}],["called",{"2":{"3":1,"28":1,"40":1,"52":1,"59":1,"100":1,"138":1,"154":1,"175":2,"188":1,"214":1,"230":1,"683":1,"709":1}}],["calling",{"2":{"3":2,"17":1,"176":1,"273":1,"656":1}}],["cache",{"2":{"249":1}}],["cacti",{"2":{"236":1}}],["cactus",{"2":{"236":1}}],["causing",{"2":{"705":1}}],["cause",{"2":{"97":1,"126":1,"137":1,"272":1,"656":1,"658":1}}],["caused",{"2":{"32":1,"97":1,"106":1,"204":1,"644":1}}],["cautious",{"2":{"249":1,"261":1}}],["caution",{"2":{"249":1,"259":1}}],["casually",{"2":{"226":1}}],["cast",{"2":{"190":1}}],["cases",{"2":{"42":1,"62":2,"137":4,"138":1,"141":1,"247":1,"656":1,"672":1}}],["case",{"2":{"28":1,"46":1,"69":1,"90":1,"94":1,"104":1,"106":1,"116":1,"128":1,"137":1,"141":2,"148":1,"154":1,"174":1,"181":3,"214":1,"232":1,"250":1,"253":1,"256":1,"268":2,"280":1,"652":1,"703":1}}],["catering",{"2":{"267":1}}],["category",{"2":{"86":1,"137":1,"663":1}}],["catch",{"2":{"137":1,"273":1}}],["cabbage",{"2":{"128":2,"164":2,"189":1,"190":1,"204":1}}],["captured",{"2":{"709":1}}],["capturing",{"2":{"125":1}}],["capabilities",{"2":{"628":1}}],["capable",{"2":{"241":1,"253":1,"634":1}}],["capacity",{"2":{"18":1,"143":2,"428":1}}],["carry",{"2":{"658":1}}],["carpenter",{"2":{"128":1,"164":1,"188":1,"189":1,"190":1,"191":1}}],["careful",{"2":{"259":1}}],["carefully",{"2":{"45":1}}],["care",{"2":{"100":1,"101":1,"103":1,"174":1,"178":1,"231":1,"666":1}}],["cargo",{"2":{"6":1,"22":2,"103":2,"104":1,"105":1,"108":1,"134":1,"172":2,"217":1,"231":1,"238":1,"239":4,"241":1,"279":3,"280":1,"282":4}}],["cantransferuserasset",{"2":{"663":1}}],["cantransferassetswithdefinition",{"2":{"663":1}}],["canburnuserasset",{"2":{"663":1}}],["canburnuserpublickeys",{"2":{"663":1}}],["canburnassetswithdefinition",{"2":{"663":1}}],["canmintassetswithdefinition",{"2":{"663":1,"664":1}}],["canmintusersignaturecheckconditions",{"2":{"663":1}}],["canmintuserpublickeys",{"2":{"663":1}}],["canregisterassetswithdefinition",{"2":{"663":1}}],["canremovekeyvalueinassetdefinition",{"2":{"663":1}}],["canremovekeyvalueinaccount",{"2":{"128":1,"164":1}}],["canremovekeyvalueinuserasset",{"2":{"663":1}}],["canremovekeyvalueinuseraccount",{"2":{"663":1}}],["canremovekeyvalueinusermetadata",{"2":{"53":1,"60":1}}],["canremovekeyvalueindomain",{"2":{"663":1}}],["canunregisteruserasset",{"2":{"663":1}}],["canunregisterassetdefinition",{"2":{"663":1}}],["canunregisterassetswithdefinition",{"2":{"663":1}}],["canunregisteraccount",{"2":{"663":1}}],["canunregisterdomain",{"2":{"663":1}}],["cansetkeyvalueinassetdefinition",{"2":{"663":1}}],["cansetkeyvalueinaccount",{"2":{"128":1,"164":1}}],["cansetkeyvalueinuserasset",{"2":{"663":1}}],["cansetkeyvalueinuseraccount",{"2":{"663":1}}],["cansetkeyvalueinusermetadata",{"2":{"53":1,"60":1}}],["cansetkeyvalueindomain",{"2":{"663":1}}],["cansetparameters",{"2":{"128":1,"164":1}}],["cannot",{"2":{"18":1,"28":2,"97":1,"135":1,"137":1,"162":1,"178":2,"203":1,"221":1,"249":2,"259":1,"266":1,"272":1,"273":2,"631":1,"656":1,"663":1}}],["can",{"2":{"5":1,"10":2,"12":2,"13":2,"16":5,"18":3,"21":1,"24":4,"25":1,"27":1,"29":1,"32":1,"36":5,"37":1,"38":1,"40":1,"41":3,"42":7,"43":4,"44":1,"45":1,"47":1,"50":3,"52":1,"54":1,"56":2,"58":1,"59":1,"61":1,"62":1,"64":1,"65":3,"67":2,"68":1,"69":2,"71":1,"72":3,"78":2,"80":2,"82":2,"83":1,"84":2,"88":3,"89":1,"90":3,"91":1,"94":2,"95":1,"97":3,"98":2,"99":1,"101":3,"105":2,"107":1,"108":1,"109":1,"110":2,"114":1,"118":1,"120":1,"121":1,"124":1,"125":2,"126":1,"127":1,"128":2,"129":2,"130":1,"131":1,"134":2,"137":8,"138":2,"140":1,"141":3,"143":2,"144":1,"146":2,"148":1,"151":2,"154":3,"155":1,"161":1,"164":1,"165":1,"171":1,"174":3,"175":6,"176":2,"177":2,"178":1,"179":1,"181":2,"183":1,"185":2,"186":1,"187":1,"188":2,"192":1,"196":2,"198":1,"200":1,"202":2,"203":3,"204":1,"205":1,"207":1,"208":1,"210":1,"211":2,"213":1,"214":2,"217":1,"220":2,"221":6,"222":1,"224":1,"228":1,"230":4,"232":1,"233":1,"234":1,"237":1,"238":4,"241":1,"243":1,"245":1,"246":3,"248":1,"249":3,"250":1,"252":2,"253":3,"254":1,"255":2,"256":1,"258":1,"259":1,"263":1,"264":2,"266":2,"268":2,"269":1,"270":1,"272":2,"273":2,"278":1,"279":1,"281":1,"283":1,"626":1,"627":1,"628":4,"630":2,"631":1,"632":1,"639":1,"644":1,"646":1,"650":1,"654":1,"656":3,"658":4,"660":1,"663":2,"664":3,"665":2,"666":3,"667":1,"691":1,"709":1,"725":1,"728":1,"748":1}}],["coins",{"2":{"630":1}}],["coolasset",{"2":{"664":1}}],["cooperation",{"2":{"257":1}}],["cookies",{"2":{"249":2}}],["coding",{"2":{"225":1}}],["code>",{"2":{"181":2}}],["codegen",{"2":{"105":1}}],["codecs",{"2":{"174":1}}],["codec",{"2":{"94":1,"103":1,"231":1,"714":2}}],["code",{"0":{"0":1,"231":1},"1":{"1":1,"2":1,"3":1,"4":1,"5":1},"2":{"0":1,"2":1,"3":1,"4":3,"5":1,"20":1,"79":1,"92":1,"97":2,"99":1,"103":1,"104":1,"105":1,"108":1,"124":1,"137":2,"141":1,"143":1,"176":1,"181":1,"185":1,"187":2,"189":3,"192":1,"197":2,"202":1,"212":2,"215":1,"217":1,"219":3,"231":5,"249":1,"272":1,"650":1,"656":1,"658":1,"666":1,"717":1,"723":1,"726":1,"733":1,"735":1,"738":1,"741":1,"746":1,"749":1,"753":1}}],["co",{"2":{"185":1,"186":8,"187":12,"192":4,"193":20,"231":1}}],["cost",{"2":{"137":1,"219":1}}],["copies",{"2":{"258":1}}],["copied",{"2":{"135":1,"200":2,"249":1}}],["copying",{"2":{"17":1,"154":1,"272":1}}],["copy",{"2":{"6":1,"8":1,"16":3,"17":2,"20":1,"137":2,"177":1,"185":2,"199":1,"213":1,"217":3,"220":1,"238":1,"253":1,"272":1}}],["corda",{"2":{"236":1}}],["coroutines",{"2":{"185":2,"187":3}}],["corner",{"2":{"175":1}}],["core",{"0":{"648":1},"2":{"108":1,"167":1,"174":2,"175":1,"181":3,"185":2,"196":15,"217":1,"218":1,"246":1,"270":1,"626":1,"641":1,"650":1}}],["correctness",{"2":{"658":1}}],["correct",{"2":{"137":1,"157":1,"221":1,"263":1,"273":2}}],["correctly",{"2":{"18":1,"187":1,"192":1}}],["corresponding",{"2":{"29":1,"94":1,"125":1,"127":1,"143":1,"212":1,"255":1,"268":1,"658":1,"677":1,"692":1,"693":1,"701":1,"702":1,"709":1,"712":1}}],["correspond",{"2":{"20":1,"21":1}}],["corruption",{"2":{"6":1}}],["coverage",{"2":{"235":2}}],["covering",{"2":{"175":1}}],["covers",{"2":{"167":1}}],["covered",{"2":{"166":1}}],["cover",{"2":{"28":1,"46":1,"85":1,"110":1,"141":1,"152":1,"174":1,"185":1,"217":1}}],["cousins",{"2":{"221":1}}],["course",{"2":{"81":1,"90":1,"218":1,"282":1,"656":1}}],["counter",{"2":{"212":1,"258":1,"735":2}}],["counterpart",{"2":{"176":1}}],["counterparts",{"2":{"21":1}}],["count=0",{"2":{"196":1}}],["count",{"2":{"57":1,"84":1,"151":1,"735":1}}],["couple",{"2":{"40":1,"213":1}}],["couldn",{"2":{"219":1}}],["could",{"2":{"2":1,"5":1,"16":1,"17":1,"19":1,"21":1,"36":2,"62":2,"88":2,"89":1,"97":2,"109":1,"136":1,"137":1,"141":2,"153":1,"160":1,"171":1,"174":1,"175":1,"178":2,"203":1,"211":1,"214":1,"217":2,"218":1,"219":1,"230":1,"256":1,"268":1,"282":2,"656":1}}],["column",{"2":{"287":2}}],["color",{"2":{"52":2}}],["colons",{"2":{"18":1}}],["collected",{"2":{"666":1}}],["collection",{"2":{"39":1,"71":1,"247":1,"666":2,"680":1}}],["collaboration",{"2":{"236":1}}],["collisions",{"2":{"18":1}}],["conflate",{"2":{"703":1}}],["conforms",{"2":{"658":1}}],["confinement",{"2":{"249":1}}],["confidentiality",{"2":{"245":1,"255":1}}],["confirm",{"2":{"201":1,"202":1,"259":1,"260":1}}],["confirmation",{"2":{"183":1,"201":1,"202":1,"265":1,"266":1,"720":1}}],["configbuilder",{"2":{"175":1}}],["configs",{"2":{"13":2,"16":7,"17":1,"18":4,"21":1,"22":1,"128":2,"130":1,"131":1,"143":1,"145":1,"164":2,"210":1,"217":2,"218":1,"272":1}}],["configuring",{"0":{"186":1,"211":1,"218":1,"265":1},"1":{"266":1},"2":{"198":1,"252":1,"264":1}}],["configure",{"0":{"200":1},"2":{"122":1,"143":1,"146":1,"151":1,"166":1,"167":1,"207":1,"227":1,"263":1,"265":1,"714":2}}],["configured",{"0":{"58":1},"2":{"12":1,"55":1,"58":1,"135":1,"175":1,"176":1,"272":1,"662":1,"663":1,"705":1}}],["configurationeventset",{"0":{"338":1},"2":{"337":1}}],["configurationeventfilter",{"0":{"337":1},"2":{"341":1}}],["configurationevent",{"0":{"336":1},"2":{"340":1}}],["configurations",{"2":{"131":1,"138":1,"151":1,"152":1,"197":1,"217":1}}],["configuration",{"0":{"8":1,"113":1,"124":1,"131":1,"142":1,"143":1,"164":1,"175":1,"271":1,"721":1,"724":1},"1":{"114":1,"115":1,"116":1,"117":1,"118":1,"119":1,"120":1,"121":1,"122":1,"123":1,"125":1,"126":1,"127":1,"144":1,"145":1,"146":1,"147":1,"148":1,"149":1,"150":1,"151":1,"152":1,"153":1,"154":1,"155":1,"272":1,"273":1,"722":1,"723":1,"725":1,"726":1},"2":{"6":1,"8":1,"10":1,"12":4,"13":4,"16":3,"17":2,"18":1,"21":2,"22":2,"33":1,"41":1,"47":1,"111":1,"113":2,"114":1,"115":1,"117":1,"118":1,"119":1,"124":4,"125":5,"127":1,"128":2,"131":2,"132":2,"135":3,"137":1,"143":9,"144":1,"145":1,"146":1,"148":1,"149":1,"150":1,"151":2,"158":1,"161":2,"164":3,"167":2,"172":1,"174":1,"175":1,"181":1,"185":1,"186":3,"187":1,"196":2,"197":2,"199":1,"200":7,"203":2,"208":1,"210":2,"211":2,"217":1,"218":4,"219":1,"238":3,"244":1,"271":1,"273":1,"285":1,"340":1,"341":1,"633":1,"637":1,"663":1,"667":1,"703":1,"714":5,"721":1,"723":3,"724":1,"725":4,"726":4}}],["config",{"2":{"8":2,"13":1,"16":4,"18":4,"22":1,"40":1,"114":2,"125":1,"126":1,"127":2,"128":1,"131":1,"135":1,"143":1,"144":2,"145":1,"146":1,"161":1,"164":2,"181":11,"186":1,"200":4,"201":1,"203":1,"210":3,"211":3,"217":4,"218":6,"238":1,"661":1,"714":2}}],["conduct",{"2":{"260":2}}],["conditions",{"2":{"106":1,"197":1,"641":1,"663":1,"664":1}}],["condition",{"2":{"41":1,"49":1,"260":1,"289":1}}],["conditional",{"2":{"36":1,"233":1}}],["conditionals",{"0":{"36":1},"2":{"100":1,"101":1}}],["conjunction",{"2":{"253":1}}],["conversion",{"2":{"221":1,"418":1,"498":1,"658":3,"741":2}}],["conversions",{"2":{"176":1}}],["convert",{"2":{"219":1}}],["converting",{"2":{"214":1}}],["converted",{"2":{"188":1,"658":2}}],["conventional",{"2":{"263":1}}],["conventions",{"0":{"660":1,"666":1},"2":{"42":1,"212":1,"660":1,"666":1}}],["convenience",{"2":{"16":1,"175":1,"202":1}}],["conveniently",{"2":{"10":1,"134":1}}],["convenient",{"2":{"3":1,"101":1,"143":1,"219":1}}],["concrete",{"2":{"215":1}}],["concurrent",{"2":{"193":4}}],["concept",{"0":{"236":1},"2":{"253":1,"628":1,"656":1}}],["concepts",{"2":{"167":1,"185":1,"208":1,"217":1,"226":1}}],["concerns",{"2":{"260":1}}],["concern",{"2":{"177":1,"220":1}}],["concatenated",{"2":{"174":1}}],["conclusion",{"0":{"110":1}}],["consult",{"2":{"233":1,"243":1,"244":1,"282":1,"725":1}}],["consulting",{"2":{"217":1}}],["consumer",{"2":{"186":2}}],["console",{"2":{"176":1,"180":3,"183":1,"190":1}}],["consisting",{"2":{"202":1}}],["consist",{"2":{"181":1}}],["consists",{"2":{"111":1,"174":2,"202":1,"287":1}}],["considers",{"2":{"268":1}}],["considering",{"2":{"247":1}}],["consideration",{"2":{"178":1}}],["considerations",{"2":{"137":1}}],["considerably",{"2":{"42":1}}],["consider",{"2":{"67":1,"88":1,"136":1,"244":1,"247":1,"249":1,"250":2,"259":1,"260":4,"268":1}}],["considered",{"2":{"63":1,"249":1,"252":1,"268":1,"633":1}}],["consequences",{"2":{"245":1,"656":1}}],["consequence",{"2":{"28":1}}],["consensusblockrejection",{"2":{"326":1}}],["consensus",{"0":{"28":1},"2":{"28":5,"88":5,"97":1,"163":1,"196":9,"207":3,"230":2,"323":1,"636":1,"652":1,"753":1}}],["constrained",{"2":{"238":1}}],["constructs",{"2":{"212":1,"660":5}}],["construction",{"2":{"69":1,"99":1,"157":1,"160":1,"178":1,"219":1,"666":1}}],["constructed",{"2":{"67":1}}],["construct",{"2":{"66":1,"67":1,"218":1,"221":2,"666":1}}],["constantly",{"2":{"252":1}}],["constant",{"2":{"207":1,"228":1}}],["constants",{"2":{"5":1,"217":2}}],["const",{"2":{"5":2,"175":12,"176":5,"178":3,"179":7,"180":8,"181":12,"183":3,"186":3,"657":1}}],["connects",{"2":{"263":1,"268":1,"714":2,"728":1}}],["connection",{"2":{"151":1,"219":1,"258":1,"720":1,"730":1}}],["connections",{"2":{"118":1,"119":1,"147":1,"714":1}}],["connected",{"2":{"28":1,"197":1,"249":1,"258":1,"268":1,"735":4,"749":1}}],["connect",{"2":{"22":1,"135":1,"151":1,"263":1,"272":1,"628":1}}],["contact",{"2":{"271":1,"274":1,"277":1,"283":1,"284":1,"285":1,"725":1}}],["contained",{"2":{"628":1}}],["containerized",{"2":{"196":1}}],["containers",{"2":{"13":1,"186":4,"197":1,"272":5}}],["container",{"0":{"6":1,"339":1},"1":{"7":1,"8":1,"9":1},"2":{"6":7,"7":2,"8":2,"9":2,"128":2,"143":1,"196":5,"197":1,"253":1,"272":1,"500":2,"628":1}}],["containing",{"2":{"258":1,"265":1,"634":1,"635":1}}],["contain",{"2":{"50":1,"115":1,"145":1,"187":1,"190":1,"200":1,"238":1,"247":1,"669":1}}],["contains",{"2":{"32":1,"51":1,"53":1,"72":1,"103":2,"111":1,"128":1,"154":1,"174":2,"217":2,"220":1,"221":1,"273":1,"288":1,"567":1,"647":1,"656":1,"723":1}}],["continuous",{"2":{"260":3,"287":1,"719":1,"729":1}}],["continuing",{"2":{"214":1,"282":1}}],["continue",{"2":{"203":1}}],["continues",{"2":{"183":1,"720":1}}],["content",{"2":{"143":1}}],["contents",{"2":{"16":1,"112":1,"653":1,"700":1}}],["context",{"2":{"62":1,"263":1,"629":1}}],["contributors",{"2":{"270":1}}],["contributing",{"2":{"168":1}}],["contributes",{"2":{"248":1}}],["contribute",{"2":{"168":1,"260":1}}],["contrary",{"2":{"221":1}}],["contract",{"0":{"102":1,"104":1},"1":{"103":1,"104":1},"2":{"90":2,"93":1,"97":1,"104":2,"106":1,"110":1,"141":1,"233":1,"664":1}}],["contracts",{"0":{"105":1,"233":1,"641":1},"1":{"106":1,"107":1,"108":1,"109":1,"110":1},"2":{"36":1,"79":1,"88":1,"100":1,"105":1,"165":1,"233":2,"626":1,"641":2,"646":1}}],["contrast",{"2":{"57":1,"65":1,"192":1,"221":1,"224":1,"230":1}}],["controls",{"2":{"246":1,"260":2}}],["control",{"2":{"20":1,"117":1,"203":1,"230":1,"260":3,"264":1}}],["comic",{"2":{"253":1}}],["come",{"2":{"231":1,"238":1,"252":1,"728":1}}],["comes",{"2":{"4":1,"28":1,"108":1,"141":1,"202":1,"219":1,"249":1,"262":1,"656":1}}],["comfortable",{"2":{"217":1}}],["combs",{"2":{"72":1}}],["combining",{"2":{"62":1,"255":1}}],["combined",{"2":{"65":1,"246":1}}],["combine",{"2":{"36":1,"69":1}}],["combinations",{"2":{"252":5}}],["combination",{"2":{"6":1,"95":1,"643":1}}],["community",{"2":{"270":2}}],["communicating",{"2":{"259":2}}],["communication",{"2":{"149":1,"202":1,"246":1,"247":1,"250":1,"254":1,"259":1,"270":1,"644":1,"719":1,"729":1}}],["communications",{"2":{"18":1,"175":1,"237":1,"254":1}}],["communicate",{"2":{"28":1,"175":2,"183":1,"263":1}}],["comments",{"2":{"235":1}}],["commonly",{"2":{"134":1,"260":1,"639":1,"714":1}}],["common",{"2":{"28":1,"126":1,"259":1,"271":1,"280":2,"672":1,"703":1}}],["commitment",{"2":{"267":1}}],["commits",{"2":{"185":1}}],["committime",{"2":{"705":1}}],["committimelimit=4000",{"2":{"128":1,"164":1}}],["committing",{"2":{"72":1,"192":1,"224":1}}],["committed",{"2":{"28":1,"31":1,"32":2,"53":1,"87":1,"88":1,"89":1,"135":1,"181":3,"196":4,"207":1,"215":2,"327":1,"707":1,"728":6,"735":1,"749":1}}],["commit",{"0":{"89":1},"2":{"21":1,"85":1,"87":2,"89":3,"185":4,"196":1,"325":1,"642":1,"705":1}}],["command>",{"2":{"200":2}}],["commands",{"2":{"16":1,"200":2}}],["command",{"2":{"6":1,"16":2,"18":2,"19":1,"104":1,"134":1,"172":3,"196":2,"200":1,"202":1,"203":1,"207":1,"218":1,"224":1,"238":2,"242":1,"272":2,"279":1,"282":2}}],["compromising",{"2":{"268":1}}],["compromised",{"2":{"250":1}}],["compromise",{"2":{"249":1}}],["comprehensive",{"2":{"260":2}}],["component",{"2":{"182":1}}],["components",{"0":{"635":1},"1":{"636":1,"637":1,"638":1,"639":1,"640":1,"641":1,"642":1,"643":1,"644":1},"2":{"181":6,"626":1}}],["compositions",{"2":{"647":1}}],["composite",{"0":{"49":1},"2":{"40":1,"49":1,"661":1}}],["compose",{"0":{"272":1},"2":{"13":1,"18":3,"19":1,"21":1,"143":1,"195":1,"196":4,"197":2,"207":1,"210":1,"217":1,"272":4}}],["compendium",{"2":{"175":1}}],["compilation",{"2":{"105":1,"107":1,"197":1}}],["compiling",{"2":{"105":1,"110":1}}],["compiler",{"2":{"104":1}}],["compilers",{"2":{"101":1}}],["compiled",{"2":{"39":1,"71":1,"100":1,"106":2,"174":3,"176":1,"242":1,"667":1,"715":1}}],["compile",{"0":{"108":1},"2":{"14":1,"108":1,"231":1,"232":1,"656":1}}],["companies",{"2":{"247":1}}],["companion",{"2":{"186":1,"193":9}}],["compatibility",{"0":{"287":1},"2":{"231":1,"287":2}}],["compatible",{"2":{"175":1,"185":2,"188":1,"210":2,"229":1}}],["comparisons",{"2":{"229":1}}],["comparison",{"2":{"166":1,"253":1}}],["compare",{"2":{"42":1,"252":1,"253":1}}],["compared",{"2":{"6":1,"83":1,"87":1,"97":1,"631":1}}],["compactcombination",{"2":{"239":1}}],["compact",{"0":{"334":1,"335":1},"2":{"100":1,"238":1,"268":1,"334":1,"335":1,"457":2,"749":2}}],["computed",{"2":{"181":2}}],["computers",{"2":{"248":1}}],["computer",{"2":{"39":2,"248":1}}],["computation",{"2":{"89":1}}],["compliant",{"2":{"241":1,"656":1}}],["complicated",{"2":{"39":1}}],["completablefuture",{"2":{"193":7}}],["completes",{"2":{"196":1}}],["complete",{"2":{"97":1,"101":1,"159":1,"181":1,"185":1,"192":1,"196":5,"210":1,"217":2,"224":1,"229":1}}],["completely",{"2":{"63":1,"127":1,"267":1}}],["complexities",{"2":{"252":1}}],["complex",{"2":{"101":1,"208":1,"233":1}}],["com",{"2":{"2":1,"5":3,"103":1,"171":1,"172":2,"174":1,"185":4,"210":1}}],["ps",{"2":{"272":2}}],["pyo3",{"2":{"210":1}}],["python3",{"2":{"283":1}}],["pythonlistener",{"2":{"215":1}}],["pythonfor",{"2":{"215":1}}],["pythonfilter",{"2":{"215":1}}],["pythonfrom",{"2":{"212":1,"213":1}}],["pythonamount",{"2":{"214":1}}],["pythonhash",{"2":{"212":1,"213":1}}],["pythonimport",{"2":{"211":1,"214":1}}],["python",{"0":{"209":1,"283":1},"1":{"210":1,"211":1,"212":1,"213":1,"214":1,"215":1},"2":{"27":1,"29":1,"42":1,"43":1,"136":1,"146":1,"166":1,"210":10,"211":3,"212":3,"214":1,"227":1,"278":1,"283":4}}],["p>events",{"2":{"181":1}}],["p>",{"2":{"181":7}}],["phrase",{"0":{"269":1},"2":{"253":3,"269":1}}],["phone",{"2":{"253":1,"259":1}}],["phones",{"2":{"248":1}}],["phishing",{"2":{"249":1,"259":1}}],["philosophy",{"2":{"90":1}}],["physically",{"0":{"267":1},"1":{"268":1,"269":1},"2":{"267":1}}],["physical",{"2":{"247":1,"253":1,"258":2,"260":3,"263":1,"267":1}}],["phase",{"2":{"137":1}}],["pivotal",{"2":{"260":1}}],["picking",{"2":{"253":1}}],["pieces",{"2":{"217":1}}],["pip3",{"2":{"283":1}}],["pip",{"2":{"210":2,"283":9}}],["pipelinestatuskind",{"2":{"181":2}}],["pipelinestatus",{"2":{"181":2}}],["pipelineeventbox",{"0":{"494":1},"2":{"349":1}}],["pipelineeventfilterbox",{"0":{"495":1},"2":{"350":1,"595":1}}],["pipelineeventfilter",{"2":{"181":2,"192":1,"224":2}}],["pipelineentitykind",{"2":{"181":2}}],["pipeline",{"0":{"32":1},"2":{"31":1,"32":2,"89":1,"94":1,"181":2,"192":5,"204":2,"207":6,"215":5,"219":1,"224":2,"349":1,"350":1,"595":1}}],["pitfalls",{"2":{"137":1}}],["plugins",{"2":{"185":1,"232":1,"249":4}}],["plus",{"2":{"88":1,"175":1,"224":1}}],["please",{"2":{"174":2,"181":1,"233":1,"283":1,"285":1}}],["platform",{"2":{"283":1}}],["platforms",{"2":{"185":1,"234":1,"259":1}}],["planned",{"2":{"278":1}}],["planning",{"2":{"174":1}}],["plans",{"2":{"235":1}}],["plan",{"0":{"250":1},"2":{"134":1,"136":1,"217":1,"250":5}}],["playing",{"2":{"656":1}}],["play",{"2":{"97":1,"174":1,"237":1}}],["plain",{"2":{"97":1,"256":1}}],["places",{"2":{"273":1}}],["place",{"2":{"5":1,"43":1,"125":1,"174":1,"218":1,"258":1,"652":1,"658":1}}],["pulled",{"2":{"196":4,"272":1}}],["pull",{"2":{"196":5}}],["pullpolicy",{"2":{"186":3}}],["purchase",{"2":{"630":1}}],["purpose",{"2":{"218":1,"248":1}}],["purposes",{"2":{"78":1,"174":1,"188":1,"202":1,"224":1,"264":1,"700":1}}],["pure",{"0":{"193":1}}],["push",{"2":{"181":1}}],["pub",{"2":{"657":1}}],["pubkey",{"2":{"177":2}}],["published",{"2":{"174":2}}],["publish",{"2":{"16":1}}],["publickey>",{"2":{"188":1}}],["publickey",{"0":{"330":1,"441":1,"496":1,"563":1,"614":1},"2":{"177":2,"187":1,"218":1,"220":1,"289":1,"294":2,"330":1,"332":1,"393":2,"441":1,"449":1,"490":1,"539":1,"540":2,"563":1,"614":1}}],["public",{"0":{"115":1,"118":1,"138":1,"145":1,"147":1,"157":1,"254":1,"273":1},"1":{"119":1,"120":1,"139":1,"140":1,"141":1,"148":1,"149":1,"150":1,"255":1,"256":1},"2":{"9":2,"18":24,"20":2,"21":2,"41":1,"42":2,"53":1,"56":2,"113":1,"115":2,"125":1,"126":2,"127":1,"128":2,"132":1,"134":1,"135":3,"138":1,"139":1,"140":1,"141":5,"143":8,"145":3,"146":5,"151":5,"157":1,"164":1,"167":1,"175":2,"177":2,"181":1,"186":1,"188":2,"190":1,"193":7,"202":2,"203":2,"213":5,"218":2,"220":2,"237":1,"238":2,"239":6,"246":2,"248":1,"249":1,"254":5,"255":4,"256":6,"258":1,"263":3,"273":1,"286":1,"490":1,"539":1,"627":1,"631":1,"663":2,"672":2,"714":4}}],["putting",{"2":{"213":1}}],["puts",{"2":{"104":1}}],["put",{"2":{"18":1,"28":1,"42":1,"137":1,"143":1,"177":1,"193":1}}],["pod",{"2":{"628":1}}],["policies",{"2":{"260":4}}],["pool",{"2":{"252":1}}],["popular",{"2":{"236":1}}],["poc",{"2":{"236":1}}],["poured",{"2":{"97":1}}],["pours",{"2":{"97":1}}],["potential",{"2":{"247":1,"248":2,"249":1,"250":4,"260":2,"268":1,"656":1}}],["potentially",{"2":{"88":1,"249":1,"263":1}}],["pot",{"2":{"92":1}}],["powerful",{"2":{"253":1}}],["power",{"2":{"65":1,"230":1}}],["pointer",{"2":{"657":1,"658":1}}],["pointers",{"2":{"218":1,"656":3}}],["point",{"2":{"25":1,"81":1,"88":2,"92":1,"104":1,"110":1,"125":1,"203":1,"214":1,"233":1,"235":1,"238":1,"282":1}}],["portable",{"2":{"39":1,"100":1,"101":1,"103":2,"165":1,"234":1,"248":2,"249":1}}],["port",{"2":{"22":1,"148":1,"186":11,"264":1,"268":1,"554":1,"555":1,"556":1}}],["ports",{"2":{"18":6,"148":1,"186":1,"264":1}}],["possession",{"2":{"268":1}}],["possessing",{"2":{"255":1}}],["possibilities",{"2":{"253":1}}],["possibility",{"2":{"103":1,"137":1,"215":1}}],["possible",{"2":{"5":1,"16":1,"18":1,"62":3,"77":1,"82":1,"141":1,"189":1,"192":1,"224":1,"232":1,"239":4,"249":1,"252":7,"256":1,"259":5,"263":1,"286":1,"699":1,"750":1}}],["pose",{"2":{"249":1,"259":2}}],["posture",{"2":{"248":1}}],["post",{"2":{"247":1,"724":1,"739":1,"751":1}}],["posted",{"2":{"18":1}}],["posing",{"2":{"261":1}}],["posix",{"2":{"241":1}}],["positive",{"2":{"25":1,"268":1}}],["p2p",{"0":{"149":1},"2":{"18":4,"20":1,"21":1,"22":1,"127":1,"143":1,"149":1,"186":5,"196":2,"200":1}}],["pwd",{"2":{"16":6}}],["p",{"2":{"14":1,"17":1,"130":2,"171":1,"238":1,"239":1}}],["pedantry",{"2":{"221":1}}],["pending",{"0":{"736":1},"1":{"737":1,"738":1},"2":{"181":1,"736":1,"738":1}}],["people",{"2":{"88":2,"156":1,"226":1}}],["peereventset",{"0":{"489":1},"2":{"488":1}}],["peereventfilter",{"0":{"488":1},"2":{"341":1}}],["peerevent",{"0":{"487":1},"2":{"340":1}}],["peer=ed0120a98bafb0663ce08d75ebd506fec38a84e576a7c9b0897693ed4b04fd9ef2d18d",{"2":{"196":1}}],["peerurl",{"2":{"187":2}}],["peerid>",{"2":{"186":1}}],["peerid",{"0":{"473":1,"490":1,"613":1},"2":{"94":1,"186":2,"325":1,"393":1,"414":2,"473":1,"486":1,"487":2,"488":1,"601":1,"613":1}}],["peerbuilder>",{"2":{"53":1}}],["peer0",{"2":{"21":2}}],["peer2",{"2":{"21":1}}],["peer1",{"2":{"21":1}}],["peers",{"0":{"135":1,"140":1,"146":1,"159":1,"163":1},"1":{"160":1,"161":1,"162":1},"2":{"12":4,"18":9,"20":1,"21":1,"22":3,"28":11,"33":1,"41":2,"42":4,"88":1,"94":1,"111":2,"112":1,"117":1,"127":1,"128":1,"134":1,"135":10,"140":1,"143":3,"146":9,"149":2,"151":5,"158":1,"160":2,"161":1,"163":1,"187":1,"196":1,"197":1,"200":1,"230":1,"272":3,"286":3,"628":3,"644":2,"650":2,"653":1,"704":1,"705":3,"717":1,"728":6,"735":4,"749":3,"750":2}}],["peer",{"0":{"143":1,"156":1,"161":1,"486":1,"506":1,"601":1,"628":1,"644":1,"703":1},"1":{"144":1,"145":1,"146":1,"147":1,"148":1,"149":1,"150":1,"151":1,"152":1,"153":1,"154":1,"155":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"647":1,"704":1,"705":1},"2":{"10":1,"13":3,"14":3,"16":7,"17":4,"18":10,"19":1,"20":4,"21":4,"22":4,"39":1,"42":1,"53":1,"65":2,"88":1,"104":1,"106":1,"119":1,"124":1,"126":1,"127":2,"128":5,"130":1,"131":2,"135":6,"138":1,"140":2,"143":7,"144":3,"145":2,"146":1,"148":1,"151":1,"157":1,"159":1,"160":4,"161":1,"162":5,"163":4,"164":1,"174":2,"175":1,"177":1,"181":1,"183":1,"186":1,"196":9,"197":1,"200":1,"219":1,"220":1,"256":2,"272":11,"340":1,"341":1,"393":1,"415":2,"506":1,"509":2,"604":2,"626":2,"628":2,"634":2,"637":1,"643":1,"649":1,"654":1,"665":1,"703":3,"704":1,"714":4,"728":1,"733":1,"735":1,"749":1}}],["pertain",{"2":{"675":1}}],["pertaining",{"2":{"192":1,"224":1}}],["percentage",{"2":{"634":1}}],["perpetually",{"2":{"221":1}}],["perhaps",{"2":{"218":2,"221":1}}],["persistence",{"2":{"638":1}}],["persistently",{"2":{"218":1}}],["persistent",{"2":{"97":1,"155":1,"200":1}}],["persists",{"2":{"283":1}}],["personnel",{"2":{"247":1,"260":3}}],["person",{"2":{"211":1,"255":1}}],["personal",{"2":{"106":1,"248":1,"253":1,"259":3}}],["performed",{"2":{"62":1,"201":1,"245":1,"719":1,"726":1,"729":1}}],["perform",{"2":{"62":1,"137":2,"166":1,"174":1,"198":1,"203":1,"244":2,"260":1,"265":2,"283":1,"658":1}}],["performance",{"2":{"10":3,"42":1,"120":1,"150":1,"232":1,"666":1,"714":1}}],["periodic",{"2":{"260":1}}],["periodically",{"2":{"181":1,"248":1,"249":1,"250":1,"252":1}}],["period",{"2":{"57":3,"88":1,"143":3,"151":1,"528":1,"631":1}}],["permits",{"2":{"263":1}}],["permissionparameter",{"2":{"417":1}}],["permissionremoved",{"2":{"290":1,"292":1,"523":1,"525":1}}],["permissionadded",{"2":{"290":1,"292":1,"523":1,"525":1}}],["permissionless",{"2":{"165":1}}],["permissioned",{"2":{"165":1}}],["permissiontokendefinition",{"2":{"673":1}}],["permissiontokenschema",{"0":{"492":1},"2":{"493":2,"499":2}}],["permissiontokenschemaupdate",{"2":{"341":1}}],["permissiontokenschemaupdateevent",{"0":{"493":1},"2":{"340":1}}],["permissiontokenid",{"2":{"414":1}}],["permissiontoken",{"0":{"406":1,"407":1,"491":1,"518":1,"519":1,"562":1},"2":{"56":1,"128":1,"160":1,"164":1,"340":1,"393":1,"406":1,"407":1,"409":3,"499":2,"518":1,"519":1,"521":3,"522":1,"562":1,"664":1,"674":1}}],["permission",{"0":{"57":1,"58":1,"59":1,"62":1,"663":1,"672":1},"1":{"58":1,"60":1,"61":1,"63":1,"664":1,"673":1,"674":1},"2":{"33":2,"40":1,"41":4,"42":1,"43":2,"44":1,"45":1,"53":2,"56":6,"57":8,"58":1,"59":1,"60":2,"62":2,"64":2,"89":1,"111":2,"128":1,"129":1,"138":2,"139":1,"141":5,"160":1,"203":1,"232":1,"295":1,"527":1,"661":1,"662":3,"663":4,"664":6,"669":1,"670":1,"672":1,"673":1,"674":1,"741":3}}],["permissions",{"0":{"55":1,"56":1,"139":1,"160":1,"662":1},"1":{"57":1,"58":1,"59":1,"60":1,"61":1,"62":1,"63":1,"64":1,"663":1,"664":1},"2":{"29":1,"40":1,"45":3,"55":1,"56":3,"59":1,"62":2,"63":1,"82":1,"89":1,"128":1,"138":1,"139":2,"141":1,"160":2,"161":1,"164":1,"203":1,"522":1,"661":1,"662":1,"663":2,"672":3}}],["permanently",{"2":{"45":1,"106":1,"244":1}}],["permanent",{"2":{"16":1}}],["permalink",{"2":{"5":1}}],["per",{"2":{"12":1,"57":1,"130":4,"143":1,"221":1,"273":1,"725":1}}],["practice",{"2":{"247":1}}],["practices",{"2":{"177":1,"213":1,"220":1,"246":2,"247":1,"248":1,"261":2}}],["practical",{"2":{"137":1}}],["prioritising",{"2":{"644":1}}],["prices",{"2":{"627":1}}],["primarily",{"2":{"262":1}}],["primary",{"2":{"250":1,"263":1}}],["primitives",{"2":{"217":1}}],["privacy",{"2":{"249":4,"255":1}}],["privatekey",{"2":{"218":1,"273":2}}],["private",{"0":{"115":1,"138":1,"145":1,"158":1,"273":1},"1":{"139":1,"140":1,"141":1,"159":1,"160":1,"161":1,"162":1,"163":1},"2":{"18":6,"20":1,"42":3,"56":2,"113":1,"115":1,"125":1,"126":2,"127":1,"134":2,"135":5,"136":1,"138":1,"139":1,"140":1,"141":8,"143":6,"145":2,"151":4,"158":1,"161":1,"164":1,"167":1,"175":2,"177":2,"181":1,"187":7,"202":2,"203":2,"211":1,"213":2,"218":2,"220":2,"238":3,"239":7,"254":3,"255":4,"256":5,"258":1,"259":1,"261":3,"263":6,"265":1,"268":1,"269":1,"273":2,"667":1,"672":2}}],["privilege",{"2":{"654":2}}],["privileged",{"2":{"161":1,"682":1}}],["privileges",{"2":{"128":2,"135":1}}],["principle",{"2":{"656":1}}],["principles",{"0":{"257":1,"258":1,"259":1,"260":1},"1":{"258":1,"259":1,"260":1},"2":{"65":1,"167":1,"246":2,"247":1,"256":1,"257":1,"262":1}}],["printout",{"2":{"224":1}}],["print",{"2":{"200":3,"215":1}}],["println",{"2":{"4":1,"187":2,"188":2,"189":3,"190":5,"191":2,"224":2}}],["proactively",{"2":{"260":1}}],["proactive",{"2":{"248":1,"250":1}}],["protocol",{"2":{"247":1,"262":2,"263":4,"715":1,"721":1,"724":1,"731":1,"734":1,"736":1,"739":1,"744":1,"747":1,"751":1}}],["protocols",{"2":{"238":1,"247":1,"260":1,"718":1,"727":1}}],["protected",{"2":{"258":1}}],["protection",{"2":{"254":1,"258":1}}],["protecting",{"2":{"249":1,"251":1,"262":1,"264":1}}],["protect",{"2":{"245":1,"246":1,"248":1,"258":1,"260":1,"261":1}}],["production",{"2":{"215":1,"219":1,"256":1}}],["produces",{"2":{"104":1,"105":1}}],["produced",{"2":{"38":1,"94":1,"97":1}}],["produce",{"2":{"28":2,"101":1,"241":1}}],["proxified",{"2":{"181":1}}],["proxy",{"2":{"117":1,"705":1}}],["problem",{"2":{"137":1,"154":1,"221":1,"278":1,"280":1,"282":1}}],["problems",{"2":{"100":2,"280":1}}],["profiles",{"2":{"249":2}}],["profile",{"2":{"105":1,"249":3}}],["projected",{"2":{"253":1}}],["project",{"0":{"103":1},"2":{"103":2,"134":1,"181":2,"187":1,"188":1,"189":2,"236":1,"238":1}}],["projects",{"2":{"102":1,"229":1}}],["proprietary",{"2":{"248":1,"249":1}}],["properties",{"2":{"238":1}}],["property",{"2":{"165":1,"235":1,"634":1}}],["properly",{"2":{"97":1,"230":1,"263":1,"634":1}}],["proposals",{"2":{"12":1}}],["promptly",{"2":{"250":3,"260":2,"264":1}}],["prompt",{"2":{"65":1,"256":1}}],["prometheus",{"2":{"10":2,"120":3,"150":3,"231":1,"714":2,"735":1}}],["proved",{"2":{"268":1}}],["prove",{"2":{"230":1,"247":1}}],["proven",{"2":{"63":1}}],["providing",{"2":{"126":1,"127":1,"185":1,"215":1,"217":1,"253":1}}],["provided",{"2":{"32":1,"49":2,"87":1,"98":1,"101":2,"110":1,"122":1,"125":2,"126":1,"127":2,"136":1,"146":1,"175":1,"186":1,"210":1,"211":1,"217":1,"218":1,"226":1,"241":1,"266":1,"646":1,"648":1,"650":1,"666":1,"670":1,"678":1,"698":1,"720":1,"741":1}}],["provides",{"2":{"29":1,"136":1,"166":1,"174":4,"175":1,"183":1,"238":1,"254":1,"263":1,"264":1,"287":1,"656":1,"662":1}}],["provide",{"2":{"10":1,"69":1,"85":1,"97":1,"116":1,"117":2,"125":1,"138":1,"143":1,"151":1,"175":2,"176":1,"177":1,"185":1,"192":1,"213":1,"217":1,"220":1,"231":1,"256":1,"260":1,"262":1,"287":1,"645":1,"649":1,"655":1,"656":1,"666":1}}],["prospective",{"2":{"28":1,"226":1}}],["proof",{"0":{"236":1},"2":{"28":1}}],["proceeds",{"2":{"728":1}}],["processed",{"2":{"97":1,"192":1,"726":1}}],["processes",{"2":{"42":1,"136":1,"141":1,"268":1,"628":1}}],["processing",{"2":{"65":1,"87":1,"97":1,"253":1}}],["processor",{"2":{"39":2}}],["process",{"2":{"16":1,"27":1,"28":4,"42":3,"43":1,"82":1,"87":1,"97":1,"101":1,"127":1,"137":2,"141":3,"159":1,"161":1,"162":2,"163":1,"192":1,"196":1,"213":1,"215":1,"217":1,"224":1,"253":1,"255":1,"260":1,"263":1,"266":2,"628":2,"652":1,"658":1,"666":1}}],["procedures",{"2":{"250":1,"260":1}}],["procedure",{"2":{"6":1,"161":1}}],["prone",{"2":{"13":1,"19":1}}],["progress",{"2":{"12":2,"32":1,"97":1,"228":1,"272":1,"725":1}}],["programs",{"2":{"266":1,"641":1}}],["programmer",{"2":{"127":1}}],["programmers",{"2":{"100":1,"221":1}}],["programming",{"2":{"101":1,"103":1,"108":1,"166":1,"187":1}}],["program",{"0":{"264":1},"1":{"265":1,"266":1},"2":{"10":1,"36":1,"103":1,"185":1,"224":1,"252":2,"256":1,"263":1,"658":1}}],["preemptive",{"2":{"245":1}}],["preamble",{"0":{"226":1}}],["prerequisite",{"2":{"742":1,"743":1}}],["prerequisites",{"0":{"14":1,"170":1,"195":1},"2":{"166":2}}],["preregistered",{"2":{"200":3}}],["predicate",{"2":{"187":2,"318":1}}],["predominantly",{"2":{"107":1}}],["preserving",{"2":{"279":1}}],["preserve",{"2":{"6":1}}],["presence",{"2":{"187":2,"260":1,"263":1}}],["presently",{"2":{"189":1}}],["present",{"2":{"186":1,"287":1,"665":1,"667":1}}],["prepared",{"2":{"219":1,"250":1}}],["prepare",{"2":{"175":1,"219":1}}],["prev",{"2":{"196":4,"207":3,"568":1}}],["preventing",{"2":{"247":1}}],["prevent",{"2":{"137":1,"248":1,"262":1}}],["prevents",{"2":{"127":1}}],["previously",{"2":{"7":1,"97":1,"128":1,"166":1,"188":1,"252":1,"269":1,"740":2}}],["previous",{"0":{"7":1},"2":{"6":1,"97":1,"175":1,"177":1,"185":1,"217":1,"220":1,"221":1,"253":1,"323":1}}],["precommit",{"2":{"357":1}}],["precaution",{"2":{"250":1}}],["precedence",{"2":{"125":1}}],["precious",{"2":{"90":1}}],["precisely",{"2":{"154":1}}],["precise",{"2":{"79":1,"666":1}}],["precision",{"2":{"25":1,"50":1,"178":2,"749":2}}],["prefers",{"2":{"270":1}}],["preference",{"2":{"249":1}}],["preferences",{"2":{"134":1}}],["preferably",{"2":{"119":1}}],["prefix",{"2":{"119":1}}],["prebuilt",{"2":{"108":1}}],["premium",{"2":{"106":1}}],["prelude",{"2":{"104":1,"218":2,"219":1,"220":1,"224":1}}],["preliminaries",{"2":{"104":1}}],["pre",{"0":{"58":1,"89":1},"2":{"55":1,"58":1,"85":1,"87":2,"89":3,"173":1,"176":1,"196":1,"217":5,"662":1,"663":1,"664":1}}],["painted",{"2":{"631":1}}],["painting",{"2":{"631":1}}],["paired",{"2":{"279":1}}],["pairs",{"0":{"134":1},"2":{"50":1,"52":2,"127":1,"134":1,"135":1,"137":1,"639":1}}],["pair",{"2":{"22":1,"40":1,"41":1,"49":2,"51":1,"53":3,"61":1,"71":1,"115":1,"127":2,"134":2,"135":1,"145":1,"175":4,"177":1,"188":3,"202":3,"213":1,"220":1,"238":4,"254":1,"256":2,"263":2,"273":1,"286":1,"661":1}}],["panel",{"2":{"265":1}}],["panics",{"2":{"105":1,"231":1}}],["panic",{"2":{"105":1,"106":2,"108":1,"709":1}}],["pales",{"2":{"253":1}}],["patches",{"2":{"249":1}}],["patching",{"2":{"234":1}}],["patch",{"2":{"234":1,"248":1}}],["path>",{"2":{"200":1}}],["paths",{"2":{"16":1,"283":1}}],["path=",{"2":{"16":6,"244":2}}],["path",{"0":{"154":1},"2":{"2":1,"16":4,"126":1,"143":1,"152":1,"154":2,"155":1,"199":2,"200":3,"217":4,"244":7,"283":1,"750":1}}],["page",{"2":{"185":1,"238":1,"249":1,"288":1}}],["pagination",{"0":{"67":1},"2":{"67":7,"69":2}}],["paginated",{"2":{"65":1,"665":1}}],["padstart",{"2":{"181":1}}],["padding",{"2":{"103":1,"181":1}}],["paying",{"2":{"249":1}}],["pay",{"2":{"178":1}}],["payload",{"2":{"18":5,"20":1,"128":3,"134":1,"143":1,"164":3,"175":1,"177":1,"181":1,"239":1,"491":1,"496":1,"539":1,"547":1,"549":1,"551":1}}],["packaged",{"2":{"231":1}}],["package",{"2":{"52":1,"103":1,"154":1,"174":6,"175":1,"185":1,"217":2,"282":1,"283":1}}],["packages",{"2":{"5":3,"174":6,"187":1,"210":1,"248":1}}],["pasting",{"2":{"238":1}}],["paste",{"2":{"16":1,"20":2}}],["passphrase",{"2":{"263":1,"269":1}}],["passed",{"2":{"175":1,"178":1,"221":1,"287":1,"753":1}}],["passes",{"2":{"63":1}}],["passwords",{"2":{"246":1,"248":2,"250":1,"251":1,"252":4,"253":3,"256":1,"259":2,"264":2,"268":1}}],["password",{"0":{"251":1,"252":1,"253":1,"264":1},"1":{"252":1,"253":1,"265":1,"266":1},"2":{"113":1,"117":3,"164":1,"238":1,"246":3,"247":1,"250":1,"251":1,"252":22,"253":6,"258":1,"259":1,"263":3,"264":4,"266":1,"269":1}}],["passing",{"2":{"98":1,"175":1}}],["pass",{"2":{"22":1,"88":1,"175":2,"183":1,"287":1,"500":1}}],["parlance",{"2":{"703":1}}],["parsing",{"2":{"218":1}}],["parse",{"2":{"52":2,"74":1,"214":2,"218":1,"219":1,"220":3,"222":3,"664":1,"749":1}}],["parity",{"2":{"94":1,"103":1,"224":1,"231":2,"714":3,"748":1}}],["paramount",{"2":{"245":1,"251":1}}],["parametric",{"2":{"94":1}}],["parameterised",{"2":{"666":1}}],["parameterid",{"0":{"472":1,"484":1},"2":{"196":1,"336":3,"337":1,"393":1,"414":2,"472":1,"483":1}}],["parametervaluebox",{"0":{"485":1},"2":{"483":1}}],["parameter",{"0":{"483":1},"2":{"40":1,"57":3,"134":1,"175":1,"238":3,"393":1,"415":2,"452":2,"538":2,"661":1,"705":2,"723":1,"725":1}}],["parameters",{"2":{"6":1,"41":1,"47":1,"57":6,"111":1,"134":1,"137":1,"202":2,"238":3,"239":2,"666":3,"670":1,"671":1,"674":1,"677":1,"678":1,"679":1,"680":1,"681":1,"685":1,"686":1,"687":1,"688":1,"689":1,"690":1,"691":1,"692":1,"693":1,"694":1,"698":1,"701":1,"702":1,"705":1,"707":1,"708":1,"711":1,"712":1,"713":1,"723":2,"725":1,"740":1,"741":1}}],["params",{"2":{"57":3}}],["parallels",{"2":{"39":1}}],["paradigm",{"2":{"37":1,"215":2}}],["partialord",{"2":{"741":1}}],["partially",{"2":{"175":1}}],["parties",{"2":{"247":1,"259":1,"264":1,"650":1}}],["participants",{"2":{"236":1}}],["participates",{"2":{"137":1}}],["participate",{"2":{"28":1}}],["particular",{"2":{"97":1,"99":1,"125":1,"174":1,"229":1,"230":1,"232":1,"253":1,"273":1}}],["particularly",{"2":{"13":1,"67":1,"99":1,"679":1}}],["party",{"2":{"160":1,"245":1,"252":1,"259":1,"268":1,"645":1}}],["parts",{"2":{"28":1}}],["part",{"2":{"12":1,"39":1,"42":1,"56":1,"98":1,"146":1,"160":2,"175":1,"181":1,"185":2,"203":1,"217":1,"247":1,"256":1,"270":2,"725":1,"740":1}}],["pnpm",{"2":{"3":4,"174":3}}],["otp",{"2":{"259":1}}],["otherwise",{"2":{"63":1}}],["others",{"2":{"39":1,"103":1,"126":1,"143":1,"175":1,"203":1,"249":1,"270":1}}],["other",{"0":{"240":1,"282":1},"1":{"241":1,"242":1,"243":1,"244":1},"2":{"0":1,"20":2,"21":1,"22":1,"24":1,"39":1,"41":1,"65":1,"81":1,"87":1,"94":2,"97":1,"102":1,"103":1,"108":2,"111":1,"116":1,"125":1,"126":1,"127":1,"128":1,"131":1,"134":1,"137":3,"141":1,"146":2,"151":1,"153":1,"172":1,"174":2,"200":1,"201":1,"202":1,"207":1,"214":1,"217":1,"221":1,"224":1,"229":1,"230":1,"234":1,"236":2,"243":1,"245":1,"250":1,"255":1,"263":1,"265":1,"272":1,"282":1,"628":2,"630":1,"631":1,"658":2,"714":1}}],["old",{"2":{"229":1,"493":1,"627":1}}],["older",{"2":{"16":1}}],["oh",{"2":{"221":1}}],["omitted",{"2":{"126":1}}],["omit",{"2":{"125":1}}],["occur",{"2":{"123":1,"278":1}}],["occasions",{"2":{"97":1}}],["o",{"2":{"109":1,"176":1,"249":1,"647":1}}],["obvious",{"2":{"273":1,"658":1}}],["obviously",{"2":{"219":1,"273":1}}],["obstacle",{"2":{"264":1}}],["observation",{"2":{"97":1}}],["obtain",{"2":{"176":1,"264":1}}],["obtained",{"2":{"65":1,"125":1,"253":1}}],["objects",{"2":{"29":2,"40":1,"41":3,"42":1,"50":1,"65":1,"201":1,"659":1,"738":1,"746":1}}],["object",{"2":{"25":1,"40":2,"41":1,"50":1,"51":1,"54":1,"98":1,"128":4,"164":4,"175":3,"176":1,"177":1,"178":2,"179":1,"181":1,"186":1,"329":1,"330":1,"331":1,"406":1,"407":1,"408":1,"440":1,"441":1,"442":1,"443":1,"502":1,"503":1,"504":1,"505":1,"506":1,"507":1,"508":1,"510":1,"511":1,"512":1,"513":1,"514":1,"518":1,"519":1,"520":1,"532":1,"533":1,"534":1,"535":1,"536":1,"580":1,"581":1,"582":1,"583":1,"597":1,"598":1,"599":1,"600":1,"601":1,"602":1,"603":1,"629":1,"656":1,"661":1,"741":1,"742":1,"743":1}}],["ownerchanged",{"2":{"305":1,"307":1,"343":1,"345":1}}],["owners",{"2":{"203":1}}],["ownership",{"2":{"137":1,"203":2,"217":1,"658":2}}],["owner",{"2":{"201":1,"203":1,"309":1,"347":1,"663":2,"664":5}}],["owned",{"2":{"52":1,"53":1,"200":3,"201":1,"218":1,"304":1,"342":1}}],["own",{"2":{"56":1,"132":1,"135":2,"136":1,"137":1,"138":1,"139":1,"146":1,"175":1,"185":1,"203":2,"214":1,"217":2,"224":1,"233":1,"247":1,"672":1}}],["ok",{"2":{"53":1,"176":1,"180":3,"214":1,"224":1,"265":1,"717":1,"723":1,"738":1,"746":1}}],["outcome",{"2":{"586":1,"587":1}}],["outdated",{"0":{"272":1},"2":{"248":1,"272":1,"283":1}}],["outlined",{"2":{"253":1}}],["outline",{"2":{"138":1,"229":1,"250":1}}],["outgoing",{"2":{"118":1,"119":1,"147":1,"714":1}}],["outside",{"2":{"56":1,"135":1,"139":1,"672":1}}],["out",{"2":{"39":1,"81":1,"91":1,"101":1,"104":1,"127":1,"143":1,"167":1,"174":1,"185":1,"207":1,"213":1,"215":1,"224":1,"228":1,"253":2,"656":1,"728":1,"735":1}}],["outputframe>",{"2":{"186":1}}],["outputframe",{"2":{"186":1}}],["outputs",{"0":{"181":1,"192":1,"207":1,"215":1,"224":1},"1":{"182":1},"2":{"227":1,"283":1}}],["output",{"2":{"4":1,"5":1,"109":1,"130":1,"134":1,"154":1,"186":2,"187":3,"188":1,"189":1,"190":2,"191":1,"196":1,"200":2,"207":1,"212":1,"238":2,"239":7,"272":1,"666":2}}],["ours",{"2":{"39":1}}],["our",{"2":{"16":1,"18":1,"21":1,"42":1,"94":1,"97":2,"101":1,"103":1,"104":1,"106":1,"107":1,"134":1,"141":1,"175":1,"176":1,"178":1,"181":1,"197":1,"201":1,"203":2,"204":1,"208":1,"217":1,"219":1,"221":1,"228":1,"231":4,"233":1,"253":1,"267":1,"268":2,"270":1,"279":1,"287":2}}],["overflow",{"2":{"430":1}}],["overview",{"2":{"263":1,"287":1}}],["oversee",{"2":{"260":1}}],["overridden",{"2":{"256":1}}],["override",{"2":{"143":1}}],["overkill",{"2":{"252":1}}],["overloading",{"2":{"125":1}}],["over",{"2":{"10":1,"28":1,"191":1,"238":1,"247":1,"252":1,"254":1,"258":1,"656":1,"658":1}}],["overall",{"2":{"6":1,"248":1,"259":1,"268":1}}],["os",{"2":{"6":2,"16":2,"103":1,"109":1,"283":1}}],["ofminutes",{"2":{"186":1}}],["often",{"2":{"109":1,"187":1,"249":1,"706":1}}],["office",{"2":{"258":1}}],["official",{"2":{"168":1,"241":1,"264":1,"714":1}}],["offline",{"2":{"248":1,"267":1,"728":3}}],["offset",{"2":{"88":5}}],["off",{"2":{"21":1,"106":1,"140":1,"158":1,"230":1,"256":1}}],["offering",{"2":{"238":1,"262":1}}],["offers",{"2":{"49":1,"238":1,"263":1,"264":1,"271":1,"274":1,"277":1,"284":1}}],["offer",{"2":{"13":2,"231":1,"269":1,"631":1}}],["of",{"0":{"18":1,"73":1,"85":1,"236":1,"273":1},"1":{"74":1,"75":1,"76":1,"77":1,"78":1,"79":1,"80":1,"86":1,"87":1,"88":1,"89":1,"90":1},"2":{"5":2,"6":6,"10":3,"12":14,"13":1,"14":1,"16":3,"17":2,"18":2,"19":2,"20":1,"21":7,"22":3,"24":3,"27":2,"28":9,"29":1,"31":1,"32":1,"33":2,"36":2,"37":1,"38":3,"39":8,"40":4,"41":5,"42":5,"43":5,"45":1,"49":2,"50":1,"51":1,"52":3,"54":1,"56":5,"57":5,"58":1,"59":1,"62":5,"63":2,"65":11,"66":1,"67":1,"69":1,"70":1,"71":2,"72":1,"75":1,"77":1,"79":4,"80":1,"81":4,"82":2,"83":1,"84":1,"85":4,"86":4,"87":3,"88":2,"89":5,"90":3,"91":1,"92":4,"94":7,"95":1,"97":10,"98":7,"100":4,"101":4,"103":5,"104":3,"105":1,"106":4,"107":2,"108":1,"109":1,"110":2,"111":4,"112":2,"115":1,"117":2,"118":1,"120":2,"121":2,"125":4,"126":2,"127":2,"128":7,"134":4,"135":4,"136":2,"137":14,"138":3,"139":2,"140":1,"141":5,"143":4,"145":1,"146":8,"147":1,"148":2,"149":1,"150":3,"151":2,"154":1,"155":1,"156":1,"157":1,"158":1,"160":3,"161":2,"163":1,"164":4,"166":3,"167":1,"172":1,"174":9,"175":7,"177":3,"178":4,"179":1,"180":3,"181":4,"182":1,"183":1,"185":7,"187":8,"188":2,"189":7,"190":5,"191":2,"192":2,"195":1,"196":6,"197":1,"199":1,"200":6,"201":4,"202":7,"203":5,"204":1,"205":1,"207":3,"210":3,"211":2,"212":4,"213":6,"214":6,"215":4,"217":13,"218":2,"219":5,"220":3,"221":10,"222":3,"224":5,"225":2,"226":3,"227":2,"228":3,"229":4,"230":7,"231":2,"233":2,"234":2,"235":1,"237":3,"238":9,"239":1,"242":1,"243":1,"244":1,"245":2,"246":6,"247":5,"249":17,"250":3,"251":2,"252":21,"253":10,"254":2,"255":4,"256":7,"258":1,"259":6,"260":6,"262":3,"263":4,"264":6,"267":3,"268":7,"269":1,"270":3,"271":1,"272":7,"273":7,"278":1,"279":3,"280":1,"282":4,"283":1,"286":3,"287":4,"626":1,"628":2,"629":2,"630":3,"631":2,"632":1,"633":1,"634":3,"641":1,"643":2,"646":1,"647":1,"652":2,"653":2,"654":1,"655":1,"656":6,"657":1,"658":4,"659":2,"660":3,"663":7,"665":2,"666":7,"669":1,"670":2,"671":1,"672":1,"674":1,"675":1,"679":2,"682":1,"683":1,"684":1,"687":1,"688":1,"691":1,"692":1,"693":1,"694":1,"699":1,"700":3,"703":1,"704":2,"705":2,"706":1,"707":3,"709":1,"710":1,"712":1,"714":1,"717":4,"720":1,"723":3,"725":4,"728":4,"733":1,"735":5,"738":1,"740":2,"746":1,"748":2,"749":7,"750":1}}],["opaque",{"2":{"657":1,"658":1}}],["opsec",{"0":{"248":1},"2":{"247":4,"261":2}}],["opposite",{"2":{"125":1,"254":1,"658":1}}],["opposed",{"2":{"88":1,"668":1,"669":1}}],["opt",{"2":{"105":1,"109":3,"110":1}}],["optimally",{"2":{"146":1}}],["optimizations",{"2":{"137":2}}],["optimising",{"0":{"105":1},"1":{"106":1,"107":1,"108":1,"109":1,"110":1}}],["optimisation",{"2":{"101":1,"105":1,"109":1,"110":1}}],["optimisations",{"2":{"100":1}}],["optimistically",{"2":{"88":1}}],["optimised",{"2":{"83":1,"100":1,"104":1,"238":1}}],["optimises",{"2":{"14":1}}],["optimise",{"0":{"109":1},"2":{"10":1,"97":1,"105":1,"109":1}}],["optionpipelinestatuskind",{"2":{"181":2}}],["optionpipelineentitykind",{"2":{"181":2}}],["optionhash",{"2":{"181":2}}],["optionipfspath",{"2":{"176":2,"181":2}}],["option",{"0":{"125":1,"126":2,"459":1,"460":1,"461":1,"462":1,"463":1,"464":1,"465":1,"466":1,"467":1,"468":1,"469":1,"470":1,"471":2,"472":1,"473":1,"474":1,"475":1,"476":1,"477":1,"478":1,"479":1,"480":1,"481":1,"482":1},"2":{"16":1,"108":1,"124":6,"125":2,"126":8,"143":3,"154":1,"266":1,"267":2,"281":1,"291":1,"304":1,"306":1,"312":1,"322":2,"323":2,"337":1,"342":1,"344":1,"356":2,"404":2,"450":1,"451":1,"458":1,"459":1,"460":1,"461":1,"462":1,"463":1,"464":1,"465":1,"466":1,"467":1,"468":1,"469":1,"470":1,"471":2,"472":1,"473":1,"474":1,"475":1,"476":1,"477":1,"478":1,"479":1,"480":1,"481":1,"482":1,"488":1,"524":1,"528":1,"568":1,"571":1,"572":4,"575":2,"579":1,"587":2,"591":1,"593":1}}],["options",{"0":{"197":1},"2":{"6":1,"13":2,"21":1,"113":1,"124":2,"125":1,"127":1,"143":4,"148":1,"151":1,"153":1,"197":1,"200":2,"214":1,"218":1}}],["optional",{"2":{"2":1,"6":2,"16":1,"38":1,"69":1,"94":1,"126":1,"667":1,"672":1}}],["opera",{"2":{"249":1}}],["operating",{"2":{"264":1}}],["operative",{"2":{"231":1}}],["operational",{"0":{"247":1},"1":{"248":1,"249":1,"250":1},"2":{"167":1,"199":1,"246":1,"247":1,"250":1,"260":1,"261":1}}],["operations",{"0":{"240":1},"1":{"241":1,"242":1,"243":1,"244":1},"2":{"36":1,"62":2,"63":2,"65":1,"100":1,"166":1,"167":1,"187":1,"190":1,"198":2,"238":1,"246":1,"247":1,"249":1,"714":1}}],["operation",{"2":{"36":1,"39":1,"62":3,"63":3,"187":1,"214":1,"219":1,"256":1,"663":1,"715":1,"723":2,"734":1,"744":1,"747":1}}],["operates",{"2":{"39":1,"40":1,"143":1,"217":1}}],["operate",{"0":{"198":1},"1":{"199":1,"200":1,"201":1,"202":1,"203":1,"204":1,"205":1,"206":1,"207":1,"208":1},"2":{"36":1,"101":1,"166":2,"256":1}}],["opened",{"2":{"265":1}}],["openssl",{"2":{"6":1,"170":7,"234":1}}],["open",{"2":{"5":1,"22":1,"187":2,"189":1,"204":1,"211":1,"219":1,"248":1,"249":5,"266":1,"627":1}}],["online",{"2":{"224":1,"254":2,"259":1,"728":1}}],["only",{"2":{"4":1,"14":1,"17":1,"21":1,"24":1,"28":1,"36":1,"39":1,"40":1,"41":1,"42":1,"43":1,"45":1,"56":1,"57":1,"62":4,"63":1,"65":2,"68":1,"69":1,"78":1,"82":1,"83":1,"87":1,"89":1,"90":1,"94":1,"97":1,"116":1,"125":2,"126":3,"127":1,"128":2,"137":2,"141":1,"146":1,"148":1,"154":1,"171":1,"174":2,"175":2,"177":3,"178":2,"187":2,"188":2,"192":1,"200":1,"213":1,"217":1,"220":3,"221":4,"230":1,"234":1,"238":1,"243":1,"248":1,"249":2,"252":2,"255":2,"259":2,"260":2,"261":2,"262":1,"263":1,"264":1,"268":1,"273":1,"282":1,"628":1,"650":1,"656":2,"663":2,"669":1,"700":1,"723":1,"725":1,"750":1}}],["ongoing",{"2":{"197":1,"260":1}}],["on=0",{"2":{"196":1}}],["onbeforeunmount",{"2":{"181":2}}],["onto",{"2":{"96":1,"263":1}}],["once",{"2":{"43":1,"62":2,"65":1,"84":1,"90":1,"106":1,"137":1,"141":1,"167":1,"196":1,"201":1,"212":1,"217":1,"221":3,"264":1,"266":1,"446":1,"633":1,"665":1}}],["on",{"0":{"13":1,"18":1,"256":1,"272":1},"1":{"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1},"2":{"5":1,"6":2,"12":1,"13":2,"14":1,"16":3,"18":3,"20":1,"21":1,"22":2,"36":3,"39":3,"40":1,"41":3,"42":3,"44":1,"49":1,"55":1,"56":1,"62":1,"65":4,"67":1,"69":1,"78":1,"79":1,"85":1,"87":1,"88":1,"94":2,"97":1,"99":1,"101":2,"103":2,"104":1,"106":5,"110":1,"115":1,"135":1,"136":2,"137":5,"139":1,"141":3,"145":1,"146":1,"163":1,"166":1,"167":1,"168":2,"169":1,"170":2,"171":1,"174":2,"175":9,"178":1,"181":1,"183":1,"185":3,"187":1,"192":1,"196":1,"198":1,"200":1,"207":1,"208":1,"211":1,"214":1,"215":1,"217":3,"218":1,"219":2,"224":1,"230":2,"232":2,"233":1,"234":1,"238":1,"241":1,"242":2,"243":1,"244":1,"246":1,"247":1,"248":1,"249":7,"252":2,"253":1,"256":4,"258":1,"259":2,"260":1,"261":1,"262":2,"263":3,"264":3,"272":2,"273":2,"278":1,"283":2,"628":1,"629":2,"631":2,"642":1,"646":1,"651":1,"656":1,"658":2,"659":1,"661":1,"662":1,"663":1,"664":1,"666":1,"667":1,"683":1,"684":1,"703":1,"709":1,"714":1,"725":1,"728":1,"735":2,"741":1,"749":1}}],["ones",{"2":{"67":1,"90":1,"126":1,"127":1}}],["one",{"2":{"5":2,"6":2,"18":1,"20":1,"27":1,"33":1,"42":1,"43":2,"49":1,"50":2,"62":3,"67":1,"87":1,"88":1,"90":1,"97":1,"105":1,"126":1,"128":2,"134":1,"135":3,"137":1,"141":1,"160":2,"163":1,"175":1,"202":1,"203":3,"204":1,"214":1,"215":1,"217":2,"221":2,"226":1,"227":1,"229":1,"238":2,"242":1,"243":1,"244":1,"246":1,"248":1,"249":3,"250":1,"256":2,"268":2,"272":2,"282":2,"628":1,"656":1,"666":3,"683":1,"720":1,"723":1,"728":2,"748":1}}],["ord",{"2":{"741":1}}],["ordered",{"2":{"741":1}}],["order",{"2":{"18":2,"49":2,"78":1,"96":1,"138":1,"146":1,"159":1,"187":1,"212":1,"215":1,"217":1,"227":1,"658":1,"728":1}}],["origin",{"2":{"196":1}}],["original",{"2":{"18":1,"21":1,"42":1,"221":1,"230":1,"232":1}}],["organisation",{"2":{"699":1}}],["organisations",{"0":{"260":1},"2":{"257":1}}],["organization",{"2":{"260":1}}],["organizational",{"2":{"260":1}}],["organizations",{"2":{"137":1,"245":1,"246":1,"247":1,"250":1,"252":1,"259":1}}],["org",{"2":{"185":3,"186":7,"193":2}}],["or",{"0":{"639":1},"2":{"2":1,"6":1,"8":2,"13":2,"16":3,"20":1,"21":2,"24":1,"25":1,"27":1,"28":1,"31":1,"32":3,"33":1,"36":1,"38":2,"39":1,"40":2,"42":1,"43":1,"44":1,"45":1,"50":2,"51":4,"55":1,"56":3,"57":1,"62":5,"63":2,"65":1,"71":1,"72":2,"76":1,"80":1,"84":1,"94":3,"97":2,"100":1,"108":1,"109":1,"111":2,"119":1,"124":1,"125":2,"126":2,"127":3,"128":2,"129":1,"135":3,"136":1,"137":3,"139":1,"141":2,"143":3,"148":1,"151":1,"153":1,"154":1,"155":1,"160":2,"170":1,"174":3,"175":3,"178":3,"186":1,"189":2,"196":1,"200":3,"211":1,"214":2,"218":2,"219":3,"221":2,"225":1,"226":1,"228":1,"230":2,"232":1,"242":1,"244":1,"245":1,"246":1,"247":1,"248":2,"249":2,"250":8,"252":3,"253":4,"258":3,"259":4,"260":3,"263":2,"264":1,"265":1,"266":1,"268":1,"270":1,"272":1,"273":2,"281":1,"286":1,"405":1,"626":1,"628":1,"646":1,"650":1,"658":1,"660":1,"661":2,"666":4,"672":1,"684":1,"728":2,"740":1,"747":1,"750":1}}],["e70121022a9d6e0d54022c0e2752e43add91ada28259e1f2ce0c6d4e9183fb2882de6749",{"2":{"239":1}}],["eq",{"2":{"220":1}}],["equal",{"2":{"28":1,"628":1,"630":1,"723":1}}],["equals",{"2":{"18":1}}],["ee",{"2":{"181":1,"183":1}}],["ecc",{"2":{"238":2}}],["ec99f8b99825",{"2":{"196":1}}],["echo",{"2":{"174":1,"244":2}}],["ecosystem",{"2":{"173":1,"262":1}}],["economical",{"2":{"89":1}}],["eloquently",{"2":{"253":1}}],["elf",{"2":{"241":1}}],["else",{"2":{"171":1,"273":1}}],["element",{"2":{"666":1}}],["election",{"2":{"652":1}}],["electron",{"2":{"249":1}}],["electromagnetic",{"2":{"248":1}}],["elected",{"2":{"112":1,"653":1}}],["elevated",{"2":{"128":1}}],["especially",{"2":{"249":1,"258":1,"259":1,"278":1,"706":1}}],["estimation",{"2":{"207":3,"323":1}}],["establishes",{"2":{"255":1}}],["established",{"2":{"249":1,"260":1,"734":1,"744":1,"747":1}}],["establishing",{"2":{"245":1,"246":1,"250":1,"260":1,"720":1,"730":1}}],["establish",{"2":{"166":1,"202":1,"248":1,"250":1,"258":1,"260":1,"280":1}}],["esm",{"2":{"174":1}}],["essentially",{"2":{"85":1,"137":1,"247":1}}],["essential",{"2":{"4":1,"245":1,"249":1,"250":1}}],["ergonomic",{"2":{"231":1}}],["ergonomics",{"2":{"97":1}}],["err",{"2":{"219":2,"221":1,"224":3}}],["errors",{"2":{"176":1,"221":1,"273":1}}],["error",{"2":{"6":1,"13":1,"19":1,"125":1,"126":1,"127":2,"153":4,"171":1,"175":1,"176":2,"178":1,"214":1,"219":1,"272":3,"273":2,"282":1,"283":2,"286":1,"427":1,"579":1,"741":7}}],["erasing",{"2":{"212":1}}],["eyed",{"2":{"97":1}}],["efficiency",{"2":{"238":2}}],["efficient",{"2":{"97":1,"101":1,"165":1,"238":1,"263":1}}],["effortlessly",{"2":{"263":1}}],["efforts",{"2":{"109":1,"287":1}}],["effort",{"2":{"88":1,"97":1,"658":1}}],["effective",{"2":{"250":1}}],["effectively",{"2":{"21":1,"25":1,"89":1,"250":1,"256":1,"262":1,"749":1}}],["effect",{"2":{"8":1,"9":1}}],["ethereum",{"2":{"86":1}}],["etc",{"2":{"18":1,"88":1,"143":1,"165":2,"166":1,"217":1,"246":1,"249":1,"252":1,"254":1,"287":1,"638":1,"639":1,"642":1,"714":1}}],["epoch",{"2":{"57":1,"112":1,"653":1}}],["emerging",{"2":{"260":1}}],["emergency",{"2":{"250":1}}],["embrace",{"2":{"260":1}}],["embedded",{"2":{"232":1}}],["emails",{"2":{"259":3}}],["email",{"2":{"249":2,"254":1,"259":2}}],["emojis",{"2":{"238":1}}],["emperor",{"0":{"636":1},"2":{"626":1}}],["employee",{"2":{"260":1}}],["employees",{"2":{"247":1,"250":1,"260":8}}],["employ",{"2":{"176":1,"260":1}}],["employs",{"2":{"176":1,"254":1}}],["emphasised",{"2":{"176":1,"178":1}}],["emptypath",{"2":{"438":1}}],["empty",{"2":{"128":1,"196":1,"220":1,"221":1}}],["emptied",{"2":{"28":1}}],["emulated",{"2":{"97":1}}],["emulate",{"2":{"89":1}}],["emits",{"2":{"709":1}}],["emit",{"2":{"72":1}}],["emitted",{"2":{"31":1,"32":1,"33":1,"34":1,"35":1,"51":2,"82":1,"97":1}}],["evaluation",{"2":{"260":1}}],["evaluate",{"2":{"260":1,"418":1}}],["evaluatestoassetid",{"2":{"179":3}}],["evaluatestovalue",{"2":{"178":2,"179":2}}],["evaluatestoidbox",{"2":{"178":2,"179":3}}],["evaluatestoregistrablebox",{"2":{"176":2,"177":2,"178":2,"181":2}}],["evaluatesto",{"2":{"36":2}}],["evolving",{"2":{"252":1,"260":1}}],["evolves",{"2":{"250":1}}],["evident",{"2":{"229":1}}],["evil™",{"2":{"28":2}}],["evil",{"2":{"28":1}}],["everyday",{"2":{"249":2}}],["everyone",{"2":{"158":1}}],["every",{"2":{"18":1,"24":2,"82":1,"106":1,"135":1,"137":1,"143":1,"153":1,"217":1,"219":1,"256":2,"263":1,"265":1,"282":1,"648":1,"656":2,"683":1,"709":1}}],["everything",{"2":{"18":2,"42":3,"94":1,"101":1,"103":1,"153":1,"174":1,"214":1,"251":1,"258":1,"656":1}}],["eventmessage",{"0":{"351":1},"2":{"730":1}}],["eventbox",{"0":{"349":1,"607":1},"2":{"325":1,"351":1,"607":1}}],["eventdata",{"2":{"181":2}}],["eventlistener",{"2":{"181":4}}],["eventfilterbox",{"0":{"350":1,"608":1},"2":{"352":1,"608":1}}],["eventfilters",{"2":{"97":3}}],["eventfilter",{"2":{"72":1,"75":1,"79":1,"94":1,"99":1,"192":4,"215":4}}],["event",{"0":{"91":1,"94":1},"1":{"92":1,"93":1,"94":1,"95":1,"96":1,"97":1},"2":{"32":2,"51":1,"65":1,"72":1,"79":2,"82":1,"85":2,"87":3,"89":1,"91":1,"94":3,"97":6,"181":3,"192":2,"200":1,"207":1,"215":8,"224":5,"233":2,"250":1,"266":1,"291":1,"306":1,"312":1,"325":1,"337":1,"344":1,"360":1,"488":1,"524":1,"591":1,"642":1,"646":1,"709":3,"728":1}}],["eventsubscriptionrequest",{"0":{"352":1},"2":{"730":1}}],["events",{"0":{"31":1,"32":1,"33":1,"34":1,"35":1,"727":1,"728":1},"1":{"32":1,"33":1,"34":1,"35":1,"728":1,"729":2,"730":2,"732":1,"733":1,"735":1,"737":1,"738":1,"740":1,"741":1},"2":{"31":6,"32":1,"33":2,"34":1,"35":1,"37":1,"38":1,"51":1,"65":1,"72":3,"79":1,"82":2,"83":2,"86":3,"87":1,"94":1,"97":3,"98":2,"172":1,"175":1,"181":5,"192":4,"196":1,"200":1,"204":2,"207":6,"215":2,"224":3,"268":1,"727":1,"728":1,"729":1}}],["eventually",{"2":{"28":1}}],["even",{"2":{"5":1,"106":1,"128":1,"134":1,"135":1,"178":1,"197":1,"230":1,"232":1,"248":2,"249":1,"250":1,"252":2,"256":1,"259":2,"268":1,"273":1,"656":1}}],["educated",{"2":{"268":1}}],["educate",{"2":{"260":1}}],["edge",{"2":{"249":1}}],["eddsa",{"2":{"185":1,"238":1}}],["ed0120b678073cfae6e247a58b442661c7da0e13bac5031cbc6343ef566b8718d47d04",{"2":{"239":4}}],["ed01206b0f56f58761060056355dba0e0fc489cfb2f974481ed64873082e6032796235",{"2":{"239":1}}],["ed012004ff5b81046ddccf19e2e451c45dfb6f53759d4eb30fa2efa807284d1cc33016",{"2":{"202":1}}],["ed0120e9f632d3034bab6bb26d92ac8fd93ef878d9c5e69e01b61b4c47101884ee2f99",{"2":{"202":1}}],["ed0120e555d194e8822da35ac541ce9eec8b45058f4d294d9426ef97ba92698766f7d3",{"2":{"175":1}}],["ed0120aba0446cfbd4e12627ffa870fb37993ed83eb1ae0588184b90d832a64c24c379",{"2":{"202":3,"203":2,"204":2,"205":1,"206":1}}],["ed0120ce7fa46c9dce7ea4b125e2e36bdb63ea33073e7590ac92816ae1e861b7048b03",{"2":{"200":1,"201":1,"202":1,"203":1,"204":2,"205":1}}],["ed0120cc25624d62896d3a0bfd8940f928dc2abf27cc57cefeb442aa96d9081aae58a1",{"2":{"18":5,"146":1}}],["ed01204164bf554923ece1fd412d241036d863a6ae430476c898248b8237d77534cfc4",{"2":{"200":2,"202":1}}],["ed01207233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0",{"2":{"20":1,"128":4,"164":3,"181":1,"218":1}}],["ed01203f4e3e98571b55514edc5ccf7e53ca7509d89b2868e62921180a6f57c2f4e255",{"2":{"18":4}}],["ed01208e351a70b6a603ed285d666b8d689b680865913ba03ce29fb7d13a166c4e7f1f",{"2":{"18":5,"146":1}}],["ed0120faca9e8aa83225cb4d16d67f27dd4f93fc30ffa11adc1f5c88fd5495ecc91020",{"2":{"18":5,"146":1}}],["ed01201c61faf8fe94e253b93114240394f79a607b7fa55f9e5a41ebec74b88055768b",{"2":{"18":5,"146":1}}],["ed25519",{"2":{"18":5,"20":1,"141":1,"175":1,"181":1,"218":1,"238":6,"239":5,"298":1}}],["editable",{"2":{"137":1}}],["edition",{"2":{"103":1}}],["editing",{"2":{"22":1}}],["edit",{"2":{"5":1,"137":1,"663":1}}],["ea01610402a54abcc40819f15e3553cc8d42d628eead7e1b10724bd2afe523a7c0446eb1cb3f14d4500bd68c997784136fd056ba04215dfd2d3fdc7883b43ae94ac52b7d01525f5a80b41c01701502b46dbb9f0384cc7be037dc2cbc928014e52a4c5c3b",{"2":{"239":1}}],["earlier",{"2":{"88":1,"101":1}}],["early",{"2":{"88":1}}],["easily",{"2":{"88":1,"137":1,"224":1,"250":1,"253":1,"268":1,"630":1}}],["easier",{"2":{"14":1,"97":1,"101":1,"176":1,"187":1,"282":1}}],["easiest",{"2":{"13":1,"211":1,"242":1}}],["easy",{"2":{"16":1,"74":1,"97":1,"100":1,"219":1,"231":1,"234":2,"254":1}}],["each",{"2":{"3":1,"18":1,"21":2,"28":1,"36":1,"39":1,"40":2,"41":2,"62":1,"63":1,"65":1,"84":1,"85":1,"88":1,"97":1,"121":1,"135":1,"137":4,"143":1,"146":1,"174":1,"175":1,"181":1,"200":1,"217":1,"228":1,"233":1,"238":1,"268":1,"285":1,"287":2,"640":1,"643":1,"666":2,"704":1,"742":1,"743":1}}],["e300886e76c777776efad1e2f5cb245bfb8ed02e",{"2":{"5":2}}],["enforced",{"2":{"656":1}}],["enforce",{"2":{"260":1}}],["ensuring",{"2":{"253":1}}],["ensuredomainexistence",{"2":{"176":2}}],["ensure",{"2":{"167":1,"176":2,"235":1,"250":1,"251":1,"257":1,"258":1,"260":3,"287":1,"658":1}}],["ensures",{"2":{"127":1,"249":1,"250":2,"255":1,"267":1}}],["english",{"2":{"252":1,"253":1}}],["engineering",{"2":{"261":1}}],["engine",{"2":{"155":1}}],["enabling",{"2":{"249":1,"254":1,"263":1,"266":1}}],["enabled",{"2":{"249":1,"715":1,"734":1,"744":1,"747":1}}],["enable",{"2":{"3":1,"203":1,"249":1,"265":1,"268":1,"658":1}}],["enhancement",{"2":{"260":1}}],["enhanced",{"2":{"249":2,"264":1}}],["enhance",{"2":{"249":1,"250":1,"260":3,"264":1}}],["enhancing",{"2":{"248":1,"252":1}}],["enough",{"2":{"248":1,"252":1,"282":1}}],["enormous",{"2":{"137":1}}],["encoding",{"2":{"714":1,"715":1,"718":1,"721":1,"724":1,"727":1,"731":1,"734":1,"736":1,"739":1,"744":1,"747":1,"748":1,"751":1}}],["encoded",{"2":{"28":1,"39":1,"120":1,"134":2,"150":1,"273":1,"714":1,"738":1,"748":2,"749":2}}],["encounter",{"2":{"272":1,"283":1,"285":1}}],["encountered",{"2":{"252":1}}],["encourages",{"2":{"260":1}}],["encourage",{"2":{"260":1}}],["encrypted",{"2":{"254":1,"255":2,"258":1}}],["encrypt",{"2":{"248":2}}],["encrypting",{"2":{"247":1,"248":1}}],["encryption",{"0":{"255":1},"2":{"238":2,"246":1,"255":1}}],["enjoy",{"2":{"232":1}}],["env",{"2":{"113":1,"164":1,"196":1}}],["environments",{"2":{"238":1}}],["environment",{"0":{"9":1,"16":1,"20":1,"107":1},"2":{"6":1,"9":1,"13":2,"16":3,"18":5,"78":1,"107":1,"125":4,"126":2,"127":1,"135":1,"143":2,"146":1,"151":1,"174":2,"175":1,"183":2,"186":1,"256":1,"286":1,"655":1}}],["enum",{"2":{"176":3,"180":10,"181":2,"183":1,"217":1,"219":1,"290":1,"294":1,"298":1,"305":1,"311":1,"315":1,"316":1,"317":1,"319":1,"326":1,"327":1,"332":1,"336":1,"339":1,"340":1,"341":1,"343":1,"349":1,"350":1,"353":1,"357":1,"359":1,"393":1,"405":1,"409":1,"414":1,"415":1,"416":1,"417":1,"418":1,"420":1,"421":1,"427":1,"430":1,"438":1,"439":1,"444":1,"445":1,"446":1,"485":1,"487":1,"494":1,"495":1,"497":1,"498":1,"499":1,"500":1,"509":1,"515":1,"516":1,"521":1,"523":1,"531":1,"537":1,"540":1,"546":1,"548":1,"550":1,"553":1,"567":1,"577":1,"578":1,"584":1,"588":1,"589":1,"590":1,"595":1,"596":1,"604":1,"606":1,"705":1,"707":1}}],["enumeration",{"2":{"77":1}}],["enums",{"2":{"50":1}}],["endswith",{"2":{"567":1}}],["endian",{"2":{"174":1}}],["ending",{"2":{"137":1}}],["end",{"2":{"79":1,"192":1,"658":1}}],["endpoints",{"0":{"714":1},"1":{"715":1,"716":1,"717":1,"718":1,"719":1,"720":1,"721":1,"722":1,"723":1,"724":1,"725":1,"726":1,"727":1,"728":1,"729":1,"730":1,"731":1,"732":1,"733":1,"734":1,"735":1,"736":1,"737":1,"738":1,"739":1,"740":1,"741":1,"742":1,"743":1,"744":1,"745":1,"746":1,"747":1,"748":1,"749":1,"750":1,"751":1,"752":1,"753":1},"2":{"11":1,"175":4}}],["endpoint",{"0":{"11":1},"2":{"18":1,"120":1,"125":1,"150":1,"161":1,"183":2,"704":1,"714":1,"715":1,"716":1,"718":1,"719":2,"721":1,"722":1,"724":1,"725":1,"727":1,"729":2,"731":1,"732":1,"734":1,"736":1,"737":1,"739":1,"740":1,"744":1,"745":1,"747":1,"748":2,"750":1,"751":1,"752":1}}],["endregion",{"2":{"4":1}}],["entails",{"2":{"256":1,"282":1,"652":1}}],["entail",{"2":{"252":1}}],["entries",{"2":{"266":1}}],["entropy=log",{"2":{"252":1}}],["entropy=log2​",{"2":{"252":1}}],["entropy=log2",{"2":{"252":1}}],["entropy",{"2":{"246":1,"252":14,"253":3}}],["entrytoobig",{"2":{"438":1}}],["entry",{"2":{"69":1,"104":1,"260":1,"265":5,"428":1}}],["entities",{"2":{"33":1,"69":1,"111":1,"167":1,"201":1,"626":1}}],["entity=pipeline",{"2":{"215":1}}],["entitytype",{"2":{"192":1,"215":1}}],["entityfilters",{"2":{"38":1}}],["entityfilter",{"2":{"38":2,"94":3}}],["entity",{"2":{"32":2,"33":1,"38":1,"40":1,"42":2,"72":2,"111":1,"137":2,"181":1,"656":1,"661":1}}],["entirely",{"2":{"65":1,"108":1,"212":2,"232":1}}],["entire",{"2":{"4":1,"221":1,"746":1}}],["entering",{"2":{"263":1}}],["enter",{"2":{"6":1,"65":1,"153":1,"171":1,"260":1}}],["e",{"2":{"3":1,"9":1,"21":1,"31":1,"38":1,"39":1,"41":1,"42":2,"56":1,"65":1,"81":1,"84":1,"88":3,"108":1,"125":1,"141":1,"166":1,"175":1,"181":1,"183":1,"215":1,"219":1,"230":1,"238":2,"247":5,"249":1,"250":1,"252":2,"256":1,"259":1,"273":2,"282":1,"663":1,"666":1,"683":1,"720":1,"723":1,"728":1}}],["exhaustive",{"2":{"253":1}}],["exemplar",{"0":{"639":1},"2":{"626":1}}],["exemplary",{"2":{"231":1}}],["exercise",{"2":{"249":1,"259":1}}],["executoreventset",{"0":{"361":1},"2":{"360":1}}],["executoreventfilter",{"0":{"360":1},"2":{"341":1}}],["executorevent",{"0":{"359":1},"2":{"340":1}}],["executor",{"0":{"358":1},"2":{"128":2,"164":2,"340":1,"341":1,"605":2,"664":2}}],["executormaxmemory=524288000",{"2":{"128":1,"164":1}}],["executorfuellimit=55000000",{"2":{"128":1,"164":1}}],["executing",{"2":{"72":1,"192":1,"198":1,"224":1}}],["executiontime",{"0":{"357":1},"2":{"569":1}}],["executionexception",{"2":{"193":3}}],["execution",{"0":{"35":1},"2":{"31":1,"35":1,"36":1,"62":2,"72":1,"78":2,"84":1,"89":1,"97":4,"141":1,"236":1,"655":1,"700":1}}],["executes",{"2":{"100":1}}],["execute",{"2":{"36":1,"40":1,"41":1,"48":1,"49":4,"88":1,"97":2,"98":1,"104":3,"211":1,"661":1,"741":1}}],["executetriggereventfilter",{"0":{"356":1},"2":{"350":1,"595":1}}],["executetriggerevent",{"0":{"355":1},"2":{"349":1}}],["executetrigger",{"0":{"48":1,"354":1},"2":{"35":1,"40":1,"41":1,"349":1,"350":1,"416":2,"420":1,"595":1,"661":1}}],["executed",{"2":{"32":1,"35":1,"62":2,"71":1,"81":1,"87":2,"88":5,"90":2,"97":2,"98":2,"201":1,"253":1}}],["executable",{"0":{"76":1,"353":1},"2":{"16":2,"72":1,"75":2,"76":1,"93":1,"95":1,"97":1,"98":1,"101":1,"175":2,"176":2,"181":2,"241":1,"297":2,"575":1}}],["exec",{"2":{"6":1,"175":2}}],["exchange",{"0":{"720":1,"730":1},"2":{"238":1,"719":1,"729":1}}],["excess",{"2":{"137":1}}],["except",{"2":{"137":1,"153":1,"213":1,"658":1,"749":1}}],["exceptional",{"2":{"656":1}}],["exception",{"2":{"21":1,"193":4,"211":1,"628":1,"656":1}}],["excluding",{"2":{"110":1}}],["excludes",{"2":{"161":1}}],["exclude",{"2":{"108":1}}],["exorbitant",{"2":{"67":1}}],["exotic",{"2":{"13":1,"90":1}}],["existence",{"2":{"221":1,"707":1}}],["exists",{"2":{"78":1,"137":1,"177":1,"178":1,"196":1,"213":1,"220":1}}],["exist",{"2":{"62":1,"116":1,"154":1,"221":1}}],["existing",{"2":{"28":1,"70":1,"104":2,"177":1,"188":1,"213":1,"217":1,"220":1,"238":1,"656":1}}],["exited",{"2":{"272":1}}],["exit",{"2":{"6":1}}],["examine",{"2":{"253":1}}],["examples",{"0":{"239":1},"2":{"12":1,"43":1,"57":1,"146":1,"252":1,"260":1,"749":2,"750":1}}],["example",{"0":{"5":1,"91":1,"102":1,"657":1,"664":1},"1":{"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"103":1,"104":1},"2":{"2":1,"5":2,"6":1,"9":1,"12":1,"18":1,"29":1,"36":1,"39":1,"41":3,"44":1,"52":1,"53":2,"65":1,"66":2,"71":2,"97":1,"119":1,"121":1,"122":1,"126":1,"128":3,"134":1,"136":1,"137":1,"143":1,"146":1,"171":1,"174":6,"175":3,"179":1,"183":1,"185":1,"187":1,"210":2,"211":1,"212":1,"217":3,"219":1,"238":1,"249":1,"259":1,"264":1,"273":1,"278":1,"630":1,"657":2,"658":1,"664":2,"670":1,"679":1,"717":1,"723":1,"725":1,"733":1,"735":2,"749":1}}],["exact",{"2":{"28":1,"62":1,"239":3}}],["exactly",{"2":{"18":1,"24":1,"77":1,"84":2,"94":1,"97":1,"272":1,"516":1}}],["extremely",{"2":{"154":1,"232":1}}],["extraneous",{"2":{"135":1}}],["extra",{"2":{"16":1,"137":1}}],["extensively",{"2":{"235":1}}],["extensive",{"2":{"187":1,"217":1,"232":1,"247":1,"253":1}}],["extensions",{"2":{"143":1,"249":5,"645":1}}],["extension",{"2":{"143":1,"253":1}}],["extended",{"2":{"590":1,"592":1}}],["extends",{"2":{"143":2,"193":1}}],["extend",{"2":{"143":1}}],["extent",{"2":{"14":1}}],["external",{"2":{"241":1,"259":1,"260":1}}],["extern",{"2":{"104":1,"657":1}}],["expr",{"2":{"222":2}}],["expression",{"2":{"36":1,"62":1,"101":1,"104":1,"176":3,"177":3,"178":8,"179":5,"181":3,"212":2,"213":1,"214":2,"664":4}}],["expressions",{"0":{"36":1},"2":{"36":2,"62":1}}],["expanding",{"2":{"252":1,"253":1}}],["expanded",{"2":{"252":2}}],["expand",{"2":{"187":2,"188":1,"189":1,"190":1,"191":1,"230":1,"666":1}}],["exposing",{"2":{"243":1}}],["expose",{"2":{"175":1,"286":1}}],["exposes",{"2":{"103":1}}],["exponent",{"2":{"143":1}}],["export",{"2":{"16":6,"181":3,"244":2,"657":1}}],["expired",{"2":{"578":1,"710":1}}],["expire",{"2":{"56":1}}],["experts",{"2":{"260":1}}],["experiencing",{"2":{"218":1,"271":1,"274":1,"277":1,"284":1,"285":1}}],["experienced",{"2":{"226":1}}],["experience",{"2":{"6":1,"13":1,"19":1,"97":1,"225":1}}],["experiment",{"2":{"217":2}}],["expensive",{"2":{"232":1}}],["expected",{"0":{"266":1},"2":{"187":2,"188":1,"189":1,"190":1,"191":1,"200":2,"201":1,"202":1,"203":1,"204":2,"207":1,"263":1,"447":1}}],["expects",{"2":{"175":1,"725":1,"740":1,"752":1}}],["expect",{"2":{"53":1,"106":1,"211":1,"220":1,"221":1}}],["exploit",{"2":{"259":1}}],["exploring",{"2":{"167":1}}],["explore",{"0":{"167":1},"2":{"208":1,"655":1}}],["explorers",{"2":{"706":1}}],["explorer",{"2":{"88":1}}],["explicit",{"2":{"214":2,"219":2}}],["explicitly",{"2":{"2":1,"56":1,"139":1,"176":1,"244":1,"672":1}}],["explains",{"2":{"194":1,"257":1}}],["explain",{"2":{"124":1,"185":1,"217":1,"288":1}}],["explained",{"2":{"101":1,"131":1}}],["explanatory",{"2":{"116":1}}],["explanation",{"2":{"6":1,"286":1}}],["either",{"2":{"2":1,"16":1,"25":1,"32":1,"38":1,"39":1,"45":1,"63":1,"72":1,"76":1,"84":1,"94":2,"97":1,"116":1,"125":2,"127":1,"128":1,"135":1,"148":1,"153":1,"196":1,"218":1,"219":1,"226":1,"249":1,"252":1,"272":1,"273":1,"646":1,"666":2,"728":2}}],["hmac",{"2":{"268":1}}],["html",{"2":{"259":1,"714":1}}],["http",{"2":{"2":1,"12":1,"18":1,"117":1,"119":2,"120":1,"175":11,"181":2,"187":2,"637":1,"714":1,"715":1,"718":1,"721":1,"724":1,"727":1,"731":1,"734":1,"736":1,"739":1,"744":1,"747":1,"751":1}}],["https",{"2":{"2":1,"5":2,"103":1,"119":1,"171":1,"172":2,"174":1,"185":1,"210":1,"714":1}}],["h",{"2":{"200":1,"238":1,"253":4}}],["hundred",{"2":{"204":1}}],["hub",{"2":{"196":1}}],["human",{"2":{"150":1}}],["hr>",{"2":{"181":2}}],["h3>listening",{"2":{"181":1}}],["h3>create",{"2":{"181":1}}],["h3>",{"2":{"181":3}}],["h3>status",{"2":{"181":1}}],["hijiri",{"0":{"644":1},"1":{"647":1},"2":{"626":1}}],["hiring",{"2":{"260":1}}],["hinges",{"2":{"252":1}}],["hit",{"2":{"248":1}}],["highest",{"2":{"267":1}}],["higher",{"2":{"252":1,"253":1,"279":1}}],["high",{"2":{"238":2,"249":1,"252":2,"253":1}}],["highlight",{"2":{"229":1}}],["highly",{"2":{"67":1,"82":1,"101":1,"109":1,"176":1,"234":1,"249":2,"254":1}}],["histogram",{"2":{"735":1}}],["history",{"2":{"69":1,"185":1,"249":1}}],["his",{"2":{"214":1}}],["him",{"2":{"178":1}}],["hierarchy",{"2":{"165":1}}],["hidden",{"2":{"127":1,"218":1,"249":1}}],["half",{"2":{"177":1,"213":1,"220":1,"253":1}}],["harm",{"2":{"644":1}}],["hare",{"2":{"91":1,"92":5}}],["hardware",{"0":{"268":1},"2":{"232":1,"248":2,"250":1,"268":5}}],["hard",{"2":{"39":1,"42":1,"178":1,"247":1,"253":1}}],["harder",{"2":{"16":1,"104":1,"163":1,"248":1,"249":1,"252":1}}],["hack",{"2":{"89":1}}],["happy",{"2":{"88":1}}],["happened",{"2":{"215":1}}],["happening",{"2":{"174":1}}],["happen",{"2":{"31":1,"212":1,"281":1}}],["happens",{"2":{"28":1,"125":1,"137":1,"272":1}}],["hatter",{"2":{"91":1,"92":6,"93":4,"97":1,"104":2,"117":1,"256":4}}],["hats",{"2":{"52":1}}],["hat",{"2":{"52":10}}],["handshake",{"0":{"719":1,"729":1},"2":{"162":1,"719":1,"729":1}}],["handling",{"2":{"118":1,"119":1,"147":1,"637":1,"714":2}}],["handles",{"2":{"175":1,"263":1,"638":1,"719":1,"729":1}}],["handled",{"2":{"100":1}}],["handle",{"2":{"34":1,"137":1,"256":1,"657":1}}],["hand",{"2":{"41":1,"87":1,"127":1,"137":1,"234":1,"273":1}}],["hada",{"2":{"174":1}}],["had",{"2":{"28":1,"92":1,"100":1,"178":1,"188":1,"278":1}}],["having",{"2":{"16":2,"21":1,"56":2,"65":1,"120":1,"150":1,"154":1,"217":2,"243":1,"249":1,"256":1}}],["haven",{"2":{"178":1,"215":1}}],["have",{"2":{"13":2,"14":1,"16":1,"18":4,"21":1,"22":2,"25":2,"28":1,"39":1,"40":1,"41":1,"43":1,"44":1,"56":1,"57":1,"62":1,"69":2,"78":1,"84":1,"88":3,"92":2,"97":3,"100":1,"101":1,"102":1,"103":1,"104":2,"122":1,"124":1,"125":2,"128":1,"135":1,"137":4,"139":1,"141":3,"143":2,"151":1,"156":1,"160":1,"161":1,"166":1,"167":1,"175":4,"176":1,"177":2,"178":1,"183":1,"185":1,"186":2,"188":2,"190":1,"201":1,"202":1,"203":1,"204":1,"213":2,"214":4,"215":1,"217":4,"219":1,"220":2,"221":1,"226":1,"229":1,"231":1,"232":1,"242":1,"248":1,"249":2,"252":1,"256":1,"258":1,"260":1,"262":1,"263":1,"268":1,"270":2,"272":2,"279":3,"280":1,"281":1,"282":3,"286":1,"631":1,"644":1,"650":1,"656":1,"660":2,"666":1,"672":2,"679":1,"681":1,"683":1,"688":1,"690":1,"699":1,"710":1,"741":1,"753":1}}],["hasn",{"2":{"248":1}}],["hashof",{"0":{"411":1,"412":1,"413":1,"465":1,"466":1,"467":1},"2":{"321":1,"323":2,"390":1,"393":2,"399":1,"431":1,"465":1,"466":1,"467":1,"571":1,"572":1,"576":1}}],["hashtopolis",{"2":{"253":1}}],["hash=none",{"2":{"215":1}}],["hash=a638001762e365280677a5407bac9adaa119c8cb82c8afe377b72f85e71ed4a9",{"2":{"196":4}}],["hashmap",{"2":{"193":2}}],["hashes",{"2":{"123":1}}],["hash",{"0":{"410":1,"640":1},"2":{"28":1,"32":1,"181":8,"185":2,"192":6,"207":9,"212":1,"215":4,"218":1,"273":2,"321":1,"323":2,"390":1,"399":1,"411":1,"412":1,"413":1,"571":1,"572":1,"576":1,"626":1,"698":2,"708":2}}],["has",{"2":{"2":1,"6":1,"18":1,"24":1,"28":1,"29":2,"36":1,"42":1,"43":1,"46":1,"62":1,"63":1,"73":1,"79":1,"88":1,"92":1,"94":3,"97":1,"104":1,"125":1,"128":2,"135":1,"141":2,"146":1,"174":2,"175":1,"178":2,"180":4,"188":2,"189":2,"196":1,"210":2,"211":1,"214":3,"219":2,"220":1,"221":5,"231":1,"233":1,"235":1,"249":4,"252":1,"268":2,"278":1,"666":2,"670":1,"707":1,"728":3,"749":1,"753":1}}],["helm",{"2":{"286":1}}],["helpful",{"2":{"238":1,"241":1}}],["helper",{"2":{"101":1}}],["help",{"2":{"10":1,"12":5,"107":1,"166":1,"175":2,"197":1,"200":4,"207":1,"225":1,"238":1,"248":1,"250":1,"273":1,"282":1,"285":2,"735":8}}],["helps",{"2":{"5":1,"215":1,"250":1,"258":1}}],["he",{"2":{"178":1,"221":1,"253":1}}],["hexadecimal",{"2":{"273":2}}],["hex",{"2":{"134":1,"218":1,"273":2}}],["heavy",{"2":{"211":1}}],["heap",{"2":{"188":1,"219":1}}],["healthy",{"2":{"733":1}}],["health",{"0":{"731":1},"1":{"732":1,"733":1},"2":{"137":1,"174":1,"731":1,"733":1}}],["headers",{"2":{"697":1}}],["header",{"2":{"117":1,"183":1,"207":3,"321":1,"325":1,"698":1,"748":3,"749":1}}],["heart",{"2":{"75":1}}],["hearts",{"2":{"24":1,"86":1}}],["hence",{"2":{"94":1,"187":2,"256":1}}],["her",{"2":{"86":1,"93":1,"94":1}}],["here",{"2":{"6":1,"13":1,"28":1,"29":1,"38":1,"40":1,"43":1,"52":1,"57":1,"66":1,"71":1,"116":1,"128":1,"137":2,"143":1,"146":1,"164":1,"175":5,"176":1,"177":1,"182":1,"183":1,"185":1,"203":1,"215":1,"219":1,"263":1,"271":1,"272":1,"274":1,"277":1,"284":1,"285":1,"286":1,"626":1,"629":1,"642":1,"646":1,"651":1,"657":1}}],["heightened",{"2":{"260":1}}],["height=1",{"2":{"196":8}}],["height",{"2":{"12":3,"87":1,"181":1,"183":6,"207":4,"322":1,"323":1,"571":1,"572":1,"640":1,"720":2,"735":4}}],["hold",{"2":{"694":1}}],["holds",{"2":{"263":1}}],["hole",{"2":{"224":1,"282":1}}],["houses",{"2":{"631":1}}],["housing",{"2":{"253":1}}],["hours",{"2":{"88":1}}],["home",{"2":{"171":1,"244":2,"258":1,"282":1,"283":2}}],["host",{"2":{"6":2,"181":4,"553":1,"554":1,"628":2}}],["hot",{"0":{"6":1},"1":{"7":1,"8":1,"9":1},"2":{"6":2}}],["however",{"2":{"5":1,"14":1,"19":1,"67":1,"78":1,"88":1,"89":1,"97":1,"100":2,"101":1,"128":1,"134":1,"137":2,"141":1,"150":1,"175":3,"177":1,"201":1,"203":1,"211":1,"214":1,"220":1,"224":1,"226":1,"241":1,"247":1,"252":2,"253":2,"268":2,"273":1,"282":1,"728":1}}],["how",{"0":{"1":1,"6":1,"12":1,"39":1,"81":1,"97":1},"1":{"2":1,"3":1,"4":1,"7":1,"8":1,"9":1,"82":1,"83":1,"84":1},"2":{"18":1,"39":1,"40":1,"42":1,"44":1,"53":1,"72":1,"81":2,"85":1,"97":1,"105":1,"108":1,"120":1,"137":2,"141":1,"143":2,"150":1,"151":1,"160":1,"166":1,"167":3,"170":1,"175":1,"176":1,"177":1,"178":1,"181":1,"183":1,"185":2,"186":1,"194":1,"207":1,"208":1,"211":1,"213":1,"214":1,"217":1,"220":1,"221":1,"226":1,"227":1,"237":1,"246":1,"249":2,"252":2,"253":1,"262":1,"263":1,"264":1,"272":1,"273":1,"282":1,"287":1,"655":2}}],["hyperledgerいろは2にようこそ",{"2":{"196":1}}],["hyperledger",{"2":{"2":1,"5":3,"18":4,"103":1,"168":4,"171":1,"172":2,"174":1,"185":3,"196":1,"210":1,"225":2,"227":1,"229":1,"236":2,"270":1,"272":2}}],["wünderbar",{"2":{"256":1}}],["wrestling",{"2":{"252":1}}],["wrong",{"2":{"153":1,"211":1,"219":1,"258":1,"273":2,"285":1,"286":1}}],["wrapping",{"2":{"212":2,"213":1}}],["wrapped",{"2":{"124":1,"125":2,"126":3,"143":1,"177":1,"212":4,"220":1}}],["wrappers",{"2":{"187":1,"656":1}}],["wrapper",{"2":{"74":1,"176":1,"191":1,"249":2,"666":1}}],["wrap",{"2":{"94":1,"175":1,"176":1,"219":1,"221":1}}],["wraps",{"2":{"94":1,"176":1}}],["writing",{"2":{"79":1,"88":1,"101":1,"136":1,"141":1,"211":1,"253":1,"656":1}}],["write",{"0":{"104":1},"2":{"20":1,"101":1,"103":1,"104":2,"130":2,"143":1,"187":1,"253":1}}],["written",{"2":{"3":1,"39":2,"210":1,"214":1,"218":1}}],["woes",{"2":{"107":1}}],["wondeland",{"2":{"176":1}}],["wonderland",{"2":{"52":2,"53":2,"66":1,"78":1,"92":9,"93":2,"94":1,"116":4,"128":20,"136":1,"164":11,"175":1,"177":1,"178":1,"179":1,"180":4,"181":1,"187":3,"188":3,"189":6,"190":6,"191":1,"200":2,"201":1,"202":2,"203":1,"204":2,"205":1,"213":1,"214":3,"218":1,"220":1,"221":1,"222":2,"256":3,"663":5,"664":3,"683":1,"735":1}}],["won",{"2":{"28":2,"69":1,"128":1,"153":1,"211":1,"215":1}}],["wouldn",{"2":{"82":1,"203":1,"224":1,"226":1}}],["would",{"2":{"17":1,"28":3,"41":1,"66":1,"78":1,"88":4,"97":1,"104":2,"106":2,"137":2,"141":1,"154":1,"166":1,"175":1,"177":1,"212":1,"213":1,"214":1,"217":1,"220":1,"224":1,"229":2,"249":1,"252":1,"253":1,"261":1,"265":1,"270":1,"273":2,"282":1,"286":1,"656":1,"658":1,"659":7}}],["worst",{"2":{"253":1}}],["word",{"2":{"126":1,"253":1}}],["words",{"2":{"94":1,"108":1,"116":1,"128":1,"230":1,"255":1,"269":2}}],["worthwhile",{"2":{"106":1}}],["worth",{"2":{"97":1}}],["worry",{"2":{"16":1,"88":1,"102":1,"103":1,"116":1,"177":1,"188":1,"215":1,"220":1}}],["worlds",{"2":{"234":1}}],["world",{"0":{"22":1,"111":1,"112":1,"653":1},"1":{"112":1},"2":{"16":1,"22":1,"28":6,"34":1,"39":2,"40":1,"41":1,"65":1,"98":1,"103":1,"111":3,"112":1,"226":1,"233":1,"626":1,"649":1,"651":1,"700":1,"709":1}}],["workflow",{"2":{"174":1,"263":1}}],["worked",{"2":{"166":1,"273":1}}],["working",{"0":{"53":1,"101":1},"2":{"16":1,"18":1,"50":1,"97":1,"107":1,"186":1,"200":2,"203":1,"210":1,"230":2,"272":1,"285":1}}],["work",{"0":{"81":1,"107":1},"1":{"82":1,"83":1,"84":1},"2":{"12":1,"16":1,"18":1,"65":2,"72":1,"82":1,"94":1,"97":1,"98":1,"125":1,"137":1,"146":1,"171":1,"174":1,"175":3,"176":1,"187":1,"197":1,"228":1,"230":1,"232":1,"242":1,"256":1,"257":1,"280":1,"283":1,"663":1}}],["workspaces",{"2":{"217":2}}],["works",{"0":{"1":1,"39":1,"97":1},"1":{"2":1,"3":1,"4":1},"2":{"63":1,"81":2,"94":3,"108":1,"137":2,"146":1,"167":1,"181":1,"200":1,"226":1,"243":1}}],["ws",{"2":{"175":6,"181":3,"183":1}}],["wsl",{"2":{"16":1}}],["wsvidentlengthlimits=1",{"2":{"128":1,"164":1}}],["wsvtriggermetadatalimits=1048576",{"2":{"128":1,"164":1}}],["wsvassetmetadatalimits=1048576",{"2":{"128":1,"164":1}}],["wsvassetdefinitionmetadatalimits=1048576",{"2":{"128":1,"164":1}}],["wsvaccountmetadatalimits=1048576",{"2":{"128":1,"164":1}}],["wsvdomainmetadatalimits=1048576",{"2":{"128":1,"164":1}}],["wsv",{"0":{"112":1,"653":1},"2":{"12":1,"626":1}}],["wallets",{"2":{"269":1}}],["walked",{"2":{"29":1}}],["walk",{"2":{"27":1,"42":1,"43":1,"226":1}}],["watch",{"2":{"213":1}}],["warehouse",{"0":{"638":1},"2":{"155":1,"626":1}}],["warn",{"2":{"153":3,"273":1,"427":1}}],["warning",{"2":{"98":1,"136":1,"153":1,"215":1,"250":1,"253":1,"256":1,"273":1,"658":1,"691":1,"700":1}}],["waitstrategy",{"2":{"186":1}}],["waiting",{"2":{"157":1}}],["wait",{"2":{"16":1,"53":1,"88":1,"122":1,"151":3,"272":1,"705":1}}],["way",{"2":{"16":1,"18":1,"28":2,"39":1,"40":1,"41":1,"42":1,"49":1,"91":1,"92":1,"94":1,"141":1,"143":1,"146":2,"177":2,"181":1,"183":2,"213":1,"220":1,"248":1,"249":1,"258":1,"263":1,"264":1,"272":1,"656":2,"658":1,"663":1,"719":1,"729":1}}],["ways",{"2":{"3":1,"16":1,"56":1,"125":1,"141":1,"167":1,"220":1,"242":2,"270":1,"725":1}}],["wants",{"2":{"135":1,"163":1}}],["wanted",{"2":{"94":1,"221":1}}],["want",{"2":{"16":3,"18":3,"22":1,"41":1,"65":1,"78":1,"89":2,"90":2,"91":1,"93":1,"94":2,"97":6,"101":2,"120":1,"135":1,"137":2,"146":1,"148":1,"150":1,"154":2,"156":1,"160":1,"163":2,"166":1,"168":1,"177":1,"181":1,"185":1,"203":1,"213":1,"215":1,"218":2,"219":1,"220":1,"226":1,"232":1,"233":3,"256":1,"263":1,"280":1,"664":1,"684":1}}],["wasn",{"2":{"88":1}}],["wasmexecutionfail",{"0":{"618":1},"2":{"577":1}}],["wasmexecution",{"2":{"577":1}}],["wasmsmartcontract",{"0":{"619":1},"2":{"353":1,"358":1}}],["wasmmaxmemory=524288000",{"2":{"128":1,"164":1}}],["wasmfuellimit=55000000",{"2":{"128":1,"164":1}}],["wasm32",{"2":{"108":1,"110":1}}],["wasm",{"0":{"100":1,"101":1,"109":1},"1":{"101":1,"102":1,"103":1,"104":1,"105":1,"106":1,"107":1,"108":1,"109":1,"110":1},"2":{"39":2,"50":1,"63":1,"71":1,"72":1,"76":1,"89":1,"97":5,"100":1,"101":3,"102":1,"103":6,"104":3,"105":3,"106":4,"109":6,"110":2,"121":2,"128":1,"164":1,"174":3,"200":2,"217":1,"232":1,"233":1,"353":1,"358":1,"421":1,"574":1,"656":2}}],["was",{"2":{"6":2,"28":1,"32":1,"51":1,"52":1,"79":1,"88":5,"97":1,"161":1,"178":1,"181":1,"191":2,"192":3,"221":2,"224":1,"230":1,"236":1,"631":1,"664":1,"679":1,"698":1,"741":2,"742":1,"743":1}}],["wip",{"2":{"725":1}}],["wiping",{"0":{"7":1}}],["window",{"2":{"175":4,"181":2,"207":1,"249":1,"264":1,"265":1,"266":2}}],["windows",{"2":{"13":1,"16":3}}],["wikipedia",{"2":{"238":3,"640":1}}],["wiki",{"2":{"168":1,"233":1,"238":1}}],["wish",{"2":{"29":1,"229":1}}],["wizards",{"2":{"28":1}}],["widely",{"2":{"185":1,"217":1}}],["wide",{"2":{"17":1,"40":1,"47":1,"82":2,"134":1,"172":2,"238":1,"661":1}}],["will",{"2":{"6":2,"7":1,"8":1,"9":1,"12":1,"17":1,"21":1,"22":1,"28":1,"60":1,"63":1,"78":1,"81":1,"88":1,"94":1,"97":3,"98":2,"100":1,"106":1,"109":1,"117":1,"120":2,"123":1,"125":1,"126":1,"127":1,"128":3,"135":2,"150":2,"154":1,"156":1,"162":1,"166":1,"174":1,"175":6,"178":2,"181":1,"185":1,"187":3,"190":1,"196":2,"202":1,"204":1,"207":2,"210":1,"212":1,"214":2,"215":1,"219":1,"236":1,"238":2,"241":1,"247":1,"252":1,"256":2,"272":3,"273":3,"650":2,"657":1,"666":1,"670":1,"683":1,"725":1,"726":1,"728":1}}],["withiroha",{"2":{"193":7}}],["within",{"2":{"12":1,"31":1,"41":2,"71":1,"100":1,"101":1,"134":1,"137":1,"202":2,"203":1,"204":2,"207":1,"238":1,"246":1,"262":1,"268":1,"750":1}}],["withtimeout",{"2":{"187":2,"188":1,"189":2,"190":1,"191":1}}],["without",{"2":{"13":2,"16":2,"28":1,"42":1,"116":1,"128":1,"141":1,"154":1,"185":1,"200":1,"219":1,"230":1,"232":1,"247":1,"254":1,"263":1,"266":1,"282":1,"651":1}}],["with",{"0":{"53":1,"101":1,"238":1,"240":1},"1":{"239":1,"241":1,"242":1,"243":1,"244":1},"2":{"5":1,"6":3,"16":2,"18":3,"20":1,"21":4,"24":1,"25":1,"36":1,"38":1,"39":1,"40":1,"44":1,"46":1,"47":1,"50":3,"52":1,"53":1,"57":1,"62":1,"63":1,"65":2,"67":2,"69":3,"71":1,"72":1,"74":1,"79":1,"84":1,"85":2,"86":1,"88":1,"89":1,"91":2,"94":3,"96":1,"97":1,"98":1,"100":2,"103":1,"105":1,"108":1,"112":1,"117":1,"127":1,"128":1,"134":3,"137":5,"141":1,"143":1,"146":5,"153":1,"154":1,"160":1,"162":1,"165":3,"166":4,"172":1,"173":1,"174":3,"175":16,"176":2,"177":3,"178":2,"181":4,"182":1,"183":2,"185":1,"186":2,"187":1,"188":1,"189":1,"190":1,"192":1,"196":2,"197":3,"200":4,"201":1,"202":5,"203":3,"207":1,"208":1,"210":2,"213":1,"214":2,"215":1,"217":5,"219":5,"220":5,"221":4,"224":2,"225":2,"226":2,"227":1,"228":1,"229":2,"230":1,"231":2,"233":1,"236":1,"237":1,"238":3,"246":1,"247":1,"248":3,"249":10,"252":6,"253":6,"255":2,"256":2,"257":1,"259":2,"260":4,"261":1,"263":2,"264":2,"266":1,"268":2,"270":3,"271":1,"272":5,"273":1,"274":1,"277":1,"279":1,"284":1,"285":1,"286":1,"287":2,"628":1,"634":2,"637":1,"642":1,"643":1,"644":1,"646":1,"648":1,"653":1,"656":2,"657":1,"658":1,"663":5,"664":4,"666":5,"703":1,"707":1,"711":1,"712":1,"714":3,"715":1,"719":1,"720":3,"725":1,"728":3,"729":1,"734":1,"738":1,"740":1,"744":1,"747":1,"748":2,"749":1}}],["whl",{"2":{"210":1,"283":1}}],["whilst",{"2":{"231":1}}],["while",{"2":{"36":1,"41":1,"74":1,"83":1,"88":1,"89":1,"92":1,"100":2,"117":1,"120":1,"126":1,"136":1,"137":1,"143":1,"150":1,"154":1,"174":1,"214":1,"219":1,"228":1,"238":1,"253":1,"256":1,"259":2,"266":1,"272":2,"278":1,"285":1,"656":1,"658":1,"666":1,"726":1,"728":1}}],["whitespace",{"2":{"220":1,"221":1}}],["whitespaces",{"2":{"74":1}}],["whiterabbitasset",{"2":{"190":4}}],["whiterabbitkeypair",{"2":{"190":2}}],["whiterabbit",{"2":{"190":8,"191":7}}],["white",{"2":{"177":5,"178":2,"213":5,"214":1,"220":7,"221":3}}],["whitepaper",{"2":{"28":1,"168":1}}],["which",{"2":{"16":2,"17":1,"18":3,"19":1,"20":1,"21":1,"25":4,"28":2,"36":1,"38":1,"39":1,"41":3,"62":1,"69":1,"72":4,"74":1,"79":1,"88":3,"92":1,"94":2,"95":1,"97":1,"100":1,"103":1,"106":1,"124":1,"135":2,"143":1,"148":1,"151":1,"153":1,"161":1,"173":1,"175":4,"176":1,"177":1,"181":2,"192":1,"197":2,"212":4,"214":3,"217":3,"218":1,"219":2,"220":1,"221":2,"223":1,"224":1,"230":1,"235":1,"236":1,"238":1,"241":1,"243":1,"247":1,"248":1,"249":1,"254":1,"256":1,"262":1,"264":2,"268":1,"280":2,"282":1,"628":1,"643":2,"656":4,"664":2,"669":1,"679":1,"717":1,"728":1,"730":1,"741":1}}],["why",{"0":{"656":1},"2":{"16":1,"19":1,"28":1,"78":1,"79":1,"88":2,"97":2,"141":1,"163":1,"221":1,"262":1,"286":1}}],["what",{"0":{"208":1},"2":{"13":1,"17":1,"21":2,"24":1,"36":1,"39":2,"40":3,"79":2,"81":1,"94":2,"104":2,"105":1,"113":1,"137":2,"138":1,"163":1,"164":1,"174":1,"178":2,"189":1,"192":1,"214":2,"215":2,"217":2,"219":2,"221":2,"230":1,"249":1,"252":1,"263":2,"278":1,"288":1,"656":1,"665":1,"684":1}}],["whole",{"2":{"97":2}}],["who",{"2":{"5":1,"88":1,"229":1,"253":1,"255":1,"267":1}}],["wheels",{"2":{"210":1}}],["wheel",{"2":{"101":1,"283":2}}],["whether",{"2":{"42":1,"62":1,"63":1,"65":1,"270":1,"742":1,"743":1}}],["whenever",{"2":{"94":1,"137":1,"249":1,"258":1,"259":1,"263":2,"266":1,"268":1}}],["when",{"2":{"4":1,"16":2,"18":1,"28":1,"31":1,"32":1,"33":1,"34":1,"35":1,"40":1,"41":2,"42":1,"51":1,"52":1,"57":1,"60":1,"65":1,"68":1,"69":1,"72":1,"81":1,"83":1,"88":5,"92":1,"93":1,"94":1,"97":1,"99":1,"105":1,"106":1,"111":1,"127":1,"135":1,"137":4,"141":1,"143":1,"146":1,"151":1,"153":1,"160":1,"174":1,"175":1,"177":1,"188":1,"203":1,"212":1,"221":2,"230":1,"233":1,"234":1,"245":1,"248":1,"249":1,"250":2,"252":1,"256":1,"259":1,"262":1,"264":1,"265":6,"266":1,"268":1,"272":1,"282":2,"283":1,"286":1,"641":1,"660":1,"667":1,"728":1}}],["whereis",{"2":{"244":1,"283":1}}],["whereas",{"2":{"126":1}}],["where",{"2":{"0":1,"18":1,"20":1,"21":1,"28":1,"57":1,"67":1,"82":1,"84":1,"94":1,"127":1,"137":1,"146":1,"155":1,"160":1,"174":1,"175":1,"196":1,"204":1,"245":1,"258":1,"261":1,"273":1,"280":1,"656":1,"666":1}}],["wear",{"2":{"630":1}}],["week",{"2":{"228":1}}],["welcome",{"2":{"196":1,"225":1}}],["well",{"2":{"16":1,"21":1,"43":1,"82":1,"92":1,"101":1,"104":1,"112":1,"125":1,"128":1,"129":2,"156":1,"174":1,"175":2,"217":1,"231":2,"232":1,"238":1,"243":1,"249":2,"250":1,"260":1,"637":1,"648":1,"653":1,"658":1}}],["website",{"2":{"264":1}}],["websites",{"2":{"249":1,"252":2}}],["websocket",{"2":{"175":3,"714":1,"718":1,"719":1,"720":1,"727":1,"729":1,"730":1}}],["webpack",{"2":{"174":1}}],["webassembly",{"2":{"165":1}}],["web",{"0":{"181":1},"1":{"182":1},"2":{"22":1,"100":1,"117":2,"174":6,"175":2,"181":3,"200":1,"233":1,"249":7}}],["went",{"2":{"21":1,"153":1}}],["we",{"2":{"4":1,"5":5,"10":1,"13":4,"14":4,"16":6,"17":1,"18":4,"20":2,"21":2,"25":2,"28":1,"29":2,"36":1,"39":1,"40":3,"42":4,"46":1,"65":1,"67":1,"78":1,"79":1,"81":3,"85":1,"88":5,"91":3,"92":2,"93":2,"94":8,"95":1,"96":1,"97":10,"99":3,"100":2,"101":3,"103":1,"104":3,"105":1,"107":1,"109":1,"110":2,"124":1,"128":1,"131":1,"137":2,"138":2,"141":2,"160":1,"167":1,"171":1,"174":3,"175":13,"176":6,"177":6,"178":6,"181":4,"183":1,"185":4,"187":3,"188":3,"190":2,"192":3,"200":2,"202":1,"203":11,"207":1,"210":1,"212":2,"213":2,"214":6,"215":8,"217":9,"219":7,"220":4,"221":7,"224":5,"226":2,"227":1,"228":2,"229":1,"230":1,"231":4,"232":1,"236":1,"252":2,"253":1,"256":1,"264":1,"273":1,"282":1,"286":1,"287":1,"655":2,"656":3,"658":1,"664":2,"665":1,"666":2,"672":1,"684":1,"703":2}}],["were",{"2":{"3":1,"42":1,"62":1,"88":1,"97":1,"151":1,"221":1,"238":1,"627":2}}],["bcrypt",{"2":{"253":2}}],["bcprov",{"2":{"185":1}}],["bsd",{"2":{"241":1}}],["blssmall",{"2":{"298":1}}],["blsnormal",{"2":{"298":1}}],["bls",{"2":{"238":6,"239":2}}],["blob",{"2":{"39":1,"71":1,"72":1,"110":1,"121":1}}],["blocktime",{"2":{"705":1}}],["blocktime=2000",{"2":{"128":1,"164":1}}],["blockrejectionreason",{"0":{"326":1},"2":{"327":1}}],["blockpayload",{"0":{"325":1,"541":1,"544":1,"564":1},"2":{"544":1,"547":2,"564":1}}],["blockmessage",{"0":{"324":1},"2":{"720":1}}],["blockheader",{"0":{"323":1},"2":{"321":1,"325":1,"499":2,"697":1,"698":1}}],["blockevent",{"0":{"321":1},"2":{"494":1}}],["blockeventfilter",{"0":{"322":1},"2":{"207":1,"495":1}}],["blocker",{"2":{"249":3}}],["blocking",{"2":{"53":4,"187":1,"224":1,"664":1}}],["blocksubscriptionrequest",{"0":{"328":1},"2":{"720":1}}],["blockstatus",{"0":{"327":1,"462":1},"2":{"321":1,"322":1,"462":1}}],["blocks",{"0":{"718":1},"1":{"719":1,"720":1},"2":{"6":1,"7":2,"12":4,"21":3,"39":3,"71":1,"89":1,"100":1,"112":1,"128":1,"155":1,"167":1,"175":1,"181":2,"183":2,"196":1,"200":1,"207":1,"638":1,"639":1,"653":1,"696":1,"697":1,"714":1,"720":2,"728":1,"749":3,"750":1}}],["blockchains",{"0":{"138":1},"1":{"139":1,"140":1,"141":1},"2":{"14":1,"42":1,"141":1,"225":1,"628":1,"629":1,"672":1,"714":1}}],["blockchain",{"0":{"7":1,"157":1,"158":1,"627":1},"1":{"159":1,"160":1,"161":1,"162":1,"163":1},"2":{"6":1,"12":1,"27":1,"29":2,"31":1,"36":3,"39":7,"40":2,"42":7,"43":1,"46":1,"50":1,"56":4,"65":1,"71":1,"88":1,"96":1,"101":1,"105":1,"110":1,"112":1,"116":1,"128":1,"136":1,"137":1,"139":2,"140":2,"141":9,"143":1,"146":2,"157":1,"158":1,"165":2,"167":1,"178":1,"183":1,"190":1,"196":1,"200":3,"201":1,"208":1,"211":1,"217":1,"221":1,"226":1,"230":2,"232":1,"233":3,"236":1,"237":1,"238":2,"245":1,"246":1,"248":1,"251":1,"627":3,"629":1,"641":1,"653":1,"661":2,"667":1,"668":1,"669":1,"672":2,"676":1,"683":1,"696":1,"697":1,"699":1,"706":1,"707":1,"714":1,"720":1,"728":2}}],["block",{"0":{"128":1,"130":1,"183":1,"695":1},"1":{"129":1,"130":1,"131":1,"696":1,"697":1,"698":1},"2":{"6":2,"7":2,"12":4,"24":1,"28":3,"31":1,"32":2,"42":1,"72":1,"87":3,"88":6,"89":1,"97":2,"106":1,"125":1,"126":1,"128":10,"129":1,"130":5,"131":1,"132":1,"135":1,"141":2,"143":2,"151":5,"155":1,"164":2,"178":1,"183":10,"185":1,"192":1,"196":9,"200":2,"207":9,"224":1,"249":1,"272":2,"323":1,"393":1,"494":1,"495":1,"499":1,"571":1,"572":1,"576":1,"628":1,"633":1,"638":1,"640":1,"642":1,"654":1,"663":1,"697":1,"698":1,"705":1,"717":2,"718":1,"719":1,"720":2,"728":1,"735":5,"749":1}}],["black",{"2":{"28":2}}],["body",{"2":{"740":1,"741":1,"749":1,"752":1}}],["boneh",{"2":{"238":2}}],["bones",{"2":{"176":1}}],["borrowing",{"2":{"217":1}}],["boundaries",{"2":{"658":1}}],["boundary",{"2":{"656":1,"658":2}}],["bound",{"2":{"196":1}}],["bouncycastle",{"2":{"185":1}}],["bob",{"2":{"128":2,"164":1,"187":1,"188":1,"189":1,"190":1,"222":1}}],["box",{"2":{"96":1,"188":1,"219":1,"222":4,"707":2}}],["boxes",{"2":{"94":1,"188":1}}],["boilerplates",{"2":{"176":1}}],["boilerplate",{"2":{"93":1,"187":1,"219":1,"656":1}}],["boot",{"2":{"248":1}}],["bootstrapping",{"2":{"161":1,"628":1}}],["bootstrap",{"2":{"21":1}}],["books",{"2":{"627":2}}],["book",{"2":{"217":1}}],["boolean",{"2":{"50":1,"186":3}}],["bool",{"0":{"620":1},"2":{"36":1,"439":2,"620":1}}],["bottom",{"2":{"94":1}}],["bottlenecks",{"2":{"10":1}}],["both",{"2":{"19":1,"42":1,"49":1,"67":1,"82":1,"122":1,"125":2,"128":1,"134":1,"165":1,"175":1,"177":1,"213":1,"220":1,"226":1,"229":1,"234":1,"252":1,"256":1,"259":1,"270":1,"273":2,"279":1,"672":1}}],["bft",{"0":{"19":1,"634":1},"1":{"20":1,"21":1},"2":{"135":1,"217":1,"626":1}}],["bruteforce",{"2":{"252":1}}],["brute",{"2":{"252":1,"253":1}}],["brackets",{"2":{"282":1}}],["brave",{"2":{"249":1}}],["branch",{"2":{"174":2,"185":1,"210":1}}],["brands",{"2":{"268":1}}],["brand",{"2":{"72":1,"78":1}}],["browsing",{"2":{"249":3}}],["browsers",{"0":{"249":1},"2":{"246":1,"249":4}}],["browser",{"2":{"175":2,"249":13}}],["brief",{"2":{"238":1}}],["brightest",{"2":{"177":1,"213":1,"220":1}}],["brings",{"2":{"19":1}}],["bringing",{"2":{"17":1}}],["breaches",{"2":{"250":2,"260":1}}],["breach",{"2":{"245":1,"246":1,"250":1,"268":1}}],["breaking",{"2":{"107":1}}],["break",{"2":{"97":1,"215":1,"234":1,"282":1}}],["breaks",{"2":{"16":1}}],["brew",{"2":{"170":2}}],["balancing",{"2":{"287":1}}],["balanced",{"2":{"97":1,"238":1}}],["balance",{"2":{"65":1,"190":4,"191":4,"234":1}}],["backend",{"2":{"287":1}}],["back",{"2":{"258":1,"263":2,"728":1}}],["backups",{"2":{"258":2}}],["bad",{"2":{"224":1,"249":1}}],["bane",{"2":{"221":1}}],["banknotes",{"2":{"630":1}}],["bank",{"2":{"158":1,"236":1,"259":2}}],["barring",{"2":{"215":1}}],["bare",{"0":{"13":1,"18":1},"1":{"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1},"2":{"13":2,"14":1,"74":1,"176":1}}],["batchedresponsev1",{"0":{"320":1},"2":{"319":1}}],["batchedresponse",{"0":{"319":1},"2":{"741":1}}],["batched",{"2":{"219":1}}],["batch",{"2":{"161":1,"320":1,"740":1,"741":1}}],["base",{"0":{"231":1},"2":{"143":3,"219":1,"231":1}}],["based",{"2":{"13":1,"49":1,"62":1,"89":1,"97":1,"136":1,"188":1,"232":1,"235":1,"249":3,"259":1,"260":1,"263":1,"264":1,"627":1,"631":1,"641":1,"664":1}}],["basics",{"2":{"91":1,"167":1,"185":1,"208":1,"217":1}}],["basic",{"0":{"117":1},"2":{"72":1,"85":1,"103":1,"113":1,"117":3,"143":1,"164":1,"166":1,"185":1,"198":1,"217":1,"226":1,"257":1,"272":1,"699":1,"703":1}}],["bashpublic",{"2":{"202":1}}],["bashiroha",{"2":{"200":1}}],["bashrc",{"2":{"16":1,"143":1,"244":3}}],["bash",{"2":{"6":1,"12":1,"20":1,"239":7,"244":1,"735":1}}],["bash$",{"2":{"6":3,"7":1,"9":1,"12":1,"16":4,"17":3,"18":1,"20":1,"21":2,"22":3,"103":1,"108":1,"109":1,"114":1,"130":3,"134":1,"144":1,"170":2,"171":3,"172":2,"174":6,"196":2,"199":1,"200":3,"201":2,"202":3,"203":2,"204":3,"205":1,"206":1,"207":1,"210":4,"217":1,"238":1,"241":1,"242":1,"243":1,"244":4,"279":3,"280":2,"281":1,"282":6}}],["biometric",{"2":{"260":1}}],["birthdays",{"2":{"137":1,"253":1}}],["bigger",{"2":{"154":1}}],["big",{"2":{"102":1,"105":2,"154":1,"221":1}}],["bigquantity",{"2":{"25":1,"214":1}}],["bill",{"2":{"24":2}}],["binaries",{"0":{"172":1},"2":{"169":1,"172":1}}],["binary",{"2":{"6":1,"14":3,"17":3,"39":1,"76":1,"100":1,"101":1,"102":1,"103":1,"105":4,"109":2,"136":1,"146":1,"175":1,"211":1,"217":1,"224":1,"241":1,"242":1,"243":3,"248":2,"256":1,"640":1,"643":1,"656":1,"703":2}}],["bin",{"0":{"242":1,"243":1,"244":1},"1":{"244":1},"2":{"14":1,"17":1,"22":1,"134":1,"238":1,"239":4,"241":1,"242":2,"243":2,"244":4,"280":1,"282":2,"283":1}}],["binding",{"0":{"658":1},"1":{"659":1},"2":{"175":1,"657":2,"658":1}}],["bindings",{"2":{"103":2}}],["bind",{"2":{"8":1,"175":2,"181":1}}],["bitmap",{"2":{"292":1,"307":1,"313":1,"338":1,"345":1,"361":1,"489":1,"525":1,"592":1}}],["bits",{"2":{"252":3,"273":1}}],["bitcoin",{"2":{"238":2}}],["bit",{"2":{"5":1,"25":3,"84":1,"101":1,"177":1,"214":2,"220":1,"222":1,"656":1,"749":1}}],["bucket",{"2":{"735":12}}],["bugging",{"2":{"273":1}}],["bug",{"2":{"249":1,"270":1}}],["bunny",{"2":{"178":1,"213":2}}],["bundlers",{"2":{"174":1}}],["bundler",{"2":{"174":2}}],["bunyan",{"2":{"154":5}}],["bulk",{"2":{"50":1}}],["burnbox",{"0":{"332":1},"2":{"416":1}}],["burnasset",{"2":{"191":1}}],["burnassets",{"2":{"191":3}}],["burning",{"0":{"191":1,"223":1},"2":{"43":2,"191":3,"206":1,"223":1}}],["burn",{"0":{"43":1,"206":1,"329":1,"330":1,"331":1},"2":{"40":2,"41":5,"43":1,"44":1,"56":1,"86":1,"94":1,"98":1,"191":2,"206":1,"223":6,"332":3,"416":1,"420":1,"661":2,"663":2}}],["burned",{"2":{"27":1}}],["but",{"2":{"13":1,"14":1,"16":1,"18":2,"28":1,"39":1,"42":3,"65":1,"79":1,"87":1,"88":3,"94":1,"100":1,"103":1,"105":1,"106":1,"125":1,"128":1,"137":2,"160":1,"163":1,"171":1,"175":1,"176":1,"177":2,"203":3,"213":2,"214":1,"217":1,"218":1,"220":2,"221":2,"224":2,"229":1,"230":1,"234":1,"238":1,"243":1,"249":1,"254":1,"255":1,"256":1,"259":1,"264":1,"273":1,"278":1,"280":1,"281":2,"655":1,"656":1,"666":2,"672":1,"679":1,"682":1,"683":1,"703":1,"728":1,"753":1}}],["button>",{"2":{"181":2}}],["button",{"2":{"5":1,"181":2,"265":1}}],["builds",{"2":{"248":1}}],["buildsigned",{"2":{"187":2,"188":2,"189":3,"190":2,"191":1,"193":14}}],["builder",{"2":{"176":1,"193":9,"221":1}}],["builders",{"2":{"42":1}}],["building",{"0":{"241":1},"2":{"14":1,"104":1,"241":1}}],["build`",{"2":{"6":1}}],["build",{"2":{"6":2,"14":7,"22":2,"62":1,"101":1,"108":3,"177":1,"181":1,"185":2,"196":1,"208":2,"210":4,"218":1,"219":1,"220":1,"224":1,"241":2,"248":1}}],["built",{"0":{"242":1},"2":{"0":1,"14":1,"24":1,"63":2,"134":1,"141":2,"178":1,"181":1,"189":1,"192":1,"202":1,"214":1,"221":1,"224":1,"241":1,"249":6,"650":1}}],["bypass",{"2":{"263":1}}],["bytearray",{"2":{"192":1}}],["byte",{"2":{"181":2,"193":1,"273":1}}],["bytestohex",{"2":{"181":2}}],["bytes",{"2":{"100":1,"121":2,"177":1,"181":2,"273":3,"439":1,"574":1}}],["byzantine",{"0":{"634":1},"2":{"146":1,"163":1,"230":2,"626":1,"654":1}}],["byremoved",{"2":{"94":2}}],["byaccount",{"2":{"94":2}}],["bysome",{"2":{"38":1,"94":7}}],["by",{"0":{"90":1,"91":1},"1":{"92":1,"93":1,"94":1,"95":1,"96":1,"97":1},"2":{"3":3,"16":1,"17":1,"22":1,"24":2,"28":1,"38":2,"50":1,"53":1,"57":1,"62":1,"63":1,"65":1,"69":1,"85":3,"87":1,"88":1,"93":1,"94":2,"97":3,"100":1,"110":1,"117":2,"125":1,"126":1,"127":1,"128":1,"134":2,"137":3,"141":5,"150":1,"166":1,"175":1,"176":1,"185":1,"192":1,"200":4,"201":1,"203":1,"214":3,"215":1,"217":4,"219":1,"221":1,"224":1,"228":1,"230":1,"233":1,"238":2,"243":1,"244":4,"245":1,"248":1,"249":1,"250":4,"252":3,"253":2,"255":2,"258":1,"259":1,"262":1,"263":2,"264":1,"265":1,"266":1,"268":2,"272":1,"273":2,"304":1,"342":1,"594":1,"644":1,"650":2,"656":1,"660":1,"663":2,"664":2,"666":1,"667":1,"678":2,"683":1,"684":1,"691":1,"692":1,"693":1,"699":1,"702":1,"704":2,"705":1,"708":1,"709":1,"717":1,"723":2,"728":2,"738":1,"741":1,"748":1,"750":1}}],["bevendorff",{"2":{"268":1}}],["beauty",{"2":{"263":1}}],["beautiful",{"2":{"146":1}}],["beneficial",{"2":{"268":1}}],["benefit",{"2":{"217":2}}],["bench",{"2":{"231":1}}],["beyond",{"2":{"215":1}}],["beginning",{"2":{"282":1,"720":1}}],["begin",{"2":{"166":1}}],["begins",{"2":{"28":1,"65":1}}],["become",{"2":{"212":1}}],["becomes",{"2":{"137":2}}],["because",{"2":{"28":1,"46":1,"88":2,"94":1,"97":1,"109":1,"163":1,"171":1,"174":1,"178":1,"181":1,"183":1,"220":1,"221":1,"282":1,"286":1,"630":1,"656":1}}],["beside",{"2":{"153":1}}],["besides",{"2":{"125":1}}],["best",{"2":{"88":1,"161":1,"177":2,"210":1,"213":2,"220":2,"228":1,"231":1,"234":1,"246":2,"248":1,"261":1,"268":2,"658":1}}],["belonging",{"2":{"256":1}}],["belongs",{"2":{"137":1,"221":1,"643":1,"683":1}}],["belong",{"2":{"116":1,"128":1,"137":1,"221":1,"680":1,"687":1}}],["below",{"2":{"29":1,"97":1,"137":1,"138":1,"179":1,"229":1,"264":1,"658":1,"659":1,"666":2}}],["being",{"2":{"41":1,"88":1,"107":1,"135":1,"230":3,"231":1,"234":1,"235":1,"249":3,"256":1,"634":1,"715":1,"728":1,"753":2}}],["between",{"0":{"137":1},"2":{"29":3,"39":1,"40":1,"44":1,"56":1,"90":1,"124":1,"137":1,"149":1,"202":1,"227":1,"229":1,"234":1,"238":1,"249":1,"272":2,"661":1,"719":1,"729":1}}],["better",{"2":{"0":1,"13":1,"174":1,"175":1}}],["behalf",{"2":{"217":1,"256":3,"663":1}}],["behaviour",{"2":{"89":2,"97":1,"99":1,"656":1,"658":1}}],["behavior",{"2":{"3":1}}],["behave",{"2":{"87":1}}],["behind",{"2":{"28":1,"208":1,"218":1,"257":1}}],["been",{"2":{"24":1,"78":1,"97":1,"141":1,"178":1,"188":1,"189":2,"214":1,"221":1,"248":1,"262":1,"272":2,"728":3,"753":1}}],["before",{"2":{"6":1,"7":1,"8":1,"9":1,"59":1,"65":1,"87":1,"88":1,"89":1,"138":1,"151":3,"174":1,"175":1,"213":1,"248":1,"249":2,"273":1,"728":1}}],["be",{"2":{"2":1,"3":1,"6":2,"7":1,"12":2,"16":1,"17":2,"18":3,"19":1,"20":2,"21":3,"24":3,"25":1,"27":1,"28":3,"32":1,"37":1,"40":1,"41":4,"42":6,"43":4,"44":1,"45":2,"50":2,"52":1,"56":3,"59":2,"62":4,"63":1,"64":1,"65":5,"66":1,"71":1,"72":2,"78":3,"80":1,"82":3,"84":2,"88":4,"89":1,"90":2,"97":5,"98":2,"100":1,"101":1,"102":2,"104":4,"106":2,"110":3,"113":1,"116":2,"117":1,"122":1,"125":3,"126":4,"127":3,"128":3,"130":1,"132":1,"134":1,"135":2,"137":2,"138":4,"139":1,"141":6,"146":3,"149":1,"150":1,"153":1,"154":1,"159":2,"160":1,"161":1,"164":1,"174":3,"175":3,"176":1,"178":5,"188":1,"189":1,"192":1,"199":1,"203":3,"204":1,"210":1,"211":2,"212":2,"214":4,"217":1,"218":1,"221":5,"224":1,"229":2,"230":2,"232":2,"233":1,"237":1,"238":3,"241":3,"242":1,"246":1,"247":3,"248":1,"249":7,"250":2,"252":4,"253":2,"255":1,"256":3,"259":3,"261":1,"264":2,"266":2,"268":4,"272":3,"273":1,"280":1,"282":1,"628":2,"630":2,"631":1,"632":1,"644":1,"646":1,"650":2,"654":1,"656":2,"658":1,"659":7,"665":1,"666":4,"672":1,"699":1,"700":1,"709":1,"715":1,"717":2,"719":1,"725":2,"726":1,"728":2,"729":1,"734":1,"738":1,"744":1,"747":1,"748":1,"749":1}}],["aid",{"2":{"249":1}}],["air",{"2":{"248":1}}],["aiming",{"2":{"264":1}}],["aim",{"2":{"88":1,"247":1,"252":2,"273":1}}],["awareness",{"2":{"260":2}}],["away",{"2":{"248":1}}],["await",{"2":{"175":2,"176":2,"180":3,"181":4,"183":1,"187":1,"188":1,"189":2,"190":1,"191":1}}],["audits",{"2":{"260":2}}],["audit",{"2":{"249":1}}],["audited",{"2":{"248":1,"249":2}}],["auditing",{"2":{"231":1}}],["authenticator",{"2":{"259":1}}],["authenticated",{"2":{"243":1}}],["authenticationremoved",{"2":{"290":1,"292":1}}],["authenticationadded",{"2":{"290":1,"292":1}}],["authentication",{"0":{"117":1},"2":{"117":2,"243":1,"259":3,"263":1,"268":1}}],["authenticity",{"2":{"237":1,"255":1,"256":1}}],["auth",{"2":{"113":1,"117":1,"164":1}}],["authorised",{"2":{"260":1}}],["authorization",{"2":{"117":1,"266":1}}],["authority",{"2":{"78":1,"261":1,"297":1,"355":1,"356":1,"501":1,"575":1}}],["author",{"2":{"88":1}}],["automatic",{"2":{"140":1,"146":1,"158":1}}],["automatically",{"2":{"3":1,"7":1,"128":1,"728":1}}],["automated",{"2":{"109":1,"260":1}}],["ahem",{"2":{"101":2}}],["ago",{"2":{"278":1}}],["agent",{"0":{"263":1},"2":{"263":11,"264":1,"265":5,"266":3}}],["age",{"2":{"253":1}}],["agebased",{"2":{"186":1}}],["agnostic",{"2":{"183":1}}],["aggregated",{"2":{"683":1,"685":1}}],["aggregate",{"2":{"174":1}}],["agreed",{"2":{"650":1}}],["agreement",{"2":{"137":1}}],["agree",{"2":{"88":2,"135":1,"656":1}}],["again",{"2":{"18":1,"84":1,"178":1,"221":2}}],["against",{"2":{"6":1,"57":1,"97":1,"101":1,"212":1,"241":2,"655":1}}],["amp",{"2":{"175":1,"263":1}}],["among",{"2":{"97":1,"229":1,"283":1}}],["amounttotransfer",{"2":{"179":2}}],["amounts",{"2":{"67":1}}],["amount",{"2":{"39":1,"43":1,"82":1,"89":1,"94":1,"97":3,"214":3,"221":2,"222":3,"252":2,"303":1,"310":1,"633":1,"705":1,"735":17}}],["amazing",{"2":{"36":1}}],["affected",{"2":{"250":1}}],["affects",{"2":{"218":1}}],["affectionately",{"2":{"39":1}}],["af1abc889019971d4c4e8866c347367d63a024319e50aef989db255f761e9d1d",{"2":{"207":3}}],["aforementioned",{"2":{"188":1,"224":1,"233":1}}],["afterwards",{"2":{"178":1}}],["after",{"2":{"3":1,"6":1,"12":1,"22":1,"25":1,"43":1,"61":1,"84":1,"88":1,"95":1,"135":2,"151":1,"161":1,"162":1,"177":2,"179":1,"181":1,"183":1,"190":1,"191":2,"192":1,"196":1,"204":1,"205":1,"210":1,"212":1,"213":2,"220":3,"221":1,"224":1,"234":1,"238":1,"249":1,"282":1,"627":1,"720":1,"730":2}}],["abstract",{"2":{"656":1}}],["absent",{"2":{"196":1}}],["ability",{"2":{"260":1}}],["abi",{"2":{"103":2,"658":1}}],["abundance",{"2":{"79":1}}],["able",{"2":{"28":1,"42":1,"56":1,"78":1,"139":1,"141":1,"175":2,"203":1,"224":1,"242":1,"280":1,"634":1,"672":1}}],["abort",{"2":{"105":2,"108":1}}],["about",{"2":{"13":2,"16":1,"24":1,"25":1,"29":1,"40":1,"42":1,"57":1,"65":1,"70":1,"80":1,"81":1,"88":1,"98":1,"99":1,"103":1,"116":1,"124":1,"127":1,"132":1,"134":1,"137":3,"141":2,"151":1,"161":1,"163":2,"167":1,"177":1,"178":1,"181":1,"188":1,"189":1,"192":1,"202":1,"214":2,"217":1,"220":1,"221":1,"224":1,"226":1,"227":1,"231":1,"233":1,"246":1,"247":1,"253":1,"259":2,"260":1,"268":2,"270":1,"662":1,"666":2,"667":1,"672":1,"685":1,"714":1,"735":1}}],["above",{"2":{"6":1,"12":1,"16":1,"97":1,"110":1,"125":1,"128":2,"134":1,"175":1,"185":1,"202":1,"217":1,"244":1,"268":1,"657":1}}],["arise",{"2":{"286":2}}],["architectural",{"2":{"262":1}}],["architectures",{"2":{"234":1}}],["architecture",{"2":{"79":1,"99":1,"103":1,"709":1}}],["arguments",{"2":{"218":1}}],["argument",{"2":{"200":1,"202":1}}],["args",{"2":{"187":1}}],["artist",{"2":{"631":1}}],["article",{"2":{"249":1,"714":1}}],["art",{"2":{"165":1}}],["arrange",{"2":{"282":1}}],["arraylist",{"2":{"193":2}}],["arrays",{"2":{"50":2}}],["array",{"0":{"299":1,"300":1,"301":1},"2":{"22":1,"42":1,"135":3,"187":1,"286":1,"299":1,"300":1,"301":1,"410":1,"423":1,"424":1}}],["arrived",{"2":{"92":1}}],["around",{"2":{"74":1,"94":1,"97":1,"269":1,"656":2,"658":1,"666":1}}],["areas",{"2":{"260":2}}],["are",{"0":{"282":1},"2":{"0":2,"2":1,"3":3,"5":1,"13":1,"16":2,"18":3,"22":1,"28":3,"31":2,"32":2,"33":2,"34":1,"35":1,"39":3,"40":2,"41":2,"42":2,"43":2,"45":1,"46":1,"50":2,"51":1,"52":1,"55":1,"56":3,"57":3,"62":4,"63":1,"65":2,"71":2,"83":1,"85":1,"86":2,"87":4,"89":1,"94":1,"97":3,"99":1,"100":3,"104":1,"105":2,"111":1,"117":1,"124":1,"126":2,"127":2,"128":2,"134":3,"137":4,"139":1,"143":4,"151":1,"153":3,"155":1,"160":1,"166":1,"167":1,"173":1,"174":5,"175":2,"177":1,"178":1,"181":1,"183":1,"186":2,"187":2,"188":2,"189":1,"192":1,"197":1,"200":1,"201":2,"203":1,"204":1,"210":1,"212":2,"213":2,"214":2,"215":1,"217":3,"218":2,"220":1,"221":3,"224":1,"227":1,"228":1,"229":4,"230":1,"231":1,"232":1,"234":1,"235":2,"238":4,"241":1,"242":1,"244":1,"245":1,"248":2,"249":5,"250":2,"253":1,"256":3,"258":1,"259":1,"260":4,"261":1,"262":1,"264":1,"266":3,"268":1,"270":2,"271":1,"272":3,"273":2,"274":1,"277":1,"280":1,"282":1,"284":1,"285":1,"287":1,"627":2,"628":1,"630":3,"631":1,"641":2,"647":1,"656":4,"658":4,"659":1,"660":2,"661":1,"663":2,"666":2,"671":1,"672":2,"689":1,"699":1,"705":1,"714":1,"720":1,"728":3,"741":2,"749":3,"750":1}}],["a70dab95c7482eb9f159111b65947e482108cfe67df877bd8d3b9441a781c7c98e351a70b6a603ed285d666b8d689b680865913ba03ce29fb7d13a166c4e7f1f",{"2":{"18":1}}],["apartment",{"2":{"261":1}}],["apt",{"2":{"170":1,"234":1,"282":1}}],["appearance",{"2":{"630":1}}],["appears",{"2":{"201":1,"265":2}}],["app",{"2":{"181":7,"259":1}}],["appointments",{"2":{"137":1}}],["applied",{"2":{"207":1,"327":1}}],["applies",{"2":{"69":1,"137":1,"256":1}}],["applicable",{"2":{"137":1,"741":1}}],["application",{"2":{"106":1,"181":2,"185":2,"218":2,"238":1,"241":1,"243":1,"249":1,"256":1,"265":1,"656":1,"748":3}}],["applications",{"2":{"99":1,"238":1,"259":1,"628":1,"706":1}}],["approval",{"2":{"255":1}}],["approved",{"2":{"207":1,"260":1,"327":1,"578":1}}],["approximately",{"2":{"252":1,"253":1}}],["appropriate",{"2":{"20":1,"160":1,"174":1,"175":1,"256":1,"709":1}}],["appropriately",{"2":{"18":1}}],["approaches",{"2":{"19":1,"229":1,"233":1,"246":1,"247":1,"262":1}}],["approach",{"2":{"13":1,"65":1,"100":1,"137":2,"233":1,"238":1,"247":1,"248":1,"249":1,"253":1,"262":1,"263":1,"268":1}}],["apis",{"2":{"231":1,"268":1}}],["api`",{"2":{"181":1}}],["apiurl",{"2":{"175":4,"181":2}}],["api",{"0":{"119":1,"148":1,"715":1},"1":{"716":1,"717":1},"2":{"18":5,"20":1,"21":1,"94":1,"118":1,"119":3,"143":1,"146":1,"148":2,"161":1,"174":1,"175":3,"176":1,"181":2,"185":1,"186":3,"192":1,"193":2,"200":1,"211":1,"218":2,"224":2,"268":1,"287":2,"643":1,"656":1,"658":1,"704":1,"714":2,"715":1,"717":2}}],["acknowledging",{"2":{"267":1}}],["academy",{"2":{"263":3}}],["achieving",{"2":{"247":1}}],["achieve",{"2":{"90":1,"174":1,"219":1,"654":1}}],["across",{"2":{"135":2,"234":1,"248":1,"287":2,"658":1,"683":1,"685":1}}],["acts",{"2":{"264":1}}],["act",{"2":{"203":1}}],["actors",{"2":{"634":2}}],["actor",{"2":{"163":1,"664":1}}],["activities",{"2":{"249":1,"254":1,"260":3,"649":1}}],["activity",{"2":{"204":1}}],["actively",{"2":{"230":2,"666":1}}],["active",{"2":{"174":1,"235":1,"272":2,"282":1,"710":1}}],["activates",{"2":{"79":1}}],["acting",{"2":{"137":1}}],["actionable",{"2":{"260":1}}],["action",{"0":{"75":1,"76":1,"77":1,"78":1,"79":1,"80":1,"297":1},"1":{"76":1,"77":1,"78":1,"79":1,"80":1},"2":{"62":1,"73":2,"75":2,"76":1,"95":4,"250":1,"585":2}}],["actions",{"2":{"56":1,"260":1}}],["actual",{"2":{"14":1,"65":1,"88":1,"104":1,"255":1,"447":1,"552":1,"726":1,"741":1}}],["actually",{"2":{"14":1,"19":1,"215":1,"219":1}}],["accuracy",{"2":{"627":1}}],["accidentally",{"2":{"249":1}}],["accompanied",{"2":{"233":1,"704":1}}],["accommodated",{"2":{"212":1}}],["according",{"2":{"87":1,"174":1,"664":1,"749":1}}],["accountdoesnotexist",{"2":{"577":1}}],["accountpublickey",{"2":{"332":1}}],["accountpermissionchanged",{"0":{"295":1},"2":{"290":2}}],["accountmintbox",{"0":{"294":1},"2":{"444":1}}],["accountrolechanged",{"0":{"296":1},"2":{"290":2}}],["accounteventset",{"0":{"292":1},"2":{"291":1}}],["accounteventfilter",{"0":{"291":1},"2":{"341":1}}],["accountevent",{"0":{"290":1},"2":{"343":1}}],["account>",{"2":{"193":4}}],["accountfilter",{"2":{"94":2}}],["accountid`",{"2":{"220":1}}],["accountid",{"0":{"293":1,"433":1,"459":1,"557":1},"2":{"52":1,"53":2,"66":1,"75":1,"92":3,"94":2,"104":2,"175":4,"177":6,"178":2,"179":3,"181":2,"187":5,"188":1,"189":2,"190":3,"191":1,"193":7,"218":1,"220":4,"222":3,"289":1,"290":5,"291":1,"295":1,"296":1,"297":1,"304":1,"309":1,"314":1,"330":1,"342":2,"347":1,"355":1,"356":1,"363":1,"364":1,"385":1,"393":1,"395":1,"397":1,"400":1,"406":1,"408":1,"414":2,"433":1,"441":1,"442":1,"449":1,"459":1,"501":1,"510":1,"518":1,"520":1,"532":1,"557":1,"575":1,"580":2,"581":2,"582":1,"583":1,"597":1,"664":2,"671":1,"674":1,"677":2,"678":1,"680":1,"681":1,"687":1,"707":1,"742":1,"743":1}}],["accounts`",{"2":{"180":1}}],["accounts",{"0":{"23":1,"92":1,"141":1,"180":1},"2":{"29":3,"33":1,"40":2,"41":6,"42":3,"44":1,"50":1,"51":1,"55":1,"56":3,"62":1,"66":1,"69":1,"72":1,"80":1,"94":1,"111":1,"116":1,"128":5,"129":2,"130":2,"136":1,"139":2,"141":5,"165":1,"166":1,"167":1,"172":1,"180":4,"188":2,"189":1,"190":1,"191":1,"200":1,"201":1,"203":1,"217":1,"259":1,"342":1,"649":1,"660":1,"661":2,"663":1,"672":2,"675":1,"676":1,"679":1,"680":2,"681":1,"683":1,"694":1,"699":1,"735":5}}],["account",{"0":{"78":1,"116":1,"136":1,"177":1,"188":1,"202":1,"213":1,"220":1,"289":1,"330":1,"406":1,"408":1,"441":1,"442":1,"502":1,"510":1,"518":1,"520":1,"532":1,"557":1,"580":2,"581":2,"582":1,"583":1,"597":1,"675":1,"742":1},"1":{"676":1,"677":1,"678":1,"679":1,"680":1,"681":1},"2":{"18":5,"29":5,"31":1,"36":4,"38":1,"39":2,"40":1,"41":7,"42":9,"43":1,"44":1,"45":1,"52":1,"53":3,"56":1,"57":2,"59":1,"60":2,"65":1,"69":1,"72":2,"75":1,"78":5,"82":1,"86":2,"93":1,"94":3,"95":1,"104":3,"113":1,"116":3,"128":14,"131":1,"135":3,"136":2,"137":2,"139":1,"141":8,"143":3,"145":2,"151":7,"164":6,"175":2,"176":1,"177":7,"178":1,"179":3,"180":10,"181":2,"187":3,"188":10,"189":4,"190":5,"191":3,"193":40,"200":4,"201":2,"202":8,"203":7,"205":1,"211":1,"213":7,"217":1,"218":2,"220":14,"221":2,"222":6,"227":1,"229":2,"273":1,"290":1,"294":2,"295":1,"296":1,"314":1,"315":2,"332":1,"341":1,"342":1,"343":1,"385":1,"393":1,"400":1,"409":2,"415":2,"444":1,"509":2,"515":2,"521":2,"537":2,"557":1,"584":4,"604":2,"660":2,"663":11,"664":7,"671":1,"672":1,"674":1,"676":1,"677":2,"678":2,"679":2,"680":1,"681":1,"683":1,"687":1,"707":1,"742":2,"743":2}}],["acceptable",{"2":{"175":2,"725":1}}],["acceptall",{"2":{"38":1,"94":2,"97":1}}],["accepted",{"2":{"138":1,"252":1,"260":1,"723":1,"725":1,"726":2,"735":1,"749":3,"750":1,"753":2}}],["accepts",{"2":{"39":1,"238":1,"748":1}}],["accept",{"2":{"38":1,"94":1,"135":1,"637":1,"748":3}}],["accessed",{"2":{"217":1,"263":1,"266":1}}],["accessing",{"2":{"172":1,"258":1,"259":1}}],["accessible",{"2":{"65":1,"106":1,"175":1,"229":1,"243":1,"250":1,"260":1}}],["access",{"2":{"12":1,"21":1,"53":3,"60":2,"65":1,"117":1,"128":1,"137":2,"164":1,"177":1,"213":1,"217":2,"220":1,"246":1,"247":1,"248":2,"249":3,"250":1,"251":1,"258":1,"260":6,"262":1,"263":5,"267":1,"268":1,"650":1}}],["ads",{"2":{"249":1}}],["ad",{"2":{"249":3}}],["adopting",{"2":{"247":1,"250":1,"268":1}}],["adopted",{"2":{"247":1}}],["adopt",{"2":{"246":1,"259":1,"261":1}}],["ado",{"2":{"185":1}}],["adapter",{"2":{"175":2,"181":1}}],["adapters",{"2":{"175":2}}],["adhere",{"2":{"121":1,"260":1}}],["adminiroha2client",{"2":{"187":3}}],["administrator",{"2":{"138":1,"160":2,"161":1}}],["administrators",{"2":{"65":1}}],["adminkeypair",{"2":{"187":3}}],["admin",{"2":{"185":1,"187":9,"188":4,"189":7,"190":4,"191":3,"670":2}}],["admittedly",{"2":{"97":1}}],["advice",{"2":{"247":1,"252":1,"256":1}}],["advised",{"2":{"108":1,"252":1}}],["advise",{"2":{"14":1,"109":1,"219":1,"252":1}}],["advance",{"2":{"250":1}}],["advanced",{"0":{"105":1},"1":{"106":1,"107":1,"108":1,"109":1,"110":1},"2":{"28":1,"36":1,"46":1,"208":1,"224":1,"265":1,"714":1}}],["advantage",{"2":{"101":1}}],["advantages",{"2":{"97":1}}],["adjust",{"2":{"18":1}}],["adjusted",{"2":{"18":1,"174":1}}],["addclient",{"2":{"174":1}}],["added",{"2":{"88":1,"135":1,"137":1,"138":1,"183":1,"188":2,"189":1,"217":1,"228":1,"237":1,"249":1,"265":1,"311":1,"313":1,"487":1,"489":1,"720":1}}],["additional",{"2":{"249":2,"259":1,"264":1,"629":1}}],["additionally",{"2":{"25":1,"252":1}}],["addition",{"2":{"189":1,"244":1,"252":1}}],["adding",{"0":{"264":1},"1":{"265":1,"266":1},"2":{"16":1,"42":1,"150":1,"244":1,"252":1,"265":2,"750":1}}],["addr=withorigin",{"2":{"196":1}}],["addr=",{"2":{"20":1}}],["addr",{"0":{"149":1},"2":{"18":4,"21":1,"22":1,"127":1,"143":1,"149":1}}],["addresses",{"0":{"118":1,"147":1},"1":{"119":1,"120":1,"148":1,"149":1,"150":1},"2":{"18":1,"20":1,"21":1,"118":1,"143":1,"146":1,"253":1,"259":1,"714":4}}],["address",{"2":{"12":1,"18":17,"20":1,"21":1,"22":1,"65":1,"97":1,"119":1,"120":1,"141":1,"143":3,"146":4,"149":2,"150":1,"196":2,"249":1,"259":2,"260":2,"490":1,"704":1,"714":3,"750":1}}],["add",{"2":{"5":1,"16":2,"22":1,"39":1,"53":2,"60":2,"83":1,"88":1,"104":1,"119":1,"123":1,"129":1,"135":1,"141":1,"143":1,"159":1,"174":2,"178":1,"187":3,"188":1,"189":3,"190":3,"191":1,"200":1,"214":2,"215":2,"217":1,"219":1,"221":1,"232":1,"244":1,"265":3,"663":4}}],["alerts",{"2":{"260":1}}],["alphabet",{"2":{"252":1,"253":1}}],["alongside",{"2":{"237":1,"246":1}}],["alas",{"2":{"221":1}}],["alternative",{"2":{"175":1,"237":1,"268":1}}],["alternatively",{"2":{"16":1,"269":1}}],["although",{"2":{"65":1,"207":1,"272":1}}],["aliases",{"2":{"282":2}}],["alias",{"2":{"186":2,"219":1,"282":2,"324":1,"328":1,"333":1,"351":1,"352":1,"410":1,"411":1,"412":1,"413":1,"422":1,"423":1,"424":1,"425":1,"432":1,"448":1,"454":1,"455":1,"456":1,"541":1,"542":1,"543":1,"566":1,"569":1,"619":1,"620":1}}],["alices",{"2":{"221":1}}],["alice",{"2":{"53":7,"61":2,"66":4,"71":2,"78":1,"92":2,"93":2,"94":2,"97":3,"116":4,"128":14,"136":1,"164":8,"175":1,"176":1,"177":1,"178":1,"179":2,"180":2,"181":1,"188":1,"189":3,"190":3,"193":30,"213":1,"214":2,"218":1,"220":1,"221":5,"222":1,"223":1,"663":3,"664":1}}],["alignment",{"2":{"103":1}}],["align",{"2":{"21":1,"260":2}}],["already",{"2":{"29":1,"40":1,"78":1,"81":1,"88":1,"107":1,"116":2,"131":1,"146":1,"154":1,"170":1,"178":1,"196":1,"200":1,"221":1,"227":1,"229":1,"256":2,"666":1,"717":1}}],["algorithms",{"2":{"134":1,"202":2,"260":1}}],["algorithm",{"0":{"298":1},"2":{"28":1,"143":1,"218":1,"230":2,"238":8,"239":1,"496":2}}],["almost",{"2":{"16":1,"656":1,"666":1,"749":1}}],["also",{"2":{"14":1,"17":1,"18":3,"20":1,"21":1,"24":1,"25":1,"36":1,"41":1,"42":1,"49":1,"51":1,"62":1,"81":1,"88":2,"97":2,"100":1,"103":1,"110":1,"119":1,"129":1,"136":1,"137":1,"143":1,"148":1,"151":1,"154":1,"167":1,"174":2,"175":1,"176":1,"178":1,"185":1,"187":3,"188":5,"189":6,"190":6,"191":3,"197":1,"204":1,"207":1,"210":3,"211":1,"212":1,"214":1,"217":2,"219":1,"221":2,"222":1,"230":1,"231":1,"232":1,"233":2,"234":1,"235":1,"238":1,"241":1,"246":1,"249":1,"253":1,"255":1,"256":1,"259":1,"264":1,"273":2,"628":1,"682":1,"748":1,"750":1}}],["always",{"2":{"13":1,"41":1,"65":1,"126":1,"143":1,"178":2,"203":1,"224":1,"243":1,"248":2,"253":1,"258":1,"261":1,"656":1,"666":1}}],["allaccountsignaturesand",{"2":{"540":1}}],["allocation",{"2":{"219":1}}],["allocated",{"2":{"188":1,"660":1}}],["allocate",{"2":{"65":1}}],["alloc",{"2":{"104":3,"107":1,"108":1}}],["allowance",{"2":{"160":1}}],["allowall",{"2":{"62":1}}],["allowing",{"2":{"158":1}}],["allows",{"2":{"63":1,"69":1,"95":1,"141":1,"172":1,"217":1,"241":1,"248":1,"255":1,"268":1,"642":1,"643":2,"644":1,"663":22}}],["allow",{"2":{"39":1,"55":1,"60":1,"62":4,"137":3,"154":1,"215":1,"260":1,"659":1}}],["allowed",{"2":{"28":1,"62":1,"63":1,"82":1,"126":1,"137":1,"146":2,"230":1,"656":1}}],["all",{"2":{"5":2,"14":1,"16":1,"18":2,"21":1,"22":1,"25":1,"36":1,"41":1,"43":1,"62":8,"63":2,"65":2,"66":1,"67":1,"71":2,"72":1,"77":1,"79":1,"82":1,"83":1,"85":1,"86":1,"87":2,"88":3,"92":1,"97":2,"98":1,"100":2,"103":2,"104":2,"107":1,"110":1,"111":1,"112":2,"120":1,"125":2,"126":1,"132":1,"135":5,"136":1,"141":2,"150":1,"174":2,"175":1,"176":3,"177":1,"181":1,"183":1,"187":6,"188":4,"189":4,"190":3,"191":3,"192":1,"200":2,"201":1,"202":1,"203":1,"204":2,"212":1,"213":2,"214":1,"217":1,"219":1,"220":1,"221":2,"224":2,"230":2,"232":1,"233":1,"238":1,"241":3,"243":1,"248":1,"249":1,"253":2,"256":1,"259":4,"260":2,"282":1,"283":1,"339":1,"626":1,"630":1,"653":2,"656":2,"658":1,"663":1,"665":1,"667":1,"668":1,"669":1,"670":1,"671":1,"673":1,"674":1,"676":1,"679":1,"680":1,"681":1,"683":2,"684":1,"686":1,"687":1,"688":1,"689":1,"694":1,"696":1,"697":1,"700":1,"704":1,"705":1,"709":1,"710":1,"713":1,"720":1,"725":1,"728":1,"749":1}}],["average",{"2":{"735":1}}],["availability",{"2":{"65":1,"247":1}}],["available",{"0":{"244":1},"2":{"13":1,"40":1,"65":2,"97":1,"120":1,"124":1,"125":1,"134":1,"150":1,"153":1,"155":1,"170":1,"175":3,"181":1,"192":1,"197":1,"201":1,"202":2,"217":1,"224":1,"238":1,"243":1,"244":2,"249":1,"262":1,"282":1,"629":1,"656":1,"666":2}}],["avoided",{"2":{"273":1}}],["avoiding",{"2":{"246":1}}],["avoid",{"2":{"6":1,"148":1,"175":2,"231":1,"249":4,"253":2,"256":1,"259":2,"261":1,"658":1,"663":1}}],["asian",{"2":{"236":1}}],["aside",{"2":{"151":1,"630":1}}],["asassetid",{"2":{"189":1,"190":3,"191":1}}],["asassetdefinitionid",{"2":{"189":1}}],["asaccountid",{"2":{"188":1,"190":2,"191":1}}],["asdomainid",{"2":{"187":2}}],["asname",{"2":{"187":1}}],["async",{"2":{"176":1,"181":3,"217":1}}],["asynchronously",{"2":{"726":1}}],["asynchronous",{"2":{"174":1,"187":1,"215":1}}],["ask",{"2":{"161":1,"177":1,"213":1,"220":1,"253":1}}],["asks",{"2":{"141":1}}],["asked",{"2":{"20":1,"21":1}}],["ascii",{"2":{"134":1,"273":1}}],["aspects",{"2":{"246":1,"250":1}}],["aspect",{"2":{"28":1}}],["assistance",{"2":{"725":1}}],["assistant",{"2":{"263":1}}],["asstring",{"2":{"187":1,"188":1,"189":1}}],["associated",{"2":{"57":1,"85":1,"86":1,"202":1,"248":1}}],["associative",{"2":{"50":1}}],["assessment",{"2":{"260":1}}],["assessments",{"2":{"260":1}}],["assembly",{"2":{"100":1,"174":1,"233":1}}],["assertequals",{"2":{"193":5}}],["assertthrows",{"2":{"193":1}}],["assertions",{"2":{"193":7}}],["assertion",{"2":{"175":2}}],["assert",{"2":{"53":1,"220":1}}],["assettransferbox",{"0":{"315":1},"2":{"584":1}}],["assetchanged",{"0":{"303":1},"2":{"311":2}}],["asseteventset",{"0":{"313":1},"2":{"312":1}}],["assetevent",{"0":{"311":1},"2":{"290":1}}],["asseteventfilter",{"0":{"312":1},"2":{"94":1,"341":1}}],["assetkey",{"2":{"193":3}}],["assetmetadatavalue2",{"2":{"193":3}}],["assetmetadatavalue",{"2":{"193":2}}],["assetmetadatakey",{"2":{"193":4}}],["assetvalue",{"0":{"316":1},"2":{"187":1,"189":2,"190":2,"193":6,"302":1,"303":1,"691":1}}],["assetvaluetype",{"0":{"317":1,"447":1},"2":{"25":1,"178":2,"187":1,"189":3,"193":4,"221":1,"304":1,"447":2,"450":1,"596":4}}],["assetfilter",{"2":{"94":2}}],["assetid",{"0":{"314":1,"435":1,"461":1,"560":1},"2":{"52":1,"92":8,"93":4,"178":3,"179":7,"190":2,"191":2,"193":6,"221":2,"222":2,"223":1,"289":1,"302":1,"303":1,"311":3,"312":1,"329":1,"380":1,"383":1,"384":1,"393":1,"414":2,"435":1,"440":1,"461":1,"511":1,"533":1,"560":1,"582":1,"583":1,"598":1,"685":1,"691":1,"692":1,"743":1}}],["assetdefinitiontotalquantitychanged",{"0":{"310":1},"2":{"305":1}}],["assetdefinitionownerchanged",{"0":{"309":1},"2":{"305":1}}],["assetdefinitioneventset",{"0":{"307":1},"2":{"306":1}}],["assetdefinitioneventfilter",{"0":{"306":1},"2":{"341":1}}],["assetdefinitionevent",{"0":{"305":1},"2":{"343":1}}],["assetdefinitionvaluequery",{"2":{"193":4}}],["assetdefinition",{"0":{"304":1,"504":1,"512":1,"534":1,"558":1,"599":1},"2":{"52":1,"92":1,"128":2,"164":2,"178":3,"189":2,"221":3,"305":1,"341":1,"342":1,"343":1,"393":1,"415":2,"509":2,"515":2,"537":2,"558":1,"584":1,"604":2,"683":1,"684":1,"743":1}}],["assetdefinitionid",{"0":{"308":1,"434":1,"460":1,"558":1,"559":1,"580":1},"2":{"52":1,"92":1,"94":1,"178":4,"179":5,"221":1,"222":1,"304":1,"305":4,"306":1,"309":1,"310":1,"314":1,"342":2,"367":1,"381":1,"382":1,"386":1,"388":1,"393":1,"398":1,"414":2,"434":1,"450":1,"460":1,"512":1,"534":1,"558":1,"559":1,"580":1,"584":1,"599":1,"664":1,"688":1,"690":1,"693":1,"694":1,"743":1}}],["asset",{"0":{"26":1,"52":1,"302":1,"329":1,"440":1,"503":1,"511":1,"533":1,"560":1,"582":1,"583":1,"598":1,"629":1,"682":1,"743":1},"1":{"630":1,"631":1,"632":1,"633":1,"683":1,"684":1,"685":1,"686":1,"687":1,"688":1,"689":1,"690":1,"691":1,"692":1,"693":1,"694":1,"745":1,"746":1,"748":1,"749":1},"2":{"25":2,"29":6,"33":1,"41":5,"42":6,"43":1,"46":1,"50":3,"51":1,"52":3,"55":1,"57":3,"86":1,"92":1,"94":5,"97":1,"128":4,"137":5,"164":2,"178":3,"179":1,"180":11,"187":3,"189":8,"190":15,"191":15,"193":13,"200":1,"201":1,"204":6,"205":1,"206":1,"214":8,"221":15,"222":6,"223":3,"289":1,"290":1,"303":1,"309":1,"310":1,"311":1,"315":2,"332":2,"341":1,"342":2,"367":1,"386":1,"388":1,"393":1,"415":2,"444":2,"503":1,"509":2,"515":2,"537":2,"560":1,"584":1,"604":2,"626":1,"629":1,"632":1,"633":1,"660":1,"663":24,"664":8,"681":1,"683":3,"684":5,"685":2,"686":1,"687":1,"688":1,"689":1,"690":1,"691":2,"692":1,"693":1,"694":5,"741":2,"743":3}}],["assets`",{"2":{"180":1}}],["assets",{"0":{"24":1,"137":1,"178":1,"179":1,"180":1,"189":1,"190":1,"191":1,"204":1,"205":1,"206":1,"214":1,"221":1,"222":1,"223":1,"630":1,"631":1,"632":1,"633":1},"1":{"25":1,"26":1,"27":1},"2":{"24":3,"25":1,"27":2,"29":3,"33":1,"40":2,"41":7,"43":6,"44":4,"50":1,"51":1,"55":1,"56":1,"57":1,"66":1,"80":1,"86":1,"129":2,"130":2,"137":3,"165":2,"166":1,"167":1,"172":1,"178":1,"179":1,"180":4,"189":7,"190":4,"191":4,"200":1,"203":1,"204":1,"205":1,"206":1,"214":1,"221":2,"222":1,"223":1,"227":1,"237":1,"247":1,"248":1,"289":1,"629":1,"630":3,"631":2,"649":1,"660":1,"661":2,"663":4,"682":1,"683":1,"686":1,"687":1,"688":1,"689":1,"690":1,"699":1}}],["assuming",{"2":{"253":1}}],["assumptions",{"2":{"16":1,"24":1,"178":1,"189":1,"214":1,"221":1,"273":1}}],["assumed",{"2":{"43":1,"56":1,"100":1,"139":1,"672":1}}],["assumes",{"2":{"16":1,"173":1,"691":1}}],["assume",{"2":{"13":1,"137":1,"175":1,"185":3,"217":2,"272":1,"273":2}}],["as",{"2":{"5":3,"6":1,"8":1,"12":2,"14":1,"16":2,"18":1,"24":2,"25":1,"28":1,"36":2,"39":1,"42":1,"43":2,"45":1,"50":1,"53":1,"56":1,"57":1,"62":1,"65":1,"67":3,"69":1,"72":1,"78":1,"81":1,"82":2,"86":1,"88":1,"90":4,"92":1,"94":1,"97":4,"99":1,"101":8,"103":1,"104":3,"105":1,"106":2,"107":1,"110":1,"112":2,"116":1,"119":1,"124":1,"125":4,"126":1,"127":2,"128":4,"129":5,"131":1,"134":1,"137":3,"138":1,"141":4,"143":1,"151":1,"160":3,"161":1,"165":2,"167":1,"171":1,"172":1,"174":4,"175":10,"176":4,"177":1,"178":1,"180":12,"181":5,"183":2,"188":1,"200":1,"203":2,"212":1,"213":1,"214":1,"217":3,"219":1,"220":1,"221":4,"222":1,"229":1,"231":4,"232":2,"234":2,"236":1,"238":5,"241":2,"243":3,"245":1,"247":3,"248":1,"249":2,"250":4,"252":3,"253":2,"254":1,"255":3,"256":3,"259":5,"261":2,"263":2,"264":2,"266":2,"269":2,"271":1,"273":1,"278":1,"281":1,"286":2,"287":1,"627":1,"628":1,"630":1,"637":2,"647":1,"648":2,"650":2,"653":2,"656":1,"657":2,"658":3,"666":3,"668":2,"669":2,"682":1,"683":2,"699":1,"700":1,"703":1,"714":2,"717":2,"720":1,"723":1,"725":1,"738":1,"740":1,"746":1,"749":2}}],["a",{"0":{"6":1,"19":1,"60":1,"61":1,"66":1,"73":1,"93":1,"95":1,"96":1,"103":1,"104":1,"107":1,"133":1,"136":1,"161":1,"176":1,"201":1,"203":1,"212":1,"219":1,"264":1,"268":1,"269":1,"272":1},"1":{"7":1,"8":1,"9":1,"20":1,"21":1,"74":1,"75":1,"76":1,"77":1,"78":1,"79":1,"80":1,"134":1,"135":1,"265":1,"266":1},"2":{"2":1,"5":4,"6":2,"7":1,"10":2,"12":2,"13":1,"14":2,"16":5,"17":1,"18":5,"19":1,"22":2,"24":2,"25":2,"27":1,"28":11,"29":7,"31":2,"32":2,"33":1,"36":2,"38":6,"39":9,"40":4,"41":4,"42":15,"43":5,"45":4,"46":1,"49":5,"50":2,"51":1,"52":2,"53":1,"56":11,"57":5,"59":3,"60":1,"62":7,"65":4,"66":3,"67":3,"68":2,"69":3,"71":6,"72":9,"73":1,"74":5,"76":2,"77":1,"78":3,"79":2,"80":1,"81":3,"82":1,"83":3,"84":2,"85":2,"87":2,"88":4,"89":4,"90":1,"92":2,"93":3,"94":12,"95":1,"96":1,"97":9,"98":4,"99":1,"100":4,"101":5,"103":5,"104":2,"105":2,"106":6,"107":1,"110":1,"115":1,"117":2,"120":4,"121":1,"124":2,"125":11,"126":4,"127":3,"128":9,"130":3,"134":3,"135":2,"136":4,"137":18,"138":2,"139":2,"140":2,"141":13,"143":9,"145":1,"146":4,"150":4,"151":2,"153":2,"154":6,"155":1,"156":1,"157":2,"158":2,"159":1,"160":8,"161":3,"162":2,"163":3,"165":2,"166":1,"171":3,"172":1,"174":4,"175":14,"176":7,"177":12,"178":3,"181":6,"182":1,"183":2,"185":3,"186":2,"187":6,"188":9,"189":4,"190":2,"191":1,"192":4,"196":6,"197":2,"199":1,"200":3,"201":5,"202":11,"203":4,"204":1,"207":2,"210":2,"211":3,"212":3,"213":7,"214":6,"215":6,"217":12,"218":5,"219":13,"220":14,"221":8,"222":2,"224":7,"226":1,"227":1,"228":3,"229":2,"230":6,"231":2,"232":2,"233":1,"234":4,"236":1,"237":1,"238":21,"239":2,"241":3,"243":1,"245":2,"246":4,"247":4,"248":6,"249":18,"250":10,"252":14,"253":12,"254":6,"255":3,"256":14,"258":7,"259":6,"260":4,"261":1,"263":8,"264":2,"265":4,"266":4,"268":11,"269":3,"270":5,"272":4,"273":5,"278":3,"280":2,"281":2,"282":2,"283":2,"286":3,"287":1,"628":8,"629":1,"631":2,"634":2,"640":2,"641":1,"643":1,"644":1,"646":1,"649":1,"650":1,"651":1,"652":3,"654":1,"655":2,"656":8,"657":4,"658":8,"660":2,"661":2,"663":8,"664":2,"666":6,"667":1,"672":4,"680":1,"682":2,"687":1,"699":2,"703":2,"705":4,"709":1,"714":1,"716":1,"717":2,"719":1,"720":2,"722":1,"723":1,"725":2,"726":2,"728":2,"729":1,"730":1,"732":1,"735":2,"737":1,"738":1,"740":3,"745":1,"748":1,"750":1}}],["angle",{"2":{"282":1}}],["anomalies",{"2":{"260":1}}],["another",{"2":{"28":1,"38":1,"41":1,"42":1,"53":1,"60":1,"94":1,"100":1,"107":1,"137":3,"141":1,"143":1,"154":1,"175":1,"176":1,"179":1,"190":1,"205":1,"221":1,"249":1,"250":2,"256":1,"281":1,"663":1,"664":1}}],["answer",{"2":{"252":1,"268":1}}],["anticipating",{"2":{"250":1}}],["anticipate",{"2":{"88":1}}],["annotate",{"2":{"221":1}}],["annotations",{"2":{"214":1}}],["analysis",{"2":{"231":1,"247":1}}],["analyze",{"2":{"137":1}}],["anatomy",{"0":{"73":1},"1":{"74":1,"75":1,"76":1,"77":1,"78":1,"79":1,"80":1}}],["anyaccountsignatureor",{"2":{"540":1}}],["anyaccount",{"2":{"345":1}}],["anyassetdefinition",{"2":{"345":1}}],["anyasset",{"2":{"292":1}}],["anyway",{"2":{"656":1}}],["anyways",{"2":{"105":1}}],["anywhere",{"2":{"219":1,"253":1}}],["anything",{"2":{"56":1,"101":3,"139":1,"171":1,"212":1,"215":1,"224":1,"672":1}}],["anyone",{"2":{"42":1,"141":1,"255":1,"256":1}}],["any",{"2":{"5":1,"6":2,"16":1,"18":1,"28":1,"39":1,"41":2,"42":1,"88":1,"94":1,"97":3,"101":1,"102":1,"108":1,"125":1,"135":1,"136":1,"137":1,"140":1,"141":2,"153":2,"156":1,"174":2,"175":1,"176":1,"178":2,"186":1,"200":1,"211":1,"214":4,"217":1,"219":2,"226":1,"230":1,"233":1,"234":1,"238":1,"241":1,"245":1,"249":1,"250":1,"256":1,"260":2,"264":2,"339":1,"341":1,"656":1,"705":1}}],["an",{"0":{"94":1,"177":1,"188":1,"202":1,"213":1,"220":1},"2":{"2":1,"6":2,"16":1,"17":1,"18":1,"25":2,"28":1,"29":10,"32":2,"36":2,"38":2,"39":2,"40":1,"41":1,"42":14,"44":2,"52":2,"54":1,"59":1,"62":2,"63":2,"65":2,"66":1,"69":1,"71":1,"72":5,"75":1,"79":1,"85":1,"86":2,"91":1,"94":12,"95":2,"97":4,"106":1,"108":1,"109":1,"110":1,"125":1,"126":4,"127":2,"128":1,"135":1,"137":1,"138":1,"141":5,"143":1,"146":2,"153":2,"160":1,"166":1,"171":1,"174":1,"175":3,"176":2,"177":7,"178":2,"183":2,"185":1,"187":1,"188":6,"192":1,"194":1,"195":1,"196":3,"198":1,"199":1,"201":1,"204":1,"207":2,"210":1,"211":2,"213":4,"214":3,"215":2,"218":2,"219":6,"220":10,"221":7,"224":2,"226":1,"227":1,"230":1,"232":1,"233":1,"234":1,"238":3,"245":1,"246":1,"248":2,"249":5,"250":2,"252":1,"253":2,"255":1,"256":2,"259":4,"260":2,"263":1,"264":2,"268":1,"272":3,"273":4,"282":1,"283":1,"287":3,"628":2,"629":1,"630":1,"632":1,"633":1,"642":2,"650":1,"654":1,"656":1,"657":2,"658":1,"661":1,"663":5,"667":1,"684":2,"699":1,"707":1,"709":1,"730":2,"741":1}}],["android",{"2":{"259":1}}],["and",{"0":{"115":1,"122":1,"137":1,"138":1,"142":1,"145":1,"178":1,"180":1,"187":1,"189":1,"204":1,"214":1,"221":1,"234":1,"255":1,"263":1,"273":1,"639":2},"1":{"139":1,"140":1,"141":1},"2":{"0":2,"2":2,"3":2,"5":2,"6":2,"10":3,"12":1,"13":4,"14":4,"16":6,"18":4,"19":1,"20":3,"21":4,"22":4,"24":1,"25":1,"27":2,"28":7,"29":5,"32":1,"36":2,"39":6,"40":2,"41":1,"42":6,"43":4,"44":1,"45":3,"47":1,"52":1,"53":2,"55":1,"56":2,"57":2,"59":1,"62":3,"63":1,"64":1,"65":2,"67":2,"69":1,"72":2,"74":1,"78":1,"79":1,"81":1,"82":3,"85":1,"87":2,"88":3,"90":2,"91":2,"94":4,"97":10,"98":3,"99":1,"100":5,"101":7,"103":5,"104":4,"106":2,"107":1,"108":1,"110":1,"115":2,"116":1,"117":3,"118":2,"119":1,"121":1,"122":1,"123":1,"124":2,"125":5,"126":2,"127":3,"128":5,"129":1,"130":3,"132":1,"134":2,"135":2,"137":18,"138":1,"141":4,"143":6,"145":1,"146":4,"147":1,"151":3,"152":1,"157":1,"160":1,"161":1,"162":2,"165":5,"166":8,"167":10,"169":1,"172":4,"173":2,"174":2,"175":12,"176":2,"177":4,"178":3,"180":2,"181":2,"183":2,"185":6,"186":2,"187":1,"188":1,"189":2,"190":2,"192":4,"196":1,"198":1,"199":2,"201":1,"202":4,"203":7,"204":1,"207":1,"208":1,"210":2,"211":2,"212":2,"213":3,"214":4,"215":5,"217":7,"218":2,"219":4,"220":6,"221":12,"222":2,"223":1,"224":4,"226":2,"227":4,"228":1,"229":7,"230":2,"231":6,"232":2,"233":1,"234":3,"235":1,"236":2,"237":2,"238":13,"241":2,"243":1,"244":2,"245":2,"246":6,"247":11,"248":5,"249":17,"250":13,"251":1,"252":5,"253":5,"254":2,"255":4,"256":6,"257":1,"258":6,"259":8,"260":19,"261":2,"262":1,"263":6,"264":2,"265":1,"266":3,"268":4,"270":3,"272":4,"273":3,"279":3,"280":3,"282":3,"283":3,"287":1,"405":1,"626":2,"627":2,"628":3,"630":2,"631":3,"633":1,"637":2,"640":1,"644":1,"647":1,"649":1,"650":1,"654":1,"655":2,"656":5,"658":4,"659":1,"660":1,"662":1,"663":4,"664":1,"665":2,"666":6,"672":1,"680":1,"699":2,"700":1,"703":2,"704":1,"705":1,"706":1,"714":4,"717":2,"719":1,"720":2,"725":2,"726":1,"728":3,"729":1,"741":1,"742":1,"743":1,"746":1,"749":1}}],["atindex",{"0":{"318":1},"2":{"339":2}}],["atleastoneallow",{"2":{"62":1}}],["attempt",{"2":{"178":1,"214":1,"652":1}}],["attempts",{"2":{"151":1,"252":1,"253":1}}],["attention",{"2":{"46":1,"178":1,"249":1}}],["attackers",{"2":{"253":1,"268":1}}],["attacker",{"2":{"248":1,"256":1}}],["attack",{"2":{"247":1,"249":1}}],["attacks",{"2":{"148":1,"238":1,"249":1,"253":1}}],["attachment",{"2":{"265":1}}],["attachments",{"2":{"265":1}}],["attaching",{"2":{"196":1}}],["attach",{"2":{"72":1,"265":1}}],["attached",{"2":{"50":1,"80":1,"97":1,"671":1,"678":1}}],["attribute",{"2":{"103":1}}],["at",{"2":{"2":1,"5":2,"18":3,"20":1,"22":1,"37":1,"41":1,"50":1,"62":2,"63":1,"65":1,"72":1,"88":9,"94":1,"99":1,"105":1,"106":1,"110":1,"113":1,"128":1,"137":3,"158":1,"174":1,"175":4,"177":1,"178":2,"180":1,"186":2,"196":4,"203":1,"213":1,"214":1,"215":2,"220":1,"230":1,"232":1,"233":1,"253":1,"273":1,"628":1,"640":1,"642":1,"652":1,"655":1,"656":1,"665":1,"666":1,"675":1,"710":1,"717":2,"728":1,"735":1}}],["ssh",{"0":{"263":2},"2":{"262":3,"263":21,"264":4,"265":3,"266":5,"268":1}}],["sss",{"2":{"252":1}}],["s^l=2^entropy",{"2":{"252":1}}],["s^l",{"2":{"252":1}}],["sms",{"2":{"247":1,"259":2}}],["smallstr",{"2":{"218":1}}],["smallest",{"2":{"110":1}}],["smaller",{"2":{"14":1,"88":2,"90":1,"234":1}}],["small",{"2":{"65":1,"88":1,"154":1,"181":1,"182":1,"226":1,"238":2,"273":1}}],["smartly",{"2":{"234":1}}],["smartcontracts",{"2":{"655":1}}],["smartcontract",{"2":{"103":1,"104":1,"137":1,"656":1}}],["smart",{"0":{"102":1,"104":1,"105":1,"233":1,"641":1},"1":{"103":1,"104":1,"106":1,"107":1,"108":1,"109":1,"110":1},"2":{"36":1,"79":1,"88":1,"90":2,"93":1,"97":1,"100":1,"104":2,"105":1,"106":1,"110":1,"141":1,"165":1,"218":1,"233":3,"626":1,"641":2,"646":1,"664":1}}],["swapped",{"2":{"630":1}}],["swarm",{"2":{"196":5,"197":1,"218":1}}],["swift",{"2":{"287":2}}],["switching",{"2":{"203":1}}],["switch",{"2":{"181":1,"203":1}}],["snip",{"2":{"175":2,"176":1}}],["snippet",{"0":{"2":1},"2":{"2":3,"3":1,"5":6,"192":1,"202":1}}],["snippets",{"0":{"0":1,"3":1,"4":1},"1":{"1":1,"2":1,"3":1,"4":1,"5":1},"2":{"0":1,"3":7,"4":4,"5":1}}],["snapshot",{"2":{"143":2,"185":8,"196":9}}],["sl=2entropy",{"2":{"252":2}}],["sl",{"2":{"252":2}}],["sls^lsl",{"2":{"252":1}}],["sledgehammer",{"2":{"230":1}}],["slf4jlogconsumer",{"2":{"186":2}}],["slf4j",{"2":{"186":1}}],["slow",{"2":{"137":1}}],["slower",{"2":{"97":1}}],["slightly",{"2":{"87":1,"88":1,"210":1,"256":1}}],["sys",{"2":{"214":1}}],["systematic",{"2":{"247":1}}],["system",{"0":{"644":1},"1":{"647":1},"2":{"16":2,"17":1,"67":1,"82":2,"137":1,"171":2,"172":2,"185":1,"187":1,"188":1,"189":1,"190":1,"210":1,"232":1,"241":2,"260":4,"263":7,"266":2,"278":1,"282":1,"283":1,"626":1,"628":1,"644":1,"705":1}}],["systems",{"2":{"13":1,"16":2,"20":1,"238":1,"242":2,"263":1,"264":1,"627":2}}],["syntactic",{"2":{"219":1}}],["syntax",{"2":{"100":2,"200":1,"214":1}}],["synthetic",{"2":{"130":2}}],["synchronize",{"2":{"272":1,"728":1}}],["synchronized",{"2":{"270":1}}],["synchronous",{"2":{"219":1,"224":1}}],["sync",{"2":{"127":1,"224":1,"228":1}}],["symbols",{"2":{"252":4,"253":1,"273":1,"287":1}}],["symbol",{"2":{"83":1,"221":1,"273":1}}],["scissors",{"2":{"256":1}}],["scenario",{"2":{"253":1}}],["scenarios",{"2":{"88":1,"250":1,"260":1}}],["scss",{"2":{"181":1}}],["scale",{"2":{"94":1,"103":1,"137":1,"174":1,"231":1,"457":1,"458":1,"714":5,"718":1,"727":1,"736":1,"738":1,"739":1,"747":1,"748":2,"749":1,"751":1}}],["scan",{"2":{"82":2}}],["schedule",{"0":{"528":1},"2":{"87":1,"357":2}}],["scheduled",{"0":{"88":1},"2":{"85":1,"87":2,"88":2,"97":1}}],["scheme",{"2":{"141":1,"238":2}}],["schemes",{"2":{"77":1}}],["schema",{"0":{"84":1,"288":1,"744":1},"1":{"289":1,"290":1,"291":1,"292":1,"293":1,"294":1,"295":1,"296":1,"297":1,"298":1,"299":1,"300":1,"301":1,"302":1,"303":1,"304":1,"305":1,"306":1,"307":1,"308":1,"309":1,"310":1,"311":1,"312":1,"313":1,"314":1,"315":1,"316":1,"317":1,"318":1,"319":1,"320":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"329":1,"330":1,"331":1,"332":1,"333":1,"334":1,"335":1,"336":1,"337":1,"338":1,"339":1,"340":1,"341":1,"342":1,"343":1,"344":1,"345":1,"346":1,"347":1,"348":1,"349":1,"350":1,"351":1,"352":1,"353":1,"354":1,"355":1,"356":1,"357":1,"358":1,"359":1,"360":1,"361":1,"362":1,"363":1,"364":1,"365":1,"366":1,"367":1,"368":1,"369":1,"370":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"378":1,"379":1,"380":1,"381":1,"382":1,"383":1,"384":1,"385":1,"386":1,"387":1,"388":1,"389":1,"390":1,"391":1,"392":1,"393":1,"394":1,"395":1,"396":1,"397":1,"398":1,"399":1,"400":1,"401":1,"402":1,"403":1,"404":1,"405":1,"406":1,"407":1,"408":1,"409":1,"410":1,"411":1,"412":1,"413":1,"414":1,"415":1,"416":1,"417":1,"418":1,"419":1,"420":1,"421":1,"422":1,"423":1,"424":1,"425":1,"426":1,"427":1,"428":1,"429":1,"430":1,"431":1,"432":1,"433":1,"434":1,"435":1,"436":1,"437":1,"438":1,"439":1,"440":1,"441":1,"442":1,"443":1,"444":1,"445":1,"446":1,"447":1,"448":1,"449":1,"450":1,"451":1,"452":1,"453":1,"454":1,"455":1,"456":1,"457":1,"458":1,"459":1,"460":1,"461":1,"462":1,"463":1,"464":1,"465":1,"466":1,"467":1,"468":1,"469":1,"470":1,"471":1,"472":1,"473":1,"474":1,"475":1,"476":1,"477":1,"478":1,"479":1,"480":1,"481":1,"482":1,"483":1,"484":1,"485":1,"486":1,"487":1,"488":1,"489":1,"490":1,"491":1,"492":1,"493":1,"494":1,"495":1,"496":1,"497":1,"498":1,"499":1,"500":1,"501":1,"502":1,"503":1,"504":1,"505":1,"506":1,"507":1,"508":1,"509":1,"510":1,"511":1,"512":1,"513":1,"514":1,"515":1,"516":1,"517":1,"518":1,"519":1,"520":1,"521":1,"522":1,"523":1,"524":1,"525":1,"526":1,"527":1,"528":1,"529":1,"530":1,"531":1,"532":1,"533":1,"534":1,"535":1,"536":1,"537":1,"538":1,"539":1,"540":1,"541":1,"542":1,"543":1,"544":1,"545":1,"546":1,"547":1,"548":1,"549":1,"550":1,"551":1,"552":1,"553":1,"554":1,"555":1,"556":1,"557":1,"558":1,"559":1,"560":1,"561":1,"562":1,"563":1,"564":1,"565":1,"566":1,"567":1,"568":1,"569":1,"570":1,"571":1,"572":1,"573":1,"574":1,"575":1,"576":1,"577":1,"578":1,"579":1,"580":1,"581":1,"582":1,"583":1,"584":1,"585":1,"586":1,"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"593":1,"594":1,"595":1,"596":1,"597":1,"598":1,"599":1,"600":1,"601":1,"602":1,"603":1,"604":1,"605":1,"606":1,"607":1,"608":1,"609":1,"610":1,"611":1,"612":1,"613":1,"614":1,"615":1,"616":1,"617":1,"618":1,"619":1,"620":1,"621":1,"622":1,"623":1,"624":1,"625":1,"745":1,"746":1},"2":{"81":1,"137":1,"492":1,"493":2,"744":2,"746":1}}],["scoped",{"0":{"83":1},"2":{"74":1,"82":7,"83":4,"668":1,"669":1,"699":1}}],["scope",{"0":{"82":1},"1":{"83":1},"2":{"65":1,"81":1,"174":1,"215":1}}],["scrutinizes",{"2":{"260":1}}],["screenshots",{"2":{"265":1}}],["screenshot",{"2":{"265":1}}],["screen",{"2":{"248":1}}],["script>",{"2":{"181":4}}],["script",{"2":{"181":4,"211":1,"244":2}}],["scripts",{"2":{"174":1,"226":1}}],["scripting",{"2":{"5":2,"211":1,"233":1}}],["scratch",{"2":{"28":1}}],["split",{"2":{"135":1,"248":1}}],["sped",{"2":{"253":1}}],["speed",{"2":{"105":1,"238":1,"253":2}}],["spend",{"2":{"94":1,"160":1}}],["specialists",{"2":{"249":1}}],["specialised",{"2":{"219":1}}],["special",{"0":{"40":1,"646":1,"647":1,"648":1,"649":1,"650":1,"661":1},"1":{"41":1,"42":1,"43":1,"44":1,"45":1,"46":1,"47":1,"48":1,"49":1,"647":1,"648":1,"649":1,"650":1},"2":{"16":1,"28":2,"36":1,"39":1,"40":4,"52":1,"56":1,"72":1,"89":1,"98":2,"127":1,"165":1,"167":1,"176":1,"178":1,"226":1,"233":1,"252":2,"253":1,"626":5,"641":1,"642":1,"648":1,"650":1,"654":1,"661":1,"682":1}}],["specifies",{"2":{"155":1,"202":1,"238":5,"740":1,"748":1}}],["specified",{"2":{"3":1,"16":1,"18":1,"41":1,"49":1,"57":1,"68":1,"71":1,"83":1,"128":1,"130":1,"131":1,"132":1,"134":1,"135":2,"143":1,"181":1,"192":1,"196":1,"200":1,"201":1,"214":1,"238":4,"633":1,"674":1,"694":1,"720":1,"741":2,"748":1,"749":1}}],["specification",{"2":{"218":1,"749":1}}],["specifically",{"2":{"25":1,"42":1,"94":1,"98":1,"185":2,"217":2,"221":1,"247":1,"248":1,"259":1,"264":1,"703":1}}],["specific",{"0":{"649":1},"2":{"18":2,"27":1,"29":2,"36":1,"40":1,"42":1,"43":2,"65":1,"97":1,"100":1,"103":1,"137":4,"141":2,"148":1,"154":1,"156":1,"166":1,"174":1,"183":1,"217":1,"218":1,"227":1,"233":1,"238":1,"247":1,"269":1,"281":1,"626":1,"631":1,"641":1,"642":1,"648":1,"649":1,"660":1,"680":1,"703":1,"706":1,"715":1,"750":1}}],["specifying",{"2":{"16":1}}],["specify",{"2":{"16":2,"24":1,"36":2,"41":1,"120":1,"121":1,"146":1,"150":1,"202":1,"221":1,"222":1,"238":1,"256":1}}],["spin",{"2":{"91":1}}],["sparingly",{"2":{"700":1}}],["space",{"2":{"90":1,"97":1,"100":1,"106":2,"660":1}}],["spades",{"2":{"24":1}}],["spoke",{"2":{"40":1}}],["saw",{"2":{"282":1}}],["sake",{"2":{"264":1}}],["safari",{"2":{"249":1}}],["safely",{"2":{"658":1}}],["safe",{"2":{"254":1,"258":1,"272":1,"649":1}}],["safeguards",{"2":{"258":1}}],["safeguard",{"2":{"237":1,"258":1,"259":1}}],["safety",{"2":{"97":1,"158":1,"167":1,"268":1}}],["sadness",{"2":{"224":1}}],["sans",{"2":{"181":1}}],["sanity",{"2":{"21":1,"279":1}}],["saving",{"2":{"154":1}}],["saved",{"2":{"154":1,"256":1,"258":1}}],["save",{"2":{"16":1,"249":1,"265":1}}],["saying",{"2":{"116":1,"128":1}}],["say",{"2":{"88":1,"99":1,"137":2,"224":1,"280":1}}],["said",{"2":{"40":1,"56":1,"81":1,"96":1,"128":1,"137":1,"139":1,"218":1,"252":1,"256":1,"282":1,"651":1,"656":1,"672":1}}],["samples",{"0":{"193":1}}],["sample",{"0":{"164":1},"2":{"12":1,"13":1,"125":3,"164":1,"175":1}}],["same",{"2":{"6":1,"16":1,"17":1,"20":1,"21":1,"24":2,"28":3,"56":1,"62":1,"72":1,"80":1,"84":1,"94":2,"104":1,"116":1,"119":1,"126":1,"128":1,"131":1,"135":2,"139":1,"174":1,"177":1,"210":1,"238":2,"239":1,"249":1,"256":1,"628":1,"630":2,"631":1,"632":1,"672":1,"683":1,"714":1,"717":1,"749":1}}],["shrine",{"2":{"714":1}}],["shut",{"2":{"709":1}}],["shh",{"2":{"266":1}}],["shinto",{"2":{"714":1}}],["shielding",{"2":{"248":1}}],["ships",{"2":{"248":1}}],["shipped",{"2":{"172":1,"237":1,"246":1}}],["shift",{"2":{"20":1}}],["she",{"2":{"92":1}}],["shell",{"0":{"244":1},"2":{"16":2,"143":1,"174":1,"244":6,"262":1,"263":2,"282":2,"283":1}}],["shapes",{"2":{"740":1}}],["sharing",{"2":{"259":1,"261":1,"659":1}}],["shared",{"2":{"658":1}}],["share",{"2":{"92":1,"254":1,"256":1,"259":1}}],["shacham",{"2":{"238":2}}],["sha=",{"2":{"196":1}}],["shallowref",{"2":{"181":2}}],["shallowreactive",{"2":{"181":2}}],["shall",{"2":{"16":1,"46":1,"81":1,"85":1,"90":1,"110":1,"127":1,"185":3,"187":1,"192":1,"217":2,"219":2,"224":3,"226":1,"237":1,"655":1}}],["shortened",{"2":{"590":1,"592":1}}],["shorthand",{"2":{"219":1}}],["short",{"2":{"185":1,"192":1,"224":1}}],["shortcut",{"2":{"20":1}}],["show",{"2":{"78":1,"265":2,"279":1,"658":1}}],["shown",{"2":{"65":1}}],["showcases",{"2":{"53":1}}],["shows",{"2":{"29":1,"88":1,"91":1,"181":1}}],["shouldclosenetwork",{"2":{"186":1}}],["shouldn",{"2":{"106":1,"656":1}}],["should",{"2":{"14":2,"16":1,"18":2,"20":2,"21":4,"42":1,"45":1,"59":1,"62":1,"72":1,"84":1,"88":1,"97":1,"103":1,"104":1,"106":1,"110":1,"115":1,"116":3,"119":1,"125":1,"126":2,"127":1,"128":3,"130":1,"135":2,"136":2,"137":2,"141":1,"145":1,"146":1,"149":1,"159":1,"162":1,"176":1,"177":2,"178":1,"181":1,"185":1,"190":1,"192":1,"200":1,"210":2,"211":1,"213":2,"215":1,"220":2,"224":1,"226":1,"229":1,"242":1,"247":1,"250":1,"252":1,"272":1,"280":3,"286":1,"656":1,"683":1,"700":1}}],["suits",{"2":{"268":1}}],["suitable",{"2":{"14":1,"141":2,"226":1,"238":1}}],["suspicious",{"2":{"259":1,"260":1}}],["suspend",{"2":{"187":2,"188":2,"189":3,"190":2,"191":1}}],["susceptible",{"2":{"249":1}}],["surpasses",{"2":{"268":1}}],["surpassing",{"2":{"253":1}}],["survive",{"2":{"230":1}}],["sure",{"2":{"16":1,"20":1,"21":1,"22":2,"104":1,"135":1,"178":1,"187":1,"200":1,"214":2,"247":1,"249":1,"271":1,"272":1,"279":1,"282":1,"283":1}}],["sugar",{"2":{"219":1}}],["suggestion",{"2":{"270":1}}],["suggestions",{"2":{"260":1}}],["suggested",{"2":{"137":1}}],["suggests",{"2":{"19":1,"106":1}}],["suggest",{"2":{"16":1,"167":1,"177":1,"213":1,"219":1,"220":1}}],["sufficient",{"2":{"174":1,"226":1,"247":1}}],["suffice",{"2":{"99":1}}],["supplied",{"2":{"241":1}}],["supplementary",{"2":{"226":1}}],["supporting",{"2":{"241":2,"246":1}}],["support",{"0":{"270":1},"2":{"217":2,"233":1,"273":1,"725":1}}],["supports",{"2":{"82":1,"89":1,"192":1,"233":1,"725":1}}],["supported",{"0":{"64":1,"98":1,"99":1},"2":{"62":1,"99":1,"283":1,"661":1}}],["supposed",{"2":{"88":4,"137":1,"253":1}}],["suppose",{"2":{"22":1,"88":1,"137":1,"256":1}}],["super",{"2":{"128":1,"178":1}}],["success",{"2":{"224":1,"588":1,"589":1,"741":2}}],["successful",{"2":{"202":1,"245":1,"726":1,"741":1}}],["successfully",{"2":{"196":4,"201":1,"202":1,"728":2}}],["succeeds",{"2":{"62":3}}],["such",{"2":{"8":1,"14":1,"36":1,"42":1,"45":1,"50":1,"62":1,"67":1,"72":1,"84":1,"86":1,"101":1,"107":1,"125":1,"126":1,"129":1,"137":2,"141":1,"151":1,"161":1,"165":2,"167":1,"174":2,"189":1,"212":1,"221":2,"236":1,"247":1,"248":1,"249":1,"250":2,"252":3,"253":1,"254":1,"259":1,"272":1,"286":1,"287":1,"627":1,"630":1,"658":1,"683":1,"714":1}}],["sum",{"2":{"694":1,"735":1}}],["summarised",{"2":{"97":1}}],["summarise",{"2":{"42":1}}],["summary",{"0":{"41":1},"2":{"40":1,"238":1}}],["sumeragi",{"0":{"127":1,"636":1},"2":{"18":4,"127":3,"143":1,"146":2,"196":15,"230":2,"626":1}}],["subnet",{"2":{"717":1}}],["subject",{"2":{"663":5,"664":2}}],["subtle",{"2":{"273":1}}],["subtopic",{"2":{"243":1}}],["subtract",{"2":{"178":1}}],["subcommand",{"2":{"200":9}}],["submission",{"2":{"151":2,"219":1}}],["submitgenesis",{"2":{"186":1}}],["submitexecutable",{"2":{"175":1,"176":1,"181":1}}],["submitting",{"2":{"162":1,"188":1,"192":1,"224":1,"733":1}}],["submitted",{"2":{"32":1,"39":1,"97":1,"141":1,"151":1,"177":1,"192":2,"212":1,"215":1,"219":1,"220":1,"707":1,"717":1,"728":1}}],["submits",{"2":{"126":1,"174":1,"221":1}}],["submit",{"0":{"162":1},"2":{"18":1,"20":3,"21":3,"22":1,"36":1,"53":4,"67":1,"72":1,"104":1,"128":1,"162":1,"175":2,"176":1,"212":1,"213":2,"214":1,"219":8,"221":7,"222":2,"223":2,"273":1,"664":2}}],["sub",{"0":{"750":1},"1":{"752":1,"753":1},"2":{"65":1,"87":1,"750":1}}],["subset",{"2":{"723":2,"725":1}}],["subsequent",{"2":{"28":1,"287":1}}],["substrate",{"2":{"231":1,"714":2}}],["subscription",{"2":{"183":2}}],["subscribing",{"0":{"183":1}}],["subscribe",{"2":{"98":1}}],["subscriber",{"2":{"65":1}}],["subvolume",{"2":{"8":1}}],["sudo",{"2":{"17":1,"170":1,"234":1,"242":1}}],["skip",{"2":{"6":1,"62":1}}],["style>",{"2":{"181":1}}],["style",{"2":{"117":1,"181":1,"219":1}}],["steal",{"2":{"248":1}}],["stem",{"2":{"107":1}}],["steps",{"2":{"16":1,"110":1,"159":1,"169":1,"174":3,"250":2,"263":1,"265":2}}],["step",{"2":{"6":3,"97":1,"107":1,"166":2,"175":1,"217":3,"247":1,"250":2,"283":1}}],["stdout",{"2":{"154":1}}],["std",{"0":{"107":1},"2":{"104":4,"107":2,"108":2}}],["still",{"2":{"97":1,"101":1,"241":1,"666":1,"725":1}}],["stopping",{"2":{"256":1}}],["stopped",{"2":{"62":2}}],["stoplistening",{"2":{"181":3}}],["stop",{"2":{"89":1,"98":1,"181":2,"230":1}}],["stops",{"2":{"63":1}}],["story",{"2":{"287":3}}],["stories",{"2":{"287":2}}],["storing",{"0":{"261":1,"262":1,"267":1},"1":{"262":1,"263":2,"264":2,"265":2,"266":2,"267":1,"268":2,"269":2},"2":{"25":1,"46":1,"137":1,"246":1,"262":1,"267":1,"268":2,"638":1}}],["storage",{"2":{"52":1,"80":1,"97":1,"106":1,"137":2,"143":2,"155":2,"256":1,"264":2,"638":1,"682":1,"703":1}}],["storeassetvaluetypeexpected",{"2":{"596":1}}],["stores",{"2":{"106":2,"256":1,"264":1}}],["store",{"0":{"52":1,"137":1},"2":{"25":2,"46":1,"50":1,"52":4,"57":1,"97":1,"105":1,"137":8,"143":2,"155":1,"167":1,"189":1,"193":2,"218":1,"248":1,"249":1,"252":1,"253":2,"256":1,"264":1,"265":1,"315":1,"316":1,"317":1,"684":1,"694":1}}],["stored",{"2":{"6":1,"7":1,"51":1,"71":1,"106":2,"128":1,"155":1,"249":1,"250":1,"258":1,"263":1,"264":1,"266":3,"268":1,"627":1,"684":1}}],["stuff",{"2":{"36":1}}],["strucuname",{"2":{"659":1}}],["structname",{"2":{"659":9}}],["structs",{"2":{"658":1}}],["struct",{"2":{"289":1,"291":1,"293":1,"295":1,"296":1,"297":1,"302":1,"303":1,"304":1,"306":1,"308":1,"309":1,"310":1,"312":1,"314":1,"318":1,"320":1,"321":1,"322":1,"323":1,"325":1,"329":1,"330":1,"331":1,"337":1,"342":1,"344":1,"346":1,"347":1,"354":1,"355":1,"356":1,"358":1,"360":1,"362":1,"363":1,"364":1,"365":1,"366":1,"367":1,"380":1,"381":1,"382":1,"383":1,"384":1,"385":1,"386":1,"387":1,"388":1,"389":1,"390":1,"391":1,"392":1,"395":1,"396":1,"397":1,"398":1,"399":1,"400":1,"401":1,"402":1,"403":1,"404":1,"406":1,"407":1,"408":1,"419":1,"426":1,"428":1,"429":1,"433":1,"434":1,"435":1,"436":1,"437":1,"440":1,"441":1,"442":1,"443":1,"447":1,"449":1,"450":1,"451":1,"452":1,"453":1,"457":1,"458":1,"483":1,"484":1,"486":1,"488":1,"490":1,"491":1,"492":1,"493":1,"496":1,"501":1,"502":1,"503":1,"504":1,"505":1,"506":1,"507":1,"508":1,"510":1,"511":1,"512":1,"513":1,"514":1,"517":1,"518":1,"519":1,"520":1,"522":1,"524":1,"526":1,"527":1,"528":1,"529":1,"530":1,"532":1,"533":1,"534":1,"535":1,"536":1,"538":1,"539":1,"544":1,"545":1,"547":1,"549":1,"551":1,"552":1,"554":1,"555":1,"556":1,"568":1,"570":1,"571":1,"572":1,"573":1,"574":1,"575":1,"576":1,"579":1,"580":1,"581":1,"582":1,"583":1,"585":1,"586":1,"587":1,"591":1,"593":1,"594":1,"597":1,"598":1,"599":1,"600":1,"601":1,"602":1,"603":1,"605":1,"618":1,"657":1,"659":5,"749":1,"750":1}}],["structured",{"2":{"154":1,"231":1,"250":1}}],["structures",{"2":{"42":1,"50":1,"176":2,"213":1,"229":1,"746":1}}],["structure",{"0":{"26":1},"2":{"29":1,"94":1,"177":1,"181":1,"218":1,"640":1,"664":1,"665":1,"666":1,"749":2}}],["street",{"2":{"631":1}}],["strengthen",{"2":{"258":1}}],["strength",{"0":{"252":1},"2":{"252":2}}],["streamline",{"2":{"263":1}}],["streaming",{"2":{"183":2,"200":2,"720":1}}],["stream",{"0":{"183":1,"718":1},"1":{"719":1,"720":1},"2":{"175":1,"183":5,"714":1,"718":1,"719":1,"720":1}}],["strategy",{"2":{"250":1}}],["strategies",{"2":{"110":1,"247":2}}],["straightforward",{"2":{"93":1}}],["strikes",{"2":{"234":1}}],["strict",{"2":{"143":1}}],["strip",{"2":{"105":1}}],["stringpredicate",{"0":{"567":1},"2":{"500":2}}],["string>",{"2":{"187":1}}],["stringified",{"2":{"175":1}}],["strings",{"2":{"50":1,"137":1,"238":1}}],["string",{"0":{"475":1,"566":1},"2":{"36":1,"53":1,"65":1,"74":1,"128":3,"134":1,"137":2,"164":3,"176":2,"181":4,"186":3,"187":1,"188":2,"189":2,"190":4,"191":1,"193":11,"218":1,"220":1,"221":1,"238":6,"273":6,"333":1,"362":1,"404":1,"417":1,"418":3,"419":1,"421":1,"422":1,"425":1,"429":1,"430":1,"439":2,"448":1,"475":1,"492":1,"498":2,"554":1,"566":1,"567":4,"573":1,"588":1,"606":1,"618":1,"717":1,"741":3}}],["strongly",{"2":{"178":1,"212":1,"219":1,"221":1,"231":1}}],["strong",{"2":{"97":1,"103":1,"246":1,"248":1,"252":3,"259":1}}],["str",{"2":{"52":1,"53":4,"60":1,"66":1,"218":1,"221":1,"273":2,"664":3}}],["stack",{"2":{"660":1}}],["stackexchange",{"2":{"268":1}}],["stage",{"2":{"285":1,"628":1}}],["staggering",{"2":{"252":1}}],["staff",{"2":{"260":1}}],["stability",{"2":{"247":1}}],["stable",{"2":{"2":1,"5":3,"103":1,"173":1,"279":1,"280":2,"281":2,"282":3,"656":1}}],["stale",{"2":{"181":4}}],["stay",{"2":{"126":1,"127":1,"248":1}}],["stamp",{"2":{"88":1,"255":1}}],["standalone",{"2":{"241":1}}],["standards",{"2":{"260":1}}],["standard",{"2":{"57":1,"100":1,"107":1,"108":1,"110":1,"231":1,"238":1,"241":2,"247":1,"282":1,"656":1}}],["stands",{"2":{"38":1,"94":1}}],["startlistening",{"2":{"181":2}}],["startswith",{"2":{"567":1}}],["starts",{"2":{"28":1,"88":1,"183":1,"197":2,"720":1}}],["starting",{"2":{"22":1,"67":2,"125":1,"137":1,"166":1,"183":1,"226":1,"238":1,"720":1}}],["started",{"0":{"166":1},"2":{"18":2,"88":2,"103":1,"146":1,"172":1,"191":1,"196":1,"225":1,"272":1,"740":1}}],["start",{"2":{"18":2,"28":1,"40":1,"53":1,"72":1,"88":1,"91":1,"135":1,"138":1,"146":1,"162":1,"166":1,"196":1,"217":1,"224":1,"229":1,"528":1,"529":1,"530":1,"740":1}}],["startup",{"2":{"16":2}}],["statuschecker",{"2":{"181":5}}],["status",{"0":{"747":1},"1":{"748":1,"749":1,"750":1},"2":{"20":1,"21":1,"32":2,"113":1,"120":1,"122":2,"150":1,"164":1,"172":1,"174":1,"176":1,"181":12,"207":4,"215":1,"287":2,"321":1,"322":1,"571":1,"572":1,"728":4,"733":2,"747":1,"749":4,"750":4}}],["stateless",{"2":{"175":1}}],["statement",{"2":{"137":1}}],["statements",{"2":{"100":1}}],["state",{"0":{"7":1,"112":1,"653":1},"2":{"6":1,"28":5,"34":1,"39":2,"40":1,"65":2,"72":1,"98":1,"112":2,"181":4,"196":7,"218":2,"224":1,"226":1,"228":1,"233":3,"272":1,"626":1,"640":1,"649":1,"651":1,"653":1,"700":1,"706":1,"709":1}}],["statically",{"2":{"101":1,"107":1,"217":1,"231":1,"241":2}}],["static",{"0":{"234":1},"2":{"6":2,"103":1,"175":1,"193":1,"219":1,"231":1}}],["semantics",{"2":{"658":1}}],["semi",{"2":{"672":1}}],["semiinterval",{"0":{"529":1,"530":1},"2":{"500":1,"531":1}}],["semirange",{"0":{"531":1},"2":{"500":1}}],["seamless",{"2":{"287":1}}],["searches",{"2":{"200":1,"666":2,"686":1,"688":1,"690":1}}],["selected",{"2":{"654":1}}],["select",{"2":{"265":10}}],["self",{"2":{"116":1,"657":2,"659":4}}],["sextillion",{"2":{"252":1}}],["session",{"2":{"244":1,"263":2}}],["severely",{"2":{"211":1}}],["several",{"2":{"5":1,"62":1,"88":1,"97":1,"128":1,"137":1,"200":1,"207":1,"628":1}}],["serde",{"2":{"217":1,"231":1}}],["serialized",{"2":{"723":1,"725":1,"749":1}}],["serialise",{"2":{"211":1,"218":1}}],["serialisation",{"2":{"103":2,"174":1,"231":1}}],["series",{"2":{"269":1}}],["seriously",{"2":{"247":1,"248":1}}],["serif",{"2":{"181":1}}],["service",{"2":{"137":1,"229":1,"266":1,"287":1}}],["services",{"2":{"18":1,"137":1,"249":2}}],["serve",{"2":{"160":1}}],["serves",{"2":{"125":1,"137":1,"187":1,"238":1,"255":2,"263":1}}],["servers",{"2":{"260":1}}],["server",{"2":{"117":1,"183":1,"703":1,"719":1,"720":1,"729":1,"730":1}}],["secret",{"2":{"256":1}}],["secp256k1",{"2":{"238":2,"239":2,"298":1}}],["secs",{"2":{"181":1,"749":2,"750":3}}],["sec",{"2":{"181":1}}],["seconds",{"2":{"193":14,"253":1}}],["second",{"2":{"175":2,"177":1,"213":1,"220":1,"248":1,"259":1,"272":1}}],["secondly",{"2":{"106":1,"154":1}}],["securing",{"2":{"246":3,"248":1}}],["security",{"0":{"245":1,"247":1,"251":1,"257":1,"258":1,"259":1,"260":1},"1":{"246":1,"248":1,"249":1,"250":1,"252":1,"253":1,"258":1,"259":1,"260":1},"2":{"42":1,"128":1,"132":1,"158":1,"163":1,"167":3,"186":1,"187":1,"230":1,"234":3,"237":1,"238":3,"245":3,"246":4,"247":9,"248":1,"249":13,"250":9,"251":2,"253":1,"259":1,"260":23,"261":1,"262":1,"264":2,"267":2,"268":4}}],["secure",{"2":{"202":1,"238":2,"246":1,"247":1,"248":2,"249":5,"250":1,"253":1,"254":4,"256":2,"257":1,"258":4,"262":1,"263":6,"649":1,"682":1}}],["securely",{"2":{"167":1,"252":1,"253":1,"268":1}}],["sections",{"2":{"29":1,"110":1,"167":1,"185":1}}],["section",{"2":{"18":1,"80":1,"98":1,"124":1,"135":1,"139":1,"141":1,"143":1,"149":1,"150":1,"167":1,"177":1,"187":1,"200":1,"201":1,"203":1,"208":2,"211":1,"218":1,"220":1,"237":1,"246":1,"247":1,"262":1,"264":1,"265":2,"271":1,"274":1,"277":1,"284":1,"285":1,"658":1,"662":1,"665":1,"666":2,"667":1}}],["sequences",{"2":{"137":1}}],["sequence",{"2":{"39":1,"40":1,"41":1,"49":2,"71":1,"100":1,"104":1,"647":1,"661":1}}],["sensitive",{"2":{"116":1,"128":1,"245":2,"247":2,"248":2,"249":3,"255":1,"258":2,"260":2,"261":1,"264":1}}],["sense",{"2":{"28":1,"88":1,"126":1,"154":1,"160":1,"175":1,"273":1,"672":1}}],["sentences",{"2":{"253":1}}],["sent",{"2":{"65":1}}],["sends",{"2":{"263":2,"730":1}}],["sender",{"2":{"255":3,"259":2}}],["sendtransactionasync",{"2":{"193":9}}],["sendtransaction",{"2":{"187":6,"188":3,"189":6,"190":5,"191":3}}],["sendqueryasync",{"2":{"193":5}}],["sendquery",{"2":{"187":1,"188":1,"189":1,"190":1}}],["sending",{"2":{"183":1,"218":1,"247":1,"256":1,"714":1,"720":1}}],["send",{"2":{"12":1,"28":1,"175":2,"183":1,"255":1,"705":1,"720":1,"730":1}}],["sets",{"2":{"138":3,"232":1,"633":1}}],["setparameter",{"0":{"47":1,"538":1},"2":{"40":1,"41":1,"47":1,"416":2,"420":1,"661":1}}],["setkeyvalueinstructioncommitted",{"2":{"193":1}}],["setkeyvaluebox",{"0":{"537":1},"2":{"52":1,"53":1,"416":1}}],["setkeyvalue",{"0":{"46":1,"532":1,"533":1,"534":1,"535":1,"536":1},"2":{"40":1,"41":1,"52":2,"193":2,"416":1,"420":1,"537":5,"661":1}}],["settings",{"2":{"137":1,"265":2}}],["setting",{"0":{"133":1},"1":{"134":1,"135":1},"2":{"16":1,"52":1,"141":1,"158":1,"160":1,"174":1,"196":1,"198":1,"203":1,"214":1,"219":1,"258":1}}],["setupeventsreturn>",{"2":{"181":1}}],["setupeventsreturn",{"2":{"181":1}}],["setups",{"2":{"154":1,"170":1}}],["setup",{"0":{"15":1,"16":1,"17":1,"185":1,"210":1,"217":1,"272":1},"1":{"16":1,"17":1},"2":{"13":1,"154":1,"166":1,"181":5,"196":1,"253":2,"263":1,"268":1,"283":1}}],["set",{"0":{"161":1,"199":1},"2":{"12":1,"18":1,"28":2,"36":1,"40":1,"42":1,"52":1,"53":2,"55":1,"56":2,"57":1,"59":1,"84":1,"88":1,"97":1,"113":1,"118":1,"120":1,"123":1,"125":1,"135":1,"139":1,"141":2,"146":1,"150":1,"154":1,"161":1,"164":1,"170":1,"174":2,"175":1,"178":1,"199":1,"200":1,"207":1,"214":1,"217":1,"227":1,"230":1,"249":1,"250":1,"252":5,"253":3,"259":3,"260":2,"264":1,"281":3,"291":1,"306":1,"312":1,"337":1,"344":1,"360":1,"488":1,"524":1,"591":1,"641":1,"647":1,"659":2,"661":1,"663":2,"675":1,"707":1,"748":1}}],["setcrypto",{"2":{"5":2,"174":2,"181":2}}],["seek",{"2":{"267":1}}],["sees",{"2":{"256":1}}],["seed",{"2":{"238":7,"239":1}}],["seems",{"2":{"103":1}}],["seen",{"2":{"40":1,"94":1,"252":1}}],["see",{"2":{"11":1,"12":1,"18":1,"88":2,"91":1,"99":1,"104":1,"115":1,"128":1,"132":1,"134":1,"137":1,"145":1,"151":1,"164":2,"168":3,"176":1,"181":1,"186":1,"187":2,"188":2,"189":1,"190":1,"191":1,"192":1,"196":1,"202":1,"204":1,"212":1,"252":1,"261":1,"263":3,"264":1,"265":2,"268":1,"270":1,"272":2,"640":1,"659":1,"714":2,"735":1,"749":1}}],["separately",{"2":{"46":1}}],["separate",{"2":{"10":1,"102":1,"160":1,"210":1,"221":1,"238":1,"249":2,"658":1,"684":1}}],["soars",{"2":{"253":1}}],["social",{"2":{"253":1,"259":1,"261":1}}],["socketaddrhost",{"0":{"554":1},"2":{"553":1}}],["socketaddrv6",{"0":{"556":1},"2":{"553":1}}],["socketaddrv4",{"0":{"555":1},"2":{"553":1}}],["socketaddr",{"0":{"553":1},"2":{"490":1}}],["socket",{"2":{"10":1,"18":1,"22":1,"161":1,"175":2,"181":1}}],["solve",{"2":{"656":1}}],["solution",{"2":{"280":1,"282":1}}],["solutions",{"2":{"236":1}}],["solo",{"2":{"250":1}}],["solokeys",{"2":{"250":1}}],["solid",{"2":{"249":1}}],["solidity",{"2":{"101":1}}],["soup",{"2":{"146":1}}],["sourced",{"2":{"287":1}}],["sources",{"0":{"2":1},"2":{"0":1,"2":3,"3":1,"5":4,"174":1,"181":1,"193":6,"249":1}}],["source",{"0":{"242":1},"2":{"0":1,"2":1,"4":1,"99":1,"128":1,"141":1,"164":1,"179":1,"181":1,"241":1,"244":2,"248":2,"249":4,"271":1,"580":1,"581":1,"582":1,"583":1,"650":1,"666":1}}],["sooner",{"2":{"88":1,"247":1}}],["sorts",{"2":{"160":1,"273":1}}],["sort",{"2":{"69":3}}],["sorting",{"0":{"69":1},"2":{"65":1,"69":3}}],["sortedvec",{"0":{"562":1,"563":1,"564":1,"565":1},"2":{"289":1,"449":1,"522":1,"544":1,"545":1}}],["sortedmap",{"0":{"557":1,"558":1,"559":1,"560":1,"561":1},"2":{"289":1,"342":3,"432":1,"575":1}}],["sorted",{"2":{"65":1,"69":1,"665":1}}],["soramitsu",{"2":{"6":1,"185":1,"186":8,"187":12,"192":4,"193":20}}],["sophisticated",{"2":{"36":1}}],["somewhere",{"2":{"217":1,"258":1}}],["somewhat",{"2":{"95":1,"120":1,"150":1}}],["sometimes",{"2":{"65":1,"278":1}}],["something",{"2":{"41":1,"56":1,"72":1,"100":1,"103":1,"137":2,"153":1,"175":1,"214":1,"219":1,"258":1,"285":1,"286":1}}],["someone",{"2":{"28":1,"137":1,"230":1,"261":1}}],["some",{"2":{"16":2,"18":1,"28":3,"36":2,"41":1,"42":1,"43":1,"57":2,"65":1,"67":3,"93":1,"94":2,"97":2,"104":1,"106":1,"110":1,"137":3,"138":1,"143":2,"148":1,"155":1,"175":1,"177":1,"181":3,"185":1,"190":1,"192":1,"193":3,"200":1,"205":1,"215":1,"221":1,"235":1,"241":1,"249":1,"256":1,"273":1,"459":1,"460":1,"461":1,"462":1,"463":1,"464":1,"465":1,"466":1,"467":1,"468":1,"469":1,"470":1,"471":1,"472":1,"473":1,"474":1,"475":1,"476":1,"477":1,"478":1,"479":1,"480":1,"481":1,"482":1,"642":1,"648":1,"656":1,"728":2}}],["software",{"2":{"14":3,"39":1,"157":1,"230":1,"248":5,"253":1,"259":1,"260":2,"643":2}}],["so",{"2":{"5":1,"14":1,"17":1,"18":2,"39":2,"40":1,"41":1,"43":1,"46":1,"55":1,"56":1,"62":2,"79":1,"82":1,"88":3,"90":2,"94":3,"97":3,"103":1,"105":2,"106":1,"135":1,"137":3,"141":1,"146":1,"163":1,"174":2,"175":2,"176":2,"186":1,"200":1,"203":1,"214":1,"215":1,"217":3,"221":2,"226":1,"234":1,"241":1,"243":1,"252":1,"253":2,"256":1,"263":2,"268":1,"270":1,"273":1,"283":1,"656":1,"684":1}}],["sigkill",{"2":{"266":2}}],["signal",{"2":{"266":1}}],["signatory",{"2":{"220":1}}],["signatories=",{"2":{"213":1}}],["signatories",{"2":{"128":3,"164":3,"177":1,"188":2,"289":1,"449":1}}],["signatureof",{"0":{"541":1,"542":1,"543":1,"564":1,"565":1},"2":{"544":1,"545":1,"549":1,"564":1,"565":1}}],["signaturecheckcondition",{"0":{"442":1,"540":1},"2":{"289":1,"294":2,"442":1}}],["signature",{"0":{"539":1},"2":{"41":1,"128":1,"137":1,"165":1,"238":2,"255":2,"256":1,"259":2,"289":1,"498":1,"541":1,"542":1,"543":1,"549":1,"663":1,"741":3}}],["signaturesof",{"0":{"544":1,"545":1},"2":{"547":1,"551":1}}],["signatures",{"0":{"255":1},"2":{"12":4,"175":1,"238":3,"246":1,"248":1,"249":1,"259":2,"544":1,"545":1,"547":1,"551":1}}],["signing",{"2":{"256":1}}],["signifies",{"2":{"125":1}}],["significant",{"2":{"25":1,"137":1}}],["significantly",{"2":{"14":1,"97":1,"104":1,"106":1,"109":1,"248":1,"252":1}}],["signer",{"2":{"175":12,"181":4}}],["signedqueryv1",{"0":{"549":1},"2":{"548":1}}],["signedquery",{"0":{"548":1},"2":{"740":1}}],["signedtransactionv1",{"0":{"551":1},"2":{"550":1}}],["signedtransaction",{"0":{"411":1,"413":1,"431":1,"465":1,"467":1,"550":1},"2":{"323":1,"393":1,"399":1,"431":1,"465":1,"467":1,"571":1,"572":1,"579":1,"738":1,"752":1}}],["signedblockv1",{"0":{"547":1},"2":{"546":1}}],["signedblock",{"0":{"412":1,"466":1,"546":1},"2":{"321":1,"323":1,"324":1,"390":1,"393":1,"466":1,"499":1,"576":1}}],["signed",{"2":{"24":2,"25":1,"128":2,"249":1,"256":1,"753":2}}],["sign",{"2":{"53":1,"61":1,"71":1,"175":3,"249":1,"259":2}}],["signs",{"2":{"18":1}}],["six",{"2":{"249":1}}],["sieves",{"2":{"192":1,"224":1}}],["silence",{"2":{"153":1}}],["sip",{"2":{"97":1}}],["site",{"2":{"249":1}}],["sit",{"2":{"91":1}}],["situation",{"2":{"88":2}}],["sided",{"2":{"163":1}}],["side",{"0":{"256":1},"2":{"65":1,"175":1,"215":1,"273":1,"665":1}}],["sizeerror",{"0":{"552":1},"2":{"438":2}}],["sizes",{"2":{"161":1,"655":1}}],["size",{"0":{"105":1,"109":1},"1":{"106":1,"107":1,"108":1,"109":1,"110":1},"2":{"39":1,"103":1,"105":5,"106":1,"107":2,"109":2,"110":4,"121":2,"137":1,"143":2,"180":3,"252":1,"268":1,"368":1,"369":1,"370":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"378":1,"379":1,"394":1,"574":1,"741":1,"749":2,"750":1}}],["singular",{"2":{"741":1}}],["single",{"2":{"18":1,"38":1,"45":1,"74":1,"92":1,"93":1,"94":1,"96":1,"124":1,"125":2,"126":2,"137":1,"143":2,"176":1,"188":2,"197":2,"220":1,"221":1,"241":1,"253":2,"628":1,"666":1}}],["since",{"2":{"5":1,"21":1,"57":1,"82":1,"88":1,"101":1,"103":1,"106":1,"116":1,"128":2,"137":1,"146":1,"175":1,"176":1,"178":1,"201":1,"214":1,"238":1,"247":1,"248":1,"256":1,"268":2,"272":1,"273":1,"282":1,"570":1,"719":1,"729":1,"735":3,"749":2}}],["simultaneously",{"2":{"123":1}}],["similarity",{"2":{"137":1}}],["similarly",{"2":{"59":1,"63":1}}],["similar",{"2":{"12":1,"20":1,"21":1,"44":1,"176":1,"190":1,"191":1,"196":1,"202":1,"206":1,"213":1,"217":1,"223":1,"278":1}}],["simplify",{"2":{"161":1}}],["simplicity",{"2":{"16":1}}],["simply",{"2":{"9":1,"185":1,"253":1,"268":1,"272":1}}],["simplest",{"2":{"282":1}}],["simpler",{"2":{"214":1}}],["simple",{"0":{"102":1},"1":{"103":1,"104":1},"2":{"5":1,"28":1,"62":2,"74":1,"79":1,"88":1,"100":1,"101":1,"137":1,"174":1,"175":1,"187":1,"211":1,"233":1,"656":1,"682":1}}],["sdks",{"2":{"134":1,"166":1,"185":1,"287":3}}],["sdk",{"2":{"5":3,"186":1,"189":1,"208":1,"287":3,"666":1}}],["s",{"0":{"208":1},"2":{"2":1,"5":1,"14":1,"25":1,"28":2,"29":3,"37":1,"39":2,"40":1,"42":1,"50":2,"52":2,"53":3,"60":2,"65":2,"66":1,"72":1,"88":2,"89":1,"91":1,"97":1,"104":1,"105":2,"113":1,"115":1,"128":2,"134":1,"135":1,"136":1,"137":7,"141":2,"143":3,"145":2,"146":2,"148":1,"150":2,"152":1,"154":1,"159":1,"160":1,"161":1,"163":1,"174":1,"175":4,"176":3,"181":1,"185":1,"190":2,"191":1,"200":1,"210":1,"212":1,"214":1,"215":1,"217":3,"218":3,"219":3,"224":2,"238":2,"239":2,"243":1,"244":2,"249":2,"250":1,"251":1,"253":9,"254":1,"255":2,"256":3,"259":2,"260":2,"262":1,"268":2,"270":1,"272":2,"280":2,"282":3,"283":1,"286":1,"631":2,"640":1,"644":1,"655":1,"656":3,"658":1,"663":8,"741":1,"749":2}}],["src",{"2":{"2":4,"3":1,"5":5,"104":1,"664":1}}],["f71ea9d897c4338cbf4f1dc7b492aad0bf6ce896b803d7cdb9cf25ecc15109826b0f56f58761060056355dba0e0fc489cfb2f974481ed64873082e6032796235",{"2":{"239":1}}],["fficonvert",{"2":{"658":2}}],["ffireturn",{"2":{"657":1}}],["ffitype",{"2":{"657":1,"658":4}}],["ffi",{"0":{"655":1,"656":1,"658":1},"1":{"656":1,"657":1,"658":1,"659":2},"2":{"103":1,"656":5,"657":1,"658":11,"659":9}}],["friend",{"2":{"161":1}}],["freestanding",{"2":{"659":1}}],["freely",{"2":{"125":1,"254":1}}],["frequently",{"2":{"219":1}}],["fresh",{"2":{"135":1,"273":1}}],["framework",{"2":{"134":1,"232":1,"249":1,"714":1}}],["franca",{"2":{"103":1}}],["front",{"2":{"18":1,"79":1}}],["fromaccount",{"2":{"179":2}}],["fromjson",{"2":{"175":1,"181":1}}],["from",{"0":{"171":1},"1":{"172":1},"2":{"0":1,"3":1,"4":1,"5":4,"12":1,"16":2,"28":1,"40":1,"51":2,"52":1,"53":4,"60":1,"65":2,"66":1,"89":1,"92":4,"93":1,"97":2,"98":2,"101":1,"104":1,"105":1,"107":1,"116":1,"125":2,"126":1,"127":1,"128":1,"134":1,"135":1,"137":2,"143":1,"151":1,"154":1,"174":2,"175":15,"176":2,"177":2,"178":3,"179":1,"180":2,"181":28,"183":2,"186":1,"187":1,"190":4,"191":1,"196":1,"203":1,"207":1,"210":2,"211":2,"212":1,"213":2,"214":1,"217":1,"218":5,"220":3,"221":2,"222":7,"229":3,"230":3,"238":1,"241":1,"248":2,"249":5,"252":2,"254":1,"256":3,"258":2,"259":1,"264":1,"265":6,"266":1,"267":1,"270":1,"272":1,"273":4,"287":3,"630":1,"658":3,"659":1,"661":1,"663":4,"664":3,"684":1,"717":1,"735":1}}],["flash",{"2":{"249":1,"268":1}}],["flag",{"2":{"22":1}}],["flexibility",{"0":{"232":1},"2":{"264":1}}],["flexible",{"2":{"203":1,"232":1}}],["floating",{"2":{"214":1}}],["flow",{"2":{"137":1}}],["flowers",{"2":{"128":4,"164":4,"187":2,"188":2,"189":3,"190":3,"191":2,"200":1,"202":1,"204":1}}],["flux",{"2":{"97":1}}],["f64",{"2":{"92":4,"93":1,"221":3,"749":1}}],["fn",{"2":{"53":1,"104":1,"657":2,"659":6}}],["fujitsu",{"2":{"236":1}}],["fuzz",{"2":{"235":1}}],["fulfilled",{"2":{"181":3}}],["fully",{"2":{"165":1}}],["full",{"2":{"16":3,"40":1,"67":1,"71":1,"106":1,"143":2,"175":2,"181":1,"677":1,"680":1,"700":1,"707":1}}],["further",{"2":{"105":1,"185":1,"247":1,"252":1}}],["fun",{"2":{"187":2,"188":2,"189":3,"190":2,"191":1}}],["fundamental",{"2":{"185":1,"208":1,"217":1,"238":1}}],["fungible",{"0":{"630":1,"631":1},"2":{"24":2,"165":2,"178":2,"189":2,"214":2,"221":2,"630":1,"631":1}}],["functioning",{"2":{"156":1,"634":1}}],["functions",{"2":{"65":1,"188":1,"217":1,"255":1,"655":2,"656":2,"658":1}}],["functionality",{"2":{"176":1,"249":1,"268":1,"635":1,"645":1}}],["functional",{"2":{"19":1}}],["function",{"0":{"655":1},"1":{"656":1,"657":1,"658":1,"659":1},"2":{"18":5,"20":1,"103":1,"137":1,"153":1,"175":2,"176":4,"177":1,"181":5,"186":1,"219":1,"239":1,"634":1,"656":5,"657":1,"658":1,"659":3}}],["future",{"2":{"21":1,"63":1,"97":1,"99":1,"103":1,"143":1,"174":1,"193":12,"237":1,"272":1}}],["f",{"2":{"18":1,"146":1,"196":1}}],["famous",{"2":{"278":1}}],["family",{"2":{"181":1}}],["familiarity",{"2":{"225":1}}],["familiarise",{"2":{"217":1}}],["familiar",{"2":{"100":1,"173":1,"227":1,"229":1}}],["favour",{"2":{"249":1}}],["fabric",{"2":{"236":1}}],["fashioned",{"2":{"627":1}}],["fashion",{"2":{"178":1}}],["fast",{"2":{"42":1,"100":1,"232":1}}],["faster",{"2":{"14":2,"174":1}}],["fatal",{"2":{"171":1}}],["fallible",{"2":{"658":1}}],["fall",{"2":{"253":1}}],["fallback",{"2":{"125":2}}],["falkon",{"2":{"249":1}}],["falsify",{"2":{"230":1}}],["false",{"2":{"3":1,"113":1,"164":1,"214":1}}],["facing",{"2":{"250":1,"706":1}}],["facilities",{"2":{"154":1}}],["facilitates",{"2":{"6":1}}],["factor",{"2":{"259":2}}],["factors",{"2":{"137":1,"247":1,"660":1}}],["factory",{"2":{"137":1,"178":1}}],["fact",{"2":{"105":1,"141":1,"178":1,"210":1,"217":1}}],["fairly",{"2":{"72":1,"175":1}}],["failing",{"2":{"272":2}}],["failure",{"2":{"125":1,"135":1,"235":1,"273":1,"588":1,"589":1}}],["fails",{"2":{"57":1}}],["fail",{"0":{"362":1},"2":{"28":1,"98":1,"135":1,"193":2,"214":1,"416":2,"418":1,"420":1,"691":1}}],["failed",{"2":{"6":1,"28":1,"219":1,"221":1,"272":3,"287":1,"652":1}}],["fake",{"2":{"28":1,"259":2}}],["faulty",{"2":{"705":1}}],["fault",{"0":{"230":1,"634":1},"2":{"18":1,"146":1,"163":1,"230":3,"626":1,"654":1}}],["faults",{"2":{"18":3,"146":2,"650":1}}],["fare",{"2":{"287":1}}],["far",{"2":{"14":2,"46":1,"94":2,"161":1,"176":1,"214":1,"253":1,"268":1}}],["figure",{"2":{"261":1}}],["firewall",{"2":{"258":2}}],["firefox",{"2":{"249":1}}],["firedragon",{"2":{"249":1}}],["firstly",{"2":{"106":1,"154":1,"280":1}}],["first",{"0":{"18":1},"2":{"5":1,"14":1,"16":1,"18":1,"20":2,"21":2,"43":1,"59":1,"62":1,"63":1,"81":1,"97":1,"119":1,"126":1,"128":1,"135":1,"136":1,"141":1,"170":1,"175":1,"176":1,"177":1,"183":1,"195":1,"204":1,"210":1,"213":1,"214":1,"215":1,"217":2,"220":1,"221":1,"222":1,"223":1,"224":1,"233":1,"248":1,"265":2,"271":1,"272":5,"283":1,"285":1,"286":1,"287":1,"719":1,"729":1}}],["fish",{"2":{"244":2}}],["field",{"2":{"127":2,"289":2,"291":2,"292":2,"293":2,"295":2,"296":2,"297":2,"302":2,"303":2,"304":2,"306":2,"307":2,"308":2,"309":2,"310":2,"312":2,"313":2,"314":2,"318":2,"320":2,"321":2,"322":2,"323":2,"325":2,"329":2,"330":2,"331":2,"337":2,"338":2,"342":2,"344":2,"345":2,"346":2,"347":2,"354":2,"355":2,"356":2,"358":2,"360":2,"361":2,"362":2,"363":2,"364":2,"365":2,"366":2,"367":2,"380":2,"381":2,"382":2,"383":2,"384":2,"385":2,"386":2,"387":2,"388":2,"389":2,"390":2,"391":2,"392":2,"395":2,"396":2,"397":2,"398":2,"399":2,"400":2,"401":2,"402":2,"403":2,"404":2,"406":2,"407":2,"408":2,"419":2,"426":2,"428":2,"429":2,"433":2,"434":2,"435":2,"436":2,"437":2,"440":2,"441":2,"442":2,"443":2,"447":2,"449":2,"450":2,"451":2,"452":2,"453":2,"457":2,"458":2,"483":2,"484":2,"486":2,"488":2,"489":2,"490":2,"491":2,"492":2,"493":2,"496":2,"501":2,"502":2,"503":2,"504":2,"505":2,"506":2,"507":2,"508":2,"510":2,"511":2,"512":2,"513":2,"514":2,"517":2,"518":2,"519":2,"520":2,"522":2,"524":2,"525":2,"526":2,"527":2,"528":2,"529":2,"530":2,"532":2,"533":2,"534":2,"535":2,"536":2,"538":2,"539":2,"544":2,"545":2,"547":2,"549":2,"551":2,"552":2,"554":2,"555":2,"556":2,"568":2,"570":2,"571":2,"572":2,"573":2,"574":2,"575":2,"576":2,"579":2,"580":2,"581":2,"582":2,"583":2,"585":2,"586":2,"587":2,"591":2,"592":2,"593":2,"594":2,"597":2,"598":2,"599":2,"600":2,"601":2,"602":2,"603":2,"605":2,"618":2,"656":1,"659":9}}],["fields",{"2":{"50":1,"126":1,"127":4,"176":1,"749":2}}],["fit",{"2":{"101":1}}],["filled",{"2":{"117":1}}],["filterbox",{"2":{"181":2,"224":1}}],["filtering",{"2":{"65":1}}],["filtered",{"2":{"65":1,"665":1}}],["filteropt",{"2":{"38":2,"94":3}}],["filter",{"0":{"79":1,"94":1},"2":{"37":1,"38":4,"65":2,"68":2,"75":1,"79":1,"81":1,"85":1,"93":1,"94":15,"95":2,"97":3,"154":1,"181":1,"192":2,"207":1,"215":5,"224":4,"297":1,"501":1}}],["filters",{"0":{"37":1,"38":1,"68":1},"1":{"38":1},"2":{"33":1,"37":1,"51":1,"69":1,"79":2,"87":1,"94":1,"97":2,"192":1,"215":1,"224":2,"709":1}}],["filename",{"2":{"2":3,"5":2}}],["file",{"0":{"154":1},"2":{"2":3,"4":1,"5":4,"13":1,"16":1,"21":1,"22":3,"115":1,"125":5,"126":3,"127":1,"128":2,"130":1,"131":2,"132":2,"135":1,"143":10,"145":1,"149":1,"150":1,"151":1,"152":1,"154":4,"164":1,"171":2,"174":5,"181":1,"185":1,"187":1,"196":1,"197":2,"199":1,"200":6,"201":1,"203":3,"211":2,"218":1,"238":1,"244":1,"256":1,"265":3,"272":5,"663":2,"714":2}}],["files",{"0":{"8":1,"17":1,"21":1,"164":1},"2":{"0":1,"4":1,"6":1,"8":1,"12":1,"13":2,"16":1,"17":1,"21":1,"132":1,"135":2,"146":1,"164":1,"172":1,"174":1,"210":1,"265":1}}],["fingerprint",{"2":{"259":1}}],["financial",{"2":{"245":2,"247":1,"252":1,"627":2}}],["final",{"2":{"193":35}}],["finalization",{"2":{"127":1}}],["finally",{"2":{"18":1,"96":1,"109":1,"136":1,"137":1,"175":1,"181":1,"192":1,"210":1,"212":1,"214":1,"215":1,"224":1,"270":1}}],["finite",{"2":{"141":1}}],["finished",{"2":{"22":1,"88":1,"141":1,"196":1}}],["fine",{"2":{"28":1,"131":1,"143":1,"151":1,"175":1,"279":1}}],["findzbyxandy",{"2":{"666":2}}],["findtransactionsbyaccountid",{"0":{"400":1,"707":1},"2":{"497":2}}],["findtransactionbyhash",{"0":{"399":1,"708":1},"2":{"497":2}}],["findtriggerbyid",{"0":{"401":1,"711":1},"2":{"497":2}}],["findtriggersbydomainid",{"0":{"403":1,"713":1},"2":{"83":1,"497":2}}],["findtriggerkeyvaluebyidandkey",{"0":{"402":1,"712":1},"2":{"54":1,"497":2}}],["findtotalassetquantitybyassetdefinitionid",{"0":{"398":1,"694":1},"2":{"497":2}}],["findpermissiontokenschema",{"0":{"394":1},"2":{"497":2}}],["findpermissiontokensbyaccountid",{"0":{"395":1,"674":1},"2":{"64":1,"497":2}}],["finderror",{"0":{"393":1},"2":{"418":1,"498":1,"577":1,"741":1,"742":4,"743":6}}],["findblockheaderbyhash",{"0":{"390":1,"698":1},"2":{"497":2}}],["finding",{"2":{"211":1}}],["finddomainbyid",{"0":{"391":1,"701":1},"2":{"193":1,"497":2}}],["finddomainkeyvaluebyidandkey",{"0":{"392":1,"702":1},"2":{"54":1,"497":2}}],["finds",{"2":{"66":1,"72":1,"666":1,"673":1,"676":1,"694":2,"710":1,"711":1,"712":1,"713":1}}],["findrolesbyaccountid",{"0":{"397":1,"671":1},"2":{"64":1,"497":2}}],["findrolebyroleid",{"0":{"396":1,"670":1},"2":{"64":1,"497":2}}],["findaccountswithasset",{"0":{"367":1,"681":1},"2":{"497":2}}],["findaccountsbyname",{"0":{"366":1,"679":1},"2":{"497":2}}],["findaccountsbydomainid",{"0":{"365":1,"680":1},"2":{"497":2}}],["findaccountbyid",{"0":{"363":1,"677":1},"2":{"190":1,"193":2,"497":2}}],["findaccountkeyvaluebyidandkey",{"0":{"364":1,"678":1},"2":{"54":1,"497":2}}],["findalltransactions",{"0":{"379":1},"2":{"497":2}}],["findallpeers",{"0":{"376":1,"704":1},"2":{"497":2}}],["findallpermissiontokendefinitions",{"0":{"673":1},"2":{"64":1}}],["findallparameters",{"0":{"375":1,"705":1},"2":{"497":2}}],["findallblocks",{"0":{"373":1,"696":1},"2":{"497":2}}],["findallblockheaders",{"0":{"372":1,"697":1},"2":{"497":2}}],["findallassetdefinitions",{"0":{"684":1}}],["findallassetsdefinitions",{"0":{"371":1},"2":{"497":2}}],["findallassets",{"0":{"370":1,"683":1},"2":{"180":1,"189":3,"497":2}}],["findallactivetriggerids",{"0":{"369":1,"710":1},"2":{"497":2}}],["findallaccounts",{"0":{"368":1,"676":1},"2":{"66":2,"180":1,"188":3,"497":2}}],["findalldomains",{"0":{"374":1,"700":1},"2":{"104":2,"176":1,"180":1,"187":3,"497":2}}],["findallroleids",{"0":{"377":1,"669":1},"2":{"64":1,"497":2}}],["findallroles",{"0":{"378":1,"668":1},"2":{"64":1,"497":2,"671":1}}],["findassetsbyname",{"0":{"389":1,"686":1},"2":{"497":2}}],["findassetsbydomainidandassetdefinitionid",{"0":{"388":1,"690":1},"2":{"497":2}}],["findassetsbydomainid",{"0":{"387":1,"689":1},"2":{"497":2}}],["findassetsbyassetdefinitionid",{"0":{"386":1,"688":1},"2":{"497":2}}],["findassetsbyaccountid",{"0":{"385":1,"687":1},"2":{"66":2,"497":2}}],["findassetquantitybyid",{"0":{"384":1,"691":1},"2":{"497":2}}],["findassetdefinitionbyid",{"0":{"381":1},"2":{"497":2}}],["findassetdefinitionkeyvaluebyidandkey",{"0":{"382":1,"693":1},"2":{"54":1,"193":1,"497":2}}],["findassetbyid",{"0":{"380":1,"685":1},"2":{"497":2}}],["findassetkeyvaluebyidandkey",{"0":{"383":1,"692":1},"2":{"54":1,"193":1,"497":2}}],["find",{"2":{"10":1,"14":1,"53":1,"58":1,"66":1,"83":1,"124":1,"164":1,"167":2,"176":1,"196":1,"207":1,"268":1,"418":1,"498":1,"626":1,"741":2}}],["fixedwidth",{"2":{"621":1,"622":1,"623":1,"624":1,"625":1}}],["fixedpointconversion",{"2":{"430":1}}],["fixed",{"2":{"25":2,"50":1,"57":1,"92":6,"93":1,"178":2,"214":2,"221":2}}],["fix",{"2":{"6":1,"14":1,"171":1,"177":1,"213":1,"220":1,"244":3,"273":1,"280":1}}],["feel",{"2":{"217":1}}],["feed",{"2":{"207":1}}],["feedback",{"2":{"192":1,"260":1}}],["fees",{"2":{"89":1}}],["few",{"2":{"24":1,"57":1,"99":1,"100":2,"137":1,"177":1,"178":1,"188":1,"189":1,"214":1,"220":1,"221":1,"228":1,"231":1}}],["featured",{"2":{"165":1}}],["features=panic",{"2":{"108":1}}],["features",{"2":{"5":1,"6":2,"166":1,"167":1,"175":3,"192":1,"224":3,"228":1,"229":1,"232":1,"249":3,"268":1,"272":1}}],["feature",{"2":{"4":2,"36":1,"69":1,"97":1,"108":1,"232":1,"249":3,"667":1,"672":1,"715":1,"734":1,"744":1,"747":1}}],["fetchsizetoobig",{"2":{"498":1,"741":2}}],["fetched",{"2":{"3":1,"287":1}}],["fetching",{"0":{"3":1}}],["fetch",{"2":{"0":1,"3":1,"175":19,"181":2,"183":1,"741":1}}],["fostering",{"2":{"260":1}}],["focuses",{"2":{"262":1}}],["focused",{"2":{"249":1}}],["focus",{"2":{"192":1,"224":1}}],["font",{"2":{"181":1,"238":1}}],["footprint",{"2":{"174":1,"233":1}}],["foundation",{"2":{"168":1,"238":1,"245":1}}],["found",{"0":{"742":1,"743":1},"1":{"745":1,"746":1,"748":1,"749":1},"2":{"53":2,"176":1,"190":1,"270":1,"282":1,"728":1,"741":1,"742":1,"743":1}}],["four",{"2":{"20":1,"22":1,"135":5,"146":2,"196":1,"197":1,"202":1,"717":1}}],["folders",{"2":{"21":3,"258":1}}],["folder",{"2":{"16":1,"17":2,"21":1,"181":1,"210":3,"217":1,"243":1,"282":1,"638":1}}],["followed",{"2":{"156":1,"250":1}}],["follow",{"2":{"90":1,"227":2,"248":1,"250":1,"252":1,"286":1,"726":1}}],["follows",{"2":{"5":1,"67":1,"97":1,"263":1}}],["following",{"2":{"2":1,"12":2,"19":1,"29":1,"32":1,"33":1,"50":1,"53":1,"62":1,"63":1,"73":1,"78":1,"85":1,"96":1,"104":2,"134":1,"141":1,"143":1,"151":1,"166":2,"167":1,"168":1,"170":1,"172":2,"174":5,"178":1,"187":1,"188":1,"189":3,"191":1,"192":1,"195":1,"196":1,"197":1,"200":2,"202":2,"203":1,"211":1,"214":1,"219":1,"238":3,"241":1,"243":1,"244":6,"246":1,"247":3,"249":1,"250":1,"252":3,"253":1,"263":1,"264":1,"265":4,"268":1,"272":1,"279":1,"657":1,"660":1,"661":1,"663":1,"664":1,"665":1,"666":1,"725":1,"728":1,"748":2,"749":2,"752":1}}],["forbidmintonmintable",{"2":{"445":1}}],["forwardcursor",{"0":{"404":1},"2":{"320":1}}],["forwarding",{"2":{"263":1}}],["forgot",{"2":{"281":1}}],["forget",{"2":{"16":1}}],["fortifying",{"2":{"260":1}}],["fortify",{"2":{"250":1}}],["fortunately",{"2":{"214":1}}],["forking",{"2":{"650":1}}],["forks",{"2":{"249":1}}],["fork",{"2":{"219":1}}],["for=",{"2":{"181":2}}],["foreign",{"0":{"655":1},"1":{"656":1,"657":1,"658":1,"659":1},"2":{"103":1,"656":1}}],["forming",{"2":{"654":1}}],["formula",{"2":{"252":4}}],["forms",{"2":{"245":1}}],["former",{"2":{"192":1,"224":1,"282":1}}],["formed",{"2":{"88":1}}],["form",{"2":{"51":1,"73":1,"88":1,"181":1,"187":1,"217":1,"219":1,"749":2}}],["formats",{"2":{"273":1}}],["formation",{"2":{"87":1}}],["format",{"0":{"273":1},"2":{"2":1,"101":1,"103":3,"130":3,"134":1,"136":1,"143":1,"154":1,"188":1,"218":2,"238":2,"256":1,"273":1,"723":1,"725":1,"750":1}}],["forces",{"2":{"6":1}}],["force",{"2":{"3":1,"252":1,"253":1}}],["for",{"0":{"105":1,"132":1,"133":1,"135":1,"180":1,"259":1,"260":1},"1":{"106":1,"107":1,"108":1,"109":1,"110":1,"133":1,"134":2,"135":2,"136":1},"2":{"3":1,"5":2,"6":3,"9":1,"12":2,"13":4,"14":3,"16":4,"17":1,"18":2,"20":2,"22":1,"25":1,"28":3,"32":1,"36":1,"38":1,"39":1,"40":2,"41":4,"42":5,"45":1,"47":1,"50":1,"51":1,"52":2,"53":2,"56":2,"57":1,"62":6,"64":2,"65":2,"66":1,"67":1,"69":1,"70":1,"78":4,"80":1,"82":1,"83":2,"84":1,"86":1,"88":3,"89":1,"93":1,"94":4,"97":3,"98":2,"99":2,"100":2,"104":2,"105":2,"106":2,"110":2,"111":1,"112":1,"115":1,"117":1,"118":1,"119":2,"121":1,"122":3,"123":1,"124":1,"125":4,"126":3,"128":4,"134":2,"135":2,"136":2,"137":3,"138":1,"139":1,"140":2,"141":8,"143":8,"145":2,"146":1,"149":1,"151":4,"153":1,"154":2,"155":2,"158":2,"160":2,"161":1,"163":1,"164":3,"166":1,"168":2,"170":1,"171":1,"172":1,"174":9,"175":6,"177":1,"180":3,"181":1,"183":2,"185":2,"188":2,"189":2,"190":2,"196":1,"197":2,"200":2,"202":3,"203":1,"207":1,"210":3,"212":2,"213":2,"214":1,"215":3,"217":3,"218":1,"219":2,"220":2,"221":2,"224":4,"226":1,"231":2,"233":3,"238":10,"244":4,"245":3,"246":2,"247":2,"248":4,"249":14,"250":2,"252":3,"254":1,"256":1,"258":1,"259":4,"260":6,"261":2,"262":1,"263":5,"264":4,"265":3,"266":1,"267":1,"268":2,"270":2,"271":1,"272":5,"273":2,"274":1,"277":1,"282":3,"283":2,"284":1,"285":1,"286":1,"287":3,"627":3,"630":1,"633":1,"636":1,"637":1,"639":1,"640":1,"653":1,"655":1,"658":2,"659":6,"660":5,"662":1,"663":5,"664":1,"666":2,"670":1,"678":1,"679":1,"682":1,"686":1,"688":1,"690":1,"694":2,"697":1,"700":1,"705":4,"706":2,"713":1,"714":5,"725":2,"728":1,"741":1,"749":3}}],["d9",{"2":{"749":1}}],["d1fd9fe",{"2":{"279":1}}],["daemon",{"2":{"272":1}}],["daily",{"2":{"250":1}}],["damage",{"2":{"250":2}}],["day",{"2":{"246":2}}],["dayssinceequinox",{"2":{"657":5}}],["days",{"2":{"228":1}}],["date",{"2":{"224":1,"228":1,"281":1,"655":1}}],["dates",{"2":{"141":1}}],["dataevent",{"0":{"340":1},"2":{"349":1}}],["dataeventfilter",{"0":{"341":1},"2":{"192":1,"224":1,"350":1,"595":1}}],["database",{"2":{"260":1,"265":7,"266":1,"268":2}}],["datamodel",{"2":{"186":1,"187":9,"192":3,"193":11}}],["data",{"0":{"29":1,"33":1,"38":1,"86":1,"288":1,"720":1,"730":1},"1":{"289":1,"290":1,"291":1,"292":1,"293":1,"294":1,"295":1,"296":1,"297":1,"298":1,"299":1,"300":1,"301":1,"302":1,"303":1,"304":1,"305":1,"306":1,"307":1,"308":1,"309":1,"310":1,"311":1,"312":1,"313":1,"314":1,"315":1,"316":1,"317":1,"318":1,"319":1,"320":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"329":1,"330":1,"331":1,"332":1,"333":1,"334":1,"335":1,"336":1,"337":1,"338":1,"339":1,"340":1,"341":1,"342":1,"343":1,"344":1,"345":1,"346":1,"347":1,"348":1,"349":1,"350":1,"351":1,"352":1,"353":1,"354":1,"355":1,"356":1,"357":1,"358":1,"359":1,"360":1,"361":1,"362":1,"363":1,"364":1,"365":1,"366":1,"367":1,"368":1,"369":1,"370":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"378":1,"379":1,"380":1,"381":1,"382":1,"383":1,"384":1,"385":1,"386":1,"387":1,"388":1,"389":1,"390":1,"391":1,"392":1,"393":1,"394":1,"395":1,"396":1,"397":1,"398":1,"399":1,"400":1,"401":1,"402":1,"403":1,"404":1,"405":1,"406":1,"407":1,"408":1,"409":1,"410":1,"411":1,"412":1,"413":1,"414":1,"415":1,"416":1,"417":1,"418":1,"419":1,"420":1,"421":1,"422":1,"423":1,"424":1,"425":1,"426":1,"427":1,"428":1,"429":1,"430":1,"431":1,"432":1,"433":1,"434":1,"435":1,"436":1,"437":1,"438":1,"439":1,"440":1,"441":1,"442":1,"443":1,"444":1,"445":1,"446":1,"447":1,"448":1,"449":1,"450":1,"451":1,"452":1,"453":1,"454":1,"455":1,"456":1,"457":1,"458":1,"459":1,"460":1,"461":1,"462":1,"463":1,"464":1,"465":1,"466":1,"467":1,"468":1,"469":1,"470":1,"471":1,"472":1,"473":1,"474":1,"475":1,"476":1,"477":1,"478":1,"479":1,"480":1,"481":1,"482":1,"483":1,"484":1,"485":1,"486":1,"487":1,"488":1,"489":1,"490":1,"491":1,"492":1,"493":1,"494":1,"495":1,"496":1,"497":1,"498":1,"499":1,"500":1,"501":1,"502":1,"503":1,"504":1,"505":1,"506":1,"507":1,"508":1,"509":1,"510":1,"511":1,"512":1,"513":1,"514":1,"515":1,"516":1,"517":1,"518":1,"519":1,"520":1,"521":1,"522":1,"523":1,"524":1,"525":1,"526":1,"527":1,"528":1,"529":1,"530":1,"531":1,"532":1,"533":1,"534":1,"535":1,"536":1,"537":1,"538":1,"539":1,"540":1,"541":1,"542":1,"543":1,"544":1,"545":1,"546":1,"547":1,"548":1,"549":1,"550":1,"551":1,"552":1,"553":1,"554":1,"555":1,"556":1,"557":1,"558":1,"559":1,"560":1,"561":1,"562":1,"563":1,"564":1,"565":1,"566":1,"567":1,"568":1,"569":1,"570":1,"571":1,"572":1,"573":1,"574":1,"575":1,"576":1,"577":1,"578":1,"579":1,"580":1,"581":1,"582":1,"583":1,"584":1,"585":1,"586":1,"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"593":1,"594":1,"595":1,"596":1,"597":1,"598":1,"599":1,"600":1,"601":1,"602":1,"603":1,"604":1,"605":1,"606":1,"607":1,"608":1,"609":1,"610":1,"611":1,"612":1,"613":1,"614":1,"615":1,"616":1,"617":1,"618":1,"619":1,"620":1,"621":1,"622":1,"623":1,"624":1,"625":1},"2":{"10":1,"12":1,"28":1,"31":1,"33":1,"38":1,"42":2,"46":1,"51":3,"52":1,"53":1,"60":1,"65":1,"67":1,"80":1,"85":1,"86":1,"87":1,"88":1,"94":2,"97":1,"99":1,"103":1,"104":1,"137":8,"167":1,"172":1,"173":1,"174":6,"175":3,"176":2,"177":1,"178":2,"179":1,"180":1,"181":5,"192":1,"207":2,"212":2,"213":2,"214":2,"217":4,"218":1,"219":1,"220":2,"221":1,"224":2,"229":1,"230":1,"231":1,"237":1,"245":2,"246":1,"247":3,"248":2,"249":6,"251":1,"254":1,"255":3,"258":4,"260":2,"261":1,"272":4,"287":2,"349":1,"350":1,"595":1,"627":1,"639":1,"640":1,"656":1,"666":6,"682":1,"685":1,"719":1,"729":1,"746":2,"748":3,"749":1,"750":1,"752":1}}],["dyn",{"2":{"219":2}}],["dynamically",{"2":{"234":1,"241":1,"287":1}}],["dynamic",{"0":{"234":1},"2":{"6":2,"90":1,"219":2,"234":1,"655":1,"725":1}}],["duck",{"2":{"212":1,"214":1}}],["due",{"2":{"196":1,"232":1,"249":1,"631":1,"726":1,"728":1,"753":2}}],["during",{"2":{"69":1,"97":1,"128":2,"221":1,"232":1,"263":1,"627":1}}],["duration",{"0":{"348":1,"464":1},"2":{"57":1,"186":2,"263":1,"464":1,"528":2,"570":2}}],["d3a0e7f5d646",{"2":{"196":1}}],["drinks",{"2":{"94":1,"97":2}}],["drives",{"2":{"247":1}}],["driven",{"2":{"233":1,"709":1}}],["drive",{"2":{"39":1,"249":1,"268":1}}],["drawbacks",{"2":{"217":1}}],["drawback",{"2":{"101":1,"268":1}}],["draw",{"2":{"39":1}}],["d",{"2":{"17":1,"78":1,"88":1,"101":2,"103":1,"137":1,"187":2,"272":1}}],["diligence",{"2":{"656":1}}],["diligently",{"2":{"214":1}}],["dividebyzero",{"2":{"430":1}}],["diverse",{"2":{"267":1,"675":1}}],["dive",{"2":{"246":1}}],["div>",{"2":{"181":6}}],["dictionaries",{"2":{"253":1}}],["dictionary",{"2":{"137":1,"211":1,"238":1}}],["dictate",{"2":{"177":1,"213":1,"220":1}}],["difficult",{"2":{"146":1,"254":1}}],["differing",{"2":{"631":1}}],["differ",{"2":{"137":1}}],["differences",{"2":{"42":1,"138":1,"141":1,"227":1,"229":1}}],["difference",{"2":{"17":1,"56":1,"124":1}}],["differentiate",{"2":{"286":1}}],["differently",{"2":{"87":1,"229":1}}],["different",{"2":{"10":1,"16":1,"21":1,"25":1,"28":2,"31":1,"37":1,"42":1,"44":1,"50":1,"88":2,"90":1,"100":1,"103":1,"116":2,"123":1,"124":1,"127":1,"128":2,"135":2,"137":1,"138":1,"141":1,"143":1,"166":1,"210":1,"213":1,"218":2,"229":1,"238":2,"239":1,"246":1,"248":1,"249":1,"256":2,"258":1,"268":1,"287":1,"631":1,"643":1,"656":2,"672":1}}],["dir",{"2":{"143":2,"171":1,"174":1}}],["direct",{"2":{"65":1,"200":1}}],["directory",{"0":{"243":1,"244":1},"1":{"244":1},"2":{"3":1,"6":2,"16":4,"17":1,"21":1,"134":1,"171":4,"174":1,"186":1,"196":1,"199":2,"200":3,"238":1,"241":1,"242":1,"243":1,"244":1,"283":2}}],["directly",{"2":{"0":1,"13":1,"16":2,"36":1,"42":1,"56":1,"97":1,"127":1,"154":1,"175":1,"201":1,"273":1,"287":1}}],["disabling",{"2":{"250":1}}],["disable",{"2":{"249":1,"259":1}}],["disallowed",{"2":{"62":1}}],["distributed",{"2":{"728":1}}],["distribution",{"2":{"282":1}}],["distributions",{"2":{"241":1,"243":1}}],["distinction",{"2":{"126":1}}],["distinguished",{"2":{"126":1}}],["dispatched",{"2":{"231":1}}],["dispatch",{"2":{"219":3}}],["displayed",{"2":{"238":1}}],["displaystatus",{"2":{"181":2}}],["display",{"2":{"176":1,"500":1}}],["disks",{"2":{"248":1}}],["disk",{"2":{"187":1}}],["discipline",{"2":{"656":1}}],["discriminant",{"2":{"290":1,"294":1,"298":1,"305":1,"311":1,"315":1,"316":1,"317":1,"319":1,"326":1,"327":1,"332":1,"336":1,"339":1,"340":1,"341":1,"343":1,"349":1,"350":1,"353":1,"357":1,"359":1,"393":1,"405":1,"409":1,"414":1,"415":1,"416":1,"417":1,"418":1,"420":1,"421":1,"427":1,"430":1,"438":1,"439":1,"444":1,"445":1,"446":1,"485":1,"487":1,"494":1,"495":1,"497":1,"498":1,"499":1,"500":1,"509":1,"515":1,"516":1,"521":1,"523":1,"531":1,"537":1,"540":1,"546":1,"548":1,"550":1,"553":1,"567":1,"577":1,"578":1,"584":1,"588":1,"589":1,"590":1,"595":1,"596":1,"604":1,"606":1}}],["disconnect",{"2":{"268":1}}],["disconnected",{"2":{"267":1}}],["discord",{"2":{"249":2,"270":3}}],["discover",{"2":{"167":1,"224":1}}],["discovered",{"2":{"151":1,"157":1,"181":1}}],["discovery",{"2":{"140":1,"146":1,"157":1,"158":1}}],["disclosed",{"2":{"248":1}}],["discussed",{"2":{"269":1}}],["discusses",{"2":{"249":1}}],["discuss",{"2":{"42":1,"137":2,"159":1,"160":1,"270":1}}],["diagram",{"2":{"29":1,"658":1,"661":1}}],["digitally",{"0":{"262":1},"1":{"263":1,"264":1,"265":1,"266":1},"2":{"262":1}}],["digital",{"2":{"165":1,"237":1,"238":4,"255":2,"258":2,"259":1,"267":1,"627":1}}],["digits",{"2":{"25":1}}],["digest",{"2":{"18":5,"20":1,"175":1,"177":2,"181":1,"239":1}}],["didn",{"2":{"16":1,"88":2,"154":1,"196":1,"214":1,"221":2,"278":1,"280":1}}],["doubt",{"2":{"286":1}}],["doubly",{"2":{"176":1}}],["double",{"2":{"124":1,"126":2,"143":1,"659":1}}],["doing",{"2":{"248":1,"256":1,"265":1}}],["doomed",{"2":{"178":1,"214":1}}],["does",{"2":{"104":1,"137":1,"162":1,"174":1,"175":2,"192":1,"238":1,"669":1,"671":1,"726":1,"741":1}}],["doesn",{"2":{"5":1,"102":1,"125":1,"160":1,"163":1,"175":2,"176":1,"177":2,"186":1,"203":1,"211":1,"213":2,"220":2,"243":1,"280":1,"283":1,"285":1,"633":1}}],["dominate",{"2":{"103":1}}],["domain=",{"2":{"735":2}}],["domainviolation",{"2":{"430":1}}],["domainownerchanged",{"0":{"347":1},"2":{"343":1}}],["domaineventset",{"0":{"345":1},"2":{"344":1}}],["domaineventfilter",{"0":{"344":1},"2":{"341":1}}],["domainevent",{"0":{"343":1},"2":{"340":1}}],["domainname",{"2":{"176":4,"181":3}}],["domainid",{"0":{"346":1,"436":1,"463":1,"581":1},"2":{"175":2,"176":2,"177":2,"178":5,"179":6,"181":2,"193":7,"219":2,"220":1,"293":1,"308":1,"342":1,"343":3,"344":1,"347":1,"365":1,"387":1,"388":1,"391":1,"392":1,"393":1,"403":1,"414":2,"436":1,"451":1,"463":1,"513":1,"535":1,"581":1,"584":1,"593":1,"600":1,"680":1,"689":1,"690":1,"701":1,"702":1,"713":1,"742":1,"743":1}}],["domain>",{"2":{"104":1,"193":2}}],["domain",{"0":{"83":1,"176":1,"201":1,"203":1,"212":1,"219":1,"342":1,"505":1,"513":1,"535":1,"600":1,"649":1,"699":1},"1":{"700":1,"701":1,"702":1},"2":{"29":5,"38":1,"41":4,"42":5,"56":1,"65":1,"74":1,"82":4,"83":6,"100":1,"104":3,"115":1,"128":4,"130":4,"137":4,"139":1,"164":3,"165":1,"175":2,"176":11,"177":8,"178":4,"179":3,"180":9,"181":8,"187":6,"188":2,"189":1,"190":1,"191":1,"193":8,"200":3,"201":8,"202":4,"203":16,"204":2,"212":6,"213":4,"214":2,"217":2,"219":8,"220":7,"221":2,"227":1,"233":1,"293":1,"308":1,"340":1,"341":1,"343":1,"347":1,"365":1,"387":1,"388":1,"393":1,"403":1,"415":2,"509":2,"515":2,"537":2,"584":1,"593":1,"604":2,"626":1,"648":1,"649":1,"658":1,"660":2,"663":6,"668":1,"669":1,"672":1,"679":1,"680":1,"689":1,"690":1,"699":4,"700":1,"701":2,"702":1,"713":2,"742":2,"743":2}}],["domainsaccountsassets",{"2":{"180":1}}],["domains",{"0":{"30":1,"180":1,"187":1},"2":{"12":4,"29":3,"33":1,"41":3,"42":1,"50":1,"51":1,"80":1,"104":4,"111":2,"116":1,"128":1,"130":2,"166":1,"172":1,"176":1,"180":2,"187":5,"188":1,"189":1,"190":1,"191":1,"200":2,"221":1,"649":1,"660":1,"700":1,"735":4}}],["dormouse",{"2":{"91":1,"92":5}}],["don",{"2":{"16":2,"57":1,"82":1,"88":2,"97":2,"101":1,"102":1,"103":1,"141":1,"175":1,"177":1,"213":1,"215":1,"217":1,"220":1,"221":1,"232":1,"272":1,"273":1,"278":1,"282":1}}],["done",{"2":{"13":1,"18":1,"22":1,"39":1,"65":2,"71":1,"98":1,"105":1,"127":1,"135":1,"161":1,"219":1,"230":1,"233":1,"236":1,"282":1,"678":1}}],["do",{"2":{"13":1,"16":3,"17":1,"18":2,"20":1,"21":2,"36":1,"40":1,"41":1,"44":1,"56":4,"62":1,"65":1,"82":1,"88":1,"94":2,"97":2,"101":3,"104":1,"105":2,"135":1,"137":1,"139":1,"151":1,"154":3,"163":1,"175":1,"177":1,"187":1,"190":1,"203":1,"210":1,"211":2,"214":1,"215":2,"218":1,"219":2,"220":1,"221":1,"224":1,"228":1,"243":1,"247":1,"272":2,"273":1,"279":1,"283":1,"286":1,"656":4,"665":1,"672":1,"679":1}}],["downs",{"2":{"709":1}}],["downside",{"2":{"175":1}}],["download",{"2":{"249":1}}],["downtime",{"2":{"137":1}}],["down",{"2":{"6":1,"91":1,"104":1,"110":1,"137":1,"224":1,"253":2,"282":1}}],["documents",{"2":{"258":2}}],["document",{"2":{"224":1,"225":1,"236":1,"250":1}}],["documentation",{"2":{"0":1,"2":1,"4":2,"5":1,"99":1,"166":1,"168":1,"174":1,"201":1,"208":1,"210":1,"211":1,"217":1,"224":1,"226":1,"235":1,"244":1,"270":1,"287":2,"639":1,"714":1}}],["doctors",{"2":{"137":1}}],["docker",{"0":{"6":1,"197":1,"272":1,"275":1},"1":{"7":1,"8":1,"9":1},"2":{"6":9,"8":1,"9":2,"13":1,"18":4,"19":1,"21":1,"128":1,"143":1,"195":2,"196":5,"197":3,"207":1,"210":2,"217":1,"226":1,"241":1,"272":6,"628":1}}],["docs",{"2":{"5":3,"12":1,"217":1,"725":1}}],["derive",{"2":{"657":1}}],["derived",{"2":{"127":1,"252":1,"256":1}}],["deep",{"2":{"246":1}}],["deal",{"2":{"230":1}}],["dealing",{"2":{"79":1,"260":1}}],["dear",{"2":{"221":1}}],["demonstration",{"2":{"214":1}}],["demo",{"0":{"182":1},"2":{"182":1,"272":1}}],["de757bcb79f4c63e8fa0795edc26f86dfdba189b846e903d0b732bb644607720e555d194e8822da35ac541ce9eec8b45058f4d294d9426ef97ba92698766f7d3",{"2":{"175":1}}],["de",{"2":{"174":1,"211":1,"218":1,"273":1}}],["delve",{"2":{"251":1}}],["delimiter$whiterabbit",{"2":{"190":1}}],["delimiter$madhatter",{"2":{"189":1}}],["delimiter$domain",{"2":{"188":1,"189":1,"190":1}}],["delay",{"2":{"143":1,"151":2}}],["delayed",{"2":{"89":1}}],["deleted",{"2":{"3":1,"290":1,"292":1,"305":1,"307":1,"311":1,"313":1,"336":1,"338":1,"343":1,"345":1,"523":1,"525":1,"590":1,"592":1}}],["denoted",{"2":{"124":1,"143":1,"287":1}}],["denies",{"2":{"63":1}}],["denyall",{"2":{"62":1}}],["deny",{"2":{"62":5,"63":1}}],["deserialization",{"2":{"749":1}}],["deserialize",{"2":{"272":2}}],["deserialising",{"2":{"219":1,"273":1}}],["desktop",{"2":{"249":2}}],["destroyed",{"2":{"230":1}}],["destination",{"2":{"41":2,"128":4,"164":4,"178":1,"179":1,"214":2,"329":1,"330":1,"331":1,"406":1,"407":1,"408":1,"440":1,"441":1,"442":1,"443":1,"518":1,"519":1,"520":1,"580":1,"581":1,"582":1,"583":1}}],["despite",{"2":{"137":1,"219":1,"235":1}}],["desirable",{"2":{"155":1}}],["desired",{"2":{"89":1}}],["designs",{"2":{"631":1}}],["designated",{"2":{"728":1}}],["designate",{"2":{"260":1}}],["design",{"2":{"90":1,"177":1,"213":1,"220":1,"232":1}}],["designed",{"2":{"52":1,"225":1,"230":1,"233":1,"248":1}}],["describes",{"2":{"237":1,"247":1}}],["describe",{"2":{"113":1,"164":1,"236":1}}],["described",{"2":{"55":1,"201":1,"271":1,"274":1,"277":1,"284":1,"285":1}}],["description",{"2":{"62":1,"174":1,"658":1,"717":1,"723":1,"726":1,"733":1,"735":1,"738":1,"741":1,"746":1,"749":1,"753":1}}],["descriptions",{"2":{"40":1,"661":1,"666":2}}],["dedicated",{"2":{"29":1,"80":1,"98":1,"136":1,"139":1,"270":1,"667":1,"672":1}}],["declarations",{"2":{"289":1,"291":1,"293":1,"295":1,"296":1,"297":1,"302":1,"303":1,"304":1,"306":1,"308":1,"309":1,"310":1,"312":1,"314":1,"318":1,"320":1,"321":1,"322":1,"323":1,"325":1,"329":1,"330":1,"331":1,"337":1,"342":1,"344":1,"346":1,"347":1,"354":1,"355":1,"356":1,"358":1,"360":1,"362":1,"363":1,"364":1,"365":1,"366":1,"367":1,"380":1,"381":1,"382":1,"383":1,"384":1,"385":1,"386":1,"387":1,"388":1,"389":1,"390":1,"391":1,"392":1,"395":1,"396":1,"397":1,"398":1,"399":1,"400":1,"401":1,"402":1,"403":1,"404":1,"406":1,"407":1,"408":1,"419":1,"426":1,"428":1,"429":1,"433":1,"434":1,"435":1,"436":1,"437":1,"440":1,"441":1,"442":1,"443":1,"447":1,"449":1,"450":1,"451":1,"452":1,"453":1,"457":1,"458":1,"483":1,"484":1,"486":1,"488":1,"490":1,"491":1,"492":1,"493":1,"496":1,"501":1,"502":1,"503":1,"504":1,"505":1,"506":1,"507":1,"508":1,"510":1,"511":1,"512":1,"513":1,"514":1,"517":1,"518":1,"519":1,"520":1,"522":1,"524":1,"526":1,"527":1,"528":1,"529":1,"530":1,"532":1,"533":1,"534":1,"535":1,"536":1,"538":1,"539":1,"544":1,"545":1,"547":1,"549":1,"551":1,"552":1,"554":1,"555":1,"556":1,"568":1,"570":1,"571":1,"572":1,"573":1,"574":1,"575":1,"576":1,"579":1,"580":1,"581":1,"582":1,"583":1,"585":1,"586":1,"587":1,"591":1,"593":1,"594":1,"597":1,"598":1,"599":1,"600":1,"601":1,"602":1,"603":1,"605":1,"618":1}}],["declare",{"2":{"175":5,"176":2,"180":2,"183":1}}],["declared",{"2":{"43":1}}],["decreasing",{"2":{"252":1}}],["decrease",{"2":{"98":1,"105":1,"246":1}}],["decreases",{"2":{"97":3}}],["decoded",{"2":{"738":1}}],["decoding",{"2":{"28":1}}],["decouple",{"2":{"174":1}}],["deciphered",{"2":{"255":1}}],["decisions",{"2":{"262":1}}],["decision",{"2":{"65":1}}],["decided",{"2":{"86":1,"100":1}}],["decides",{"2":{"62":1}}],["decide",{"2":{"42":1,"108":1,"138":1,"141":1,"160":1}}],["decimal",{"2":{"25":1,"50":1}}],["detect",{"2":{"260":1}}],["deterministic",{"2":{"238":1}}],["determining",{"2":{"97":1,"247":1}}],["determined",{"2":{"85":2,"110":1,"128":1}}],["determines",{"2":{"79":1,"81":2,"143":1}}],["determine",{"2":{"22":1,"81":1,"153":1,"203":1}}],["detour",{"2":{"226":1}}],["detail",{"2":{"25":1,"42":1,"99":1,"160":1,"201":1,"226":1,"270":1,"655":1,"672":1}}],["detailed",{"2":{"16":1,"29":1,"70":1,"85":1,"226":1,"263":1}}],["details",{"2":{"13":2,"51":1,"57":1,"65":1,"81":1,"97":1,"115":1,"139":1,"140":1,"141":2,"143":1,"145":1,"164":2,"170":1,"174":1,"201":1,"248":1,"249":1,"252":1,"640":1,"662":1,"666":1,"668":1,"669":1,"670":1,"671":1,"673":1,"674":1,"676":1,"677":1,"678":1,"679":1,"680":1,"681":1,"683":1,"684":1,"685":1,"686":1,"687":1,"688":1,"689":1,"690":1,"691":1,"692":1,"693":1,"694":1,"696":1,"697":1,"698":1,"700":1,"701":1,"702":1,"704":1,"705":1,"707":1,"708":1,"710":1,"711":1,"712":1,"713":1,"749":1}}],["depth",{"0":{"167":1}}],["depend",{"2":{"175":1}}],["depends",{"2":{"79":1,"137":1,"174":1,"253":1,"272":1}}],["depending",{"2":{"42":1,"141":1,"196":1,"218":1,"244":1,"249":1,"272":1,"666":1,"728":1}}],["dependencies",{"2":{"3":1,"103":1,"185":2,"217":2,"231":1,"234":1}}],["deployed",{"2":{"137":1,"247":1,"286":1}}],["deploying",{"2":{"132":1,"196":1}}],["deployments",{"2":{"20":1,"165":1,"234":1,"667":1}}],["deployment",{"0":{"22":1,"132":1,"274":1},"1":{"133":1,"134":1,"135":1,"136":1,"275":1,"276":1},"2":{"14":1,"65":1,"143":1,"146":1,"210":1,"230":1,"274":1,"285":1,"648":1,"650":1}}],["deploy",{"0":{"19":1},"1":{"20":1,"21":1},"2":{"14":1,"16":2,"17":2,"22":2,"185":1,"196":1,"260":1}}],["debugging",{"0":{"106":1},"2":{"105":1,"106":1,"700":1,"705":1}}],["debuginfo",{"2":{"105":1}}],["debug",{"2":{"14":4,"16":5,"17":1,"106":4,"110":1,"153":1,"176":1,"181":1,"241":1,"242":1,"243":1,"427":1,"725":1}}],["devoid",{"2":{"253":1}}],["devastating",{"2":{"245":1}}],["devices",{"2":{"224":1,"247":1,"248":5,"258":1}}],["device",{"2":{"137":1,"248":2,"249":2,"268":2}}],["developing",{"2":{"250":1}}],["develop",{"2":{"248":1,"260":1}}],["developer",{"2":{"219":1}}],["developers",{"2":{"108":1,"226":1,"268":1}}],["development",{"2":{"3":1,"137":1,"174":1,"185":1,"211":1,"230":1,"235":1,"236":1}}],["dev",{"2":{"5":1,"18":4,"143":2,"154":1,"170":1,"185":1,"272":1}}],["def",{"2":{"221":3}}],["definitionid",{"2":{"214":4,"221":1}}],["definition",{"2":{"52":6,"57":4,"128":3,"164":3,"178":1,"179":2,"180":2,"189":3,"190":1,"191":1,"193":6,"204":2,"214":1,"221":1,"222":2,"309":1,"310":1,"314":1,"367":1,"386":1,"388":1,"491":1,"663":12,"664":8,"684":2,"688":1,"690":1,"693":1,"694":1,"743":1}}],["definitions`",{"2":{"180":1}}],["definitions",{"2":{"33":1,"41":3,"42":1,"50":1,"51":1,"55":1,"57":1,"111":1,"180":2,"201":1,"286":1,"342":1,"626":1,"673":1,"684":1,"725":1}}],["defining",{"2":{"36":1}}],["define",{"0":{"94":1},"2":{"5":1,"137":1,"176":1,"203":1,"220":1,"664":4}}],["defines",{"2":{"2":2,"252":1,"658":2}}],["defined",{"2":{"2":1,"5":1,"75":1,"178":3,"260":1,"286":1,"658":1,"659":1,"663":1}}],["defaultgenesis",{"2":{"193":7}}],["defaults",{"2":{"115":1,"125":1,"132":2,"196":1,"199":1}}],["default",{"0":{"127":1,"130":1,"281":1},"2":{"2":1,"3":1,"5":2,"63":1,"114":1,"124":1,"125":2,"127":1,"128":1,"130":1,"137":2,"141":1,"143":1,"144":1,"153":1,"155":1,"186":9,"193":9,"196":1,"200":3,"203":1,"214":1,"217":1,"218":2,"219":2,"238":2,"249":1,"272":1,"281":2,"663":1,"664":1,"667":1,"748":1}}],["icecat",{"2":{"249":1}}],["iuse",{"2":{"202":1}}],["i2p",{"2":{"185":1}}],["ignore",{"2":{"137":1,"175":1}}],["ignored",{"2":{"117":1}}],["io",{"2":{"185":1,"217":2,"714":1}}],["iot",{"2":{"137":1}}],["ios",{"2":{"136":1}}],["ilovetea",{"2":{"117":1}}],["illustrative",{"2":{"188":1}}],["illustration",{"2":{"29":1,"224":1}}],["illustrates",{"2":{"253":1}}],["illustrated",{"2":{"29":1}}],["illustrate",{"2":{"29":1}}],["irrelevant",{"2":{"97":1}}],["irohad",{"2":{"196":3}}],["irohad1",{"2":{"196":6}}],["irohad3",{"2":{"196":6}}],["irohad0",{"2":{"196":12}}],["irohad2",{"2":{"196":7}}],["irohatest",{"2":{"193":2}}],["irohacontainer",{"2":{"186":4}}],["irohaconfig",{"2":{"186":1}}],["irohax",{"2":{"20":1,"21":1}}],["iroha3",{"2":{"18":8,"146":1}}],["iroha1",{"2":{"18":8,"146":1}}],["iroha0",{"2":{"6":1,"18":8,"146":1}}],["iroha2asyncclient>",{"2":{"193":1}}],["iroha2asyncclient",{"2":{"193":1}}],["iroha2config",{"2":{"186":1}}],["iroha2client",{"2":{"186":1}}],["iroha2ver",{"2":{"185":1}}],["iroha2",{"2":{"5":2,"16":4,"18":12,"146":1,"173":1,"174":15,"175":13,"176":2,"177":1,"178":2,"179":1,"180":2,"181":11,"183":1,"186":8,"187":12,"192":4,"193":20,"210":1,"211":1,"212":2,"213":2,"214":2,"272":2}}],["iroha",{"0":{"6":1,"13":1,"18":1,"39":1,"40":1,"118":1,"147":1,"165":1,"169":1,"171":1,"172":1,"185":1,"186":1,"194":1,"196":1,"198":1,"199":1,"200":1,"210":1,"211":1,"217":1,"218":1,"229":2,"635":1,"645":1,"646":1,"647":1,"648":1,"649":1,"650":1,"651":1,"661":1},"1":{"7":1,"8":1,"9":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1,"41":1,"42":1,"43":1,"44":1,"45":1,"46":1,"47":1,"48":1,"49":1,"119":1,"120":1,"148":1,"149":1,"150":1,"166":1,"167":1,"168":1,"170":1,"171":1,"172":2,"195":1,"196":1,"197":2,"199":1,"200":1,"201":1,"202":1,"203":1,"204":1,"205":1,"206":1,"207":1,"208":1,"230":2,"231":2,"232":2,"233":2,"234":2,"235":2,"636":1,"637":1,"638":1,"639":1,"640":1,"641":1,"642":1,"643":1,"644":1,"647":1,"648":1,"649":1,"650":1},"2":{"2":2,"5":9,"6":6,"9":2,"10":3,"12":2,"13":4,"14":6,"16":17,"17":12,"18":17,"19":2,"20":3,"21":3,"22":6,"24":1,"28":2,"33":1,"36":1,"37":2,"38":1,"39":5,"40":4,"41":1,"47":1,"49":1,"52":2,"53":1,"55":1,"60":1,"62":1,"63":1,"65":2,"69":1,"72":1,"82":1,"88":1,"89":1,"98":2,"99":1,"100":1,"103":6,"104":3,"106":2,"111":1,"116":1,"117":1,"120":2,"123":1,"127":1,"128":1,"132":1,"134":1,"136":5,"137":1,"138":2,"141":2,"143":1,"146":4,"150":2,"151":2,"154":1,"155":1,"158":1,"164":1,"165":3,"166":14,"167":4,"168":7,"169":1,"170":1,"171":4,"172":8,"173":2,"174":8,"175":8,"178":2,"181":2,"183":1,"185":11,"186":1,"187":2,"188":1,"189":2,"192":1,"194":1,"195":1,"196":20,"197":2,"198":2,"199":3,"200":9,"201":2,"202":3,"203":4,"204":4,"205":1,"206":1,"207":2,"208":2,"210":13,"211":2,"212":1,"214":2,"215":1,"217":18,"218":5,"219":5,"220":1,"221":4,"224":4,"225":2,"226":2,"227":4,"228":2,"229":9,"230":7,"231":1,"232":3,"233":4,"234":2,"235":3,"236":1,"237":2,"238":1,"241":2,"245":1,"246":2,"247":2,"248":1,"249":1,"256":1,"257":1,"262":2,"270":3,"271":2,"272":12,"274":1,"277":1,"283":1,"284":1,"285":1,"626":9,"628":5,"633":1,"634":1,"635":1,"636":1,"640":1,"641":2,"642":1,"643":2,"644":1,"645":1,"646":1,"648":1,"650":3,"654":1,"656":4,"658":1,"660":1,"661":2,"662":1,"663":3,"664":1,"667":1,"675":1,"699":1,"709":2,"714":6,"715":1,"717":1,"725":1,"734":1,"744":1,"747":1,"749":2}}],["idioms",{"2":{"212":1}}],["idiomatically",{"2":{"211":1}}],["idx",{"2":{"186":3}}],["id=asset",{"2":{"214":1}}],["id=ed0120cacf3a84b8dc8710ce9d6b968ee95ec7ee4c93c85858f026f3b4417f569592ce",{"2":{"196":2}}],["id=ed01209897952d14bdfaea780087c38ff3eb800cb20b882748fc95a575adb9cd2cb21d",{"2":{"196":2}}],["id=ed0120a98bafb0663ce08d75ebd506fec38a84e576a7c9b0897693ed4b04fd9ef2d18d",{"2":{"196":2}}],["id=ed01204ee2fcd53e1730af142d1e23951198678295047f9314b4006b0cb61850b1db10",{"2":{"196":3}}],["id=",{"2":{"181":1,"201":1,"202":1,"203":1,"204":2,"205":1,"206":1}}],["idle",{"2":{"143":2,"196":1}}],["idfilter",{"2":{"94":10}}],["idbox",{"0":{"414":1},"2":{"92":4,"93":2,"178":2,"179":2,"222":2,"499":1,"517":1}}],["id$domain",{"2":{"74":1}}],["ids",{"2":{"53":2,"492":1,"669":2,"671":1}}],["ideographic",{"2":{"238":1}}],["identify",{"2":{"260":1}}],["identifies",{"2":{"260":1}}],["identified",{"2":{"217":1,"704":1}}],["identifier",{"2":{"202":1,"691":1,"692":1,"693":1,"701":1,"702":1}}],["identifiablebox",{"0":{"415":1},"2":{"92":4,"96":1,"176":2,"177":2,"178":2,"181":2,"219":1,"220":1,"499":1}}],["identifiable>",{"2":{"53":1}}],["identifiable",{"2":{"42":2,"176":2,"177":1,"178":1,"180":3,"181":1,"212":2,"213":1,"214":1,"499":1,"500":1}}],["identical",{"2":{"256":1,"630":1}}],["identity",{"2":{"224":1,"255":1,"259":1}}],["identities",{"2":{"94":1}}],["ideally",{"2":{"72":1,"248":1}}],["idea",{"2":{"16":1,"117":1,"136":1,"161":1,"177":1,"213":1,"220":1,"268":1,"627":1}}],["id",{"0":{"74":1},"2":{"36":1,"40":1,"42":1,"52":7,"53":15,"57":8,"60":4,"61":3,"66":2,"71":4,"72":1,"73":1,"74":1,"83":2,"93":1,"94":2,"95":1,"104":5,"113":2,"116":1,"127":2,"128":18,"143":1,"145":1,"164":20,"175":1,"176":2,"177":2,"178":8,"179":10,"180":14,"181":2,"187":3,"188":4,"189":7,"190":2,"193":25,"196":1,"200":3,"201":1,"202":7,"204":3,"217":1,"218":2,"219":1,"220":6,"221":4,"222":15,"289":1,"291":1,"293":1,"295":2,"296":2,"302":1,"303":1,"304":1,"306":1,"308":1,"309":1,"310":1,"312":1,"314":2,"329":1,"330":1,"331":1,"337":1,"342":1,"344":1,"347":1,"354":1,"355":1,"356":1,"363":1,"364":1,"365":1,"367":1,"380":1,"381":1,"382":1,"383":1,"384":1,"385":1,"386":1,"387":1,"388":2,"391":1,"392":1,"395":1,"396":1,"397":1,"398":1,"400":1,"401":1,"402":1,"403":1,"404":1,"406":1,"407":1,"408":1,"433":1,"434":1,"435":1,"436":1,"437":1,"440":1,"441":1,"442":1,"443":1,"449":1,"450":1,"451":1,"483":1,"486":1,"488":1,"491":1,"499":1,"510":1,"511":1,"512":1,"513":1,"514":1,"517":1,"518":1,"519":1,"520":1,"522":1,"524":1,"527":2,"532":1,"533":1,"534":1,"535":1,"536":1,"575":1,"580":2,"581":2,"582":2,"583":2,"585":1,"586":1,"587":1,"591":1,"593":1,"594":1,"597":1,"598":1,"599":1,"600":1,"601":1,"602":1,"603":1,"661":1,"664":4,"670":1,"688":1,"690":1,"711":1,"712":1,"713":1,"741":1}}],["immediately",{"2":{"187":1,"219":1}}],["immediate",{"2":{"108":1,"181":1,"217":1}}],["imagine",{"2":{"88":1,"137":1,"221":1}}],["imagename",{"2":{"186":1}}],["imagetag",{"2":{"186":1}}],["imagepullpolicy",{"2":{"186":2}}],["images",{"2":{"186":2}}],["image",{"2":{"18":4,"186":2,"196":1,"241":1}}],["improperly",{"2":{"753":2}}],["improving",{"2":{"252":1}}],["improvement",{"2":{"260":2}}],["improvements",{"2":{"166":1}}],["improves",{"2":{"259":1}}],["improve",{"2":{"247":1}}],["improved",{"2":{"230":1}}],["impartial",{"2":{"260":1}}],["impact",{"2":{"39":1,"666":1}}],["impersonate",{"2":{"259":2}}],["impervious",{"2":{"251":1}}],["impl",{"2":{"657":1,"659":1}}],["implicit",{"2":{"176":1,"221":1}}],["implements",{"2":{"175":1}}],["implementing",{"2":{"97":1,"175":1,"260":1,"268":1}}],["implemented",{"2":{"90":1,"97":1,"161":1,"165":1,"186":1,"229":1,"272":1,"641":1}}],["implement",{"2":{"36":1,"175":2,"187":1,"188":1,"189":2,"191":1,"260":2,"262":1}}],["implementations",{"2":{"62":1,"103":1,"229":1,"655":1}}],["implementation",{"2":{"6":1,"97":1,"185":7,"256":1,"273":1,"640":1,"657":1,"659":1,"666":1}}],["impostor",{"2":{"256":1}}],["impossible",{"2":{"254":1}}],["imposed",{"2":{"137":1}}],["importance",{"2":{"230":1}}],["important",{"2":{"105":1,"110":1,"212":1,"234":1,"248":1,"249":1,"253":1,"258":1,"268":1,"628":1}}],["imports",{"2":{"177":1,"187":1}}],["imported",{"2":{"104":1}}],["import",{"2":{"5":1,"174":1,"175":8,"176":2,"180":1,"181":26,"186":17,"187":15,"192":3,"193":27,"211":1,"212":2,"213":2,"214":1}}],["ipv6",{"2":{"553":1}}],["ipv6addr",{"0":{"424":1},"2":{"137":1,"556":1}}],["ipv4",{"2":{"553":1}}],["ipv4addr",{"0":{"423":1},"2":{"555":1}}],["ipfspath",{"0":{"422":1,"468":1},"2":{"304":1,"342":1,"450":1,"451":1,"468":1}}],["ip",{"2":{"12":1,"65":1,"555":1,"556":1}}],["ipsum",{"2":{"4":6}}],["if=",{"2":{"181":1}}],["if",{"0":{"282":1},"2":{"6":4,"13":1,"14":1,"16":2,"18":2,"21":1,"28":6,"32":1,"36":2,"39":2,"40":2,"41":2,"43":1,"49":2,"57":2,"62":4,"69":1,"78":1,"84":1,"88":4,"89":1,"90":1,"91":1,"94":3,"97":2,"98":1,"100":1,"104":1,"120":1,"123":1,"125":2,"128":3,"132":1,"134":1,"135":2,"136":1,"137":3,"148":1,"150":1,"154":3,"155":1,"156":1,"160":2,"163":1,"166":3,"168":1,"171":1,"174":4,"175":1,"176":2,"177":4,"178":2,"181":1,"185":1,"186":1,"192":2,"200":1,"202":1,"204":1,"210":1,"211":2,"213":4,"215":1,"217":2,"218":1,"219":5,"220":4,"221":2,"227":1,"230":1,"232":1,"233":1,"238":6,"243":1,"244":4,"248":1,"249":2,"250":2,"253":2,"254":1,"256":1,"258":1,"261":1,"263":1,"265":1,"271":1,"272":5,"273":7,"274":1,"277":1,"278":1,"279":2,"280":2,"281":1,"282":1,"283":4,"284":1,"285":4,"286":3,"632":1,"633":1,"647":1,"661":1,"679":1,"683":1,"684":2,"705":1,"728":1,"748":1}}],["i",{"2":{"3":1,"41":1,"42":1,"84":1,"125":1,"141":1,"174":8,"175":1,"183":1,"221":1,"230":1,"252":2,"282":1,"647":1,"720":1,"723":1}}],["islistening",{"2":{"181":3}}],["isn",{"2":{"137":1,"160":1,"177":1,"213":1,"214":2,"215":1,"219":1,"220":1,"221":1,"253":1,"273":1}}],["isi",{"0":{"98":1,"646":1},"1":{"647":1,"648":1,"649":1,"650":1},"2":{"28":1,"39":1,"41":1,"72":1,"97":1,"100":3,"101":5,"103":1,"212":2,"213":2,"214":1,"219":1,"233":1,"626":1,"646":1,"647":1}}],["issued",{"2":{"632":1}}],["issue",{"2":{"6":2,"12":3,"97":1,"128":1,"219":1,"270":1,"271":1,"272":2,"274":1,"277":1,"283":1,"284":1,"285":1,"725":3,"749":1}}],["issues",{"0":{"271":1,"274":1,"277":1,"284":1},"1":{"272":1,"273":1,"275":1,"276":1,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1},"2":{"6":1,"14":1,"215":1,"218":1,"249":1,"271":2,"274":1,"277":1,"284":1,"285":5,"286":1}}],["is",{"2":{"0":1,"2":1,"3":1,"4":1,"5":1,"6":1,"10":1,"12":1,"13":3,"14":1,"16":7,"17":2,"18":5,"19":1,"20":2,"21":3,"22":2,"24":2,"25":5,"28":10,"29":1,"31":2,"32":1,"33":1,"34":1,"35":1,"36":4,"38":4,"39":9,"40":1,"41":4,"42":4,"45":1,"46":1,"48":1,"50":1,"51":2,"52":2,"56":1,"57":2,"59":1,"61":1,"62":9,"63":2,"65":5,"66":1,"67":1,"69":3,"71":3,"72":3,"74":1,"75":2,"77":1,"78":2,"79":3,"80":2,"81":4,"82":1,"84":3,"85":3,"87":1,"88":6,"89":3,"90":3,"93":1,"94":10,"97":5,"98":2,"99":2,"100":3,"101":5,"103":7,"104":1,"106":5,"108":1,"110":4,"111":2,"112":1,"113":2,"116":4,"117":1,"118":1,"119":2,"120":1,"125":3,"126":4,"128":9,"131":1,"134":1,"135":4,"137":6,"140":1,"141":4,"146":6,"147":1,"148":3,"149":1,"150":1,"151":1,"153":1,"154":4,"155":2,"157":2,"158":2,"160":2,"161":3,"162":1,"163":2,"164":2,"165":1,"166":1,"170":1,"171":2,"174":2,"175":14,"176":5,"177":5,"178":4,"181":5,"182":1,"183":2,"186":1,"187":2,"188":1,"189":1,"191":1,"192":3,"197":1,"200":3,"201":3,"202":2,"203":5,"204":1,"206":1,"210":3,"211":6,"212":8,"213":3,"214":8,"215":3,"217":4,"218":1,"219":9,"220":6,"221":7,"222":1,"223":1,"224":4,"225":1,"226":2,"228":1,"229":1,"230":3,"231":2,"232":2,"233":5,"234":2,"235":2,"236":1,"238":10,"241":2,"242":1,"243":2,"244":1,"245":2,"247":6,"248":7,"249":4,"250":3,"251":1,"252":6,"253":3,"254":1,"255":1,"256":3,"259":6,"260":1,"262":1,"263":6,"264":3,"265":3,"266":5,"268":6,"271":2,"272":6,"273":5,"274":1,"277":1,"280":2,"281":2,"282":1,"283":5,"284":1,"285":2,"286":2,"287":3,"567":1,"627":1,"629":2,"632":1,"633":2,"634":1,"637":1,"640":1,"641":1,"643":1,"650":1,"654":1,"656":6,"657":1,"658":6,"660":6,"663":2,"664":3,"666":5,"667":1,"675":1,"678":1,"679":1,"682":1,"683":1,"684":2,"691":1,"699":1,"703":1,"705":1,"706":1,"709":1,"710":1,"714":4,"717":2,"723":1,"725":2,"726":4,"728":3,"741":2,"748":4,"749":2,"750":1,"753":3}}],["iteration",{"2":{"228":1,"253":2}}],["items",{"2":{"69":1}}],["itself",{"2":{"72":1,"135":1,"163":1,"175":1,"684":1,"749":1}}],["its",{"2":{"18":1,"32":1,"81":1,"106":1,"127":2,"135":1,"136":1,"137":1,"146":1,"169":1,"174":1,"175":2,"200":1,"204":1,"210":2,"211":1,"214":1,"219":1,"221":1,"223":1,"230":1,"232":1,"233":1,"238":1,"247":1,"249":1,"256":1,"261":1,"264":1,"272":1,"628":1,"634":1,"664":2,"669":1,"684":1,"703":1,"714":1}}],["it",{"0":{"1":1,"97":1},"1":{"2":1,"3":1,"4":1},"2":{"0":1,"3":1,"4":1,"5":4,"6":4,"14":4,"16":4,"17":2,"18":1,"28":2,"38":1,"41":1,"42":1,"61":1,"63":2,"65":3,"69":1,"72":1,"75":1,"81":2,"82":1,"84":1,"88":5,"89":2,"90":2,"94":3,"97":1,"98":3,"99":1,"101":3,"102":1,"103":2,"104":3,"105":2,"106":1,"109":1,"110":2,"113":1,"116":1,"125":5,"126":1,"127":1,"128":5,"136":2,"137":6,"141":6,"146":3,"148":1,"150":2,"154":3,"155":1,"159":1,"160":1,"161":2,"163":3,"164":1,"171":1,"172":1,"174":1,"175":6,"176":3,"177":6,"178":2,"181":1,"187":3,"188":3,"189":4,"190":1,"191":1,"192":2,"196":1,"198":2,"200":2,"201":2,"202":3,"203":4,"210":3,"211":2,"212":3,"213":5,"214":1,"217":2,"218":2,"219":2,"220":6,"221":4,"222":1,"224":1,"228":1,"229":1,"230":1,"232":2,"234":2,"238":4,"241":2,"243":2,"245":1,"247":2,"248":3,"249":3,"250":1,"251":1,"252":1,"253":10,"254":1,"256":2,"259":4,"261":1,"262":1,"263":4,"264":2,"266":1,"268":7,"270":1,"271":1,"272":2,"273":8,"279":1,"280":3,"281":2,"282":3,"283":2,"286":2,"628":1,"631":2,"633":1,"637":1,"638":1,"639":1,"643":2,"644":1,"656":5,"667":1,"669":1,"670":1,"671":1,"679":1,"684":1,"706":1,"714":2,"723":1,"725":1,"750":2}}],["inherent",{"2":{"659":2}}],["inner",{"2":{"453":1}}],["inactive",{"2":{"230":1}}],["inadvertently",{"2":{"97":1,"268":1}}],["invariantviolation",{"2":{"418":1}}],["invalidsingularparameters",{"2":{"741":2}}],["invalidsegment",{"2":{"438":1}}],["invalidparametererror",{"0":{"421":1},"2":{"418":1}}],["invalidparameter",{"2":{"418":1}}],["invalid",{"2":{"273":1,"741":2}}],["invoked",{"2":{"646":1}}],["invoking",{"2":{"642":1}}],["involving",{"2":{"249":1}}],["involved",{"2":{"101":1,"137":1,"177":1,"188":1,"220":1,"222":1,"735":1}}],["involves",{"2":{"13":1,"107":1}}],["invocation",{"2":{"238":1}}],["invite",{"2":{"227":1}}],["inject",{"2":{"174":1}}],["ineffective",{"2":{"137":1,"247":1}}],["influenced",{"2":{"262":1}}],["inflates",{"2":{"252":1}}],["infamous",{"2":{"249":1}}],["infrastructure",{"2":{"101":1,"260":2}}],["infinitely",{"2":{"128":2,"164":2,"178":2,"189":1,"446":1}}],["infinite",{"2":{"97":1,"215":1,"224":2}}],["infinitesimally",{"2":{"88":1}}],["information",{"2":{"14":1,"28":1,"32":1,"39":2,"65":4,"70":1,"72":1,"85":1,"106":4,"137":3,"154":1,"161":2,"167":1,"168":2,"190":1,"217":1,"253":1,"254":1,"255":1,"258":4,"259":5,"260":1,"261":1,"263":2,"264":1,"268":1,"287":1,"627":1,"629":1,"633":1,"662":1,"666":1,"677":1,"682":1,"683":1,"714":1,"728":1}}],["info",{"0":{"106":1},"2":{"13":1,"14":1,"42":2,"78":1,"82":1,"89":1,"90":1,"94":1,"97":2,"105":1,"120":1,"139":1,"140":1,"141":1,"143":3,"150":1,"153":1,"154":1,"157":1,"160":1,"173":2,"174":3,"175":2,"181":1,"189":1,"196":19,"199":1,"201":1,"211":1,"217":1,"218":1,"219":1,"221":2,"230":1,"234":1,"235":1,"244":1,"268":1,"272":1,"287":1,"427":1,"656":1,"663":1,"665":1,"683":1,"709":1,"714":1,"715":1,"717":1,"723":1,"725":1,"734":1,"735":1,"741":1,"744":1,"747":1}}],["industry",{"2":{"245":1}}],["indicating",{"2":{"223":1,"287":3}}],["individuals",{"2":{"246":1,"247":1,"255":1,"259":2,"261":1}}],["individually",{"2":{"217":1}}],["individual",{"0":{"259":1},"2":{"65":1,"257":1}}],["independently",{"2":{"259":1}}],["index",{"2":{"207":3,"318":1,"323":1}}],["indeed",{"2":{"106":1,"256":1,"726":1}}],["indefinitely",{"2":{"77":1,"84":1,"88":1,"93":1,"516":1}}],["inserted",{"2":{"51":2}}],["inside",{"2":{"39":1,"98":1,"101":1,"248":1,"699":1}}],["instincts",{"2":{"219":1}}],["instructionexecution",{"2":{"577":1}}],["instructionexecutionfail",{"0":{"419":1},"2":{"577":1}}],["instructionexecutionerror",{"0":{"418":1},"2":{"606":1}}],["instructionevaluationerror",{"0":{"417":1},"2":{"418":1}}],["instructiontype",{"0":{"420":1},"2":{"417":1,"517":1}}],["instructionbox>",{"2":{"219":1}}],["instructionbox",{"0":{"416":1,"610":1},"2":{"219":1,"353":1,"419":1,"610":1}}],["instructionfailed",{"2":{"193":1,"606":1}}],["instruction",{"0":{"162":1,"650":1},"2":{"35":1,"36":2,"40":2,"41":5,"45":1,"48":1,"52":2,"56":2,"59":2,"62":1,"65":1,"71":1,"72":2,"76":1,"78":1,"90":1,"94":1,"96":1,"97":2,"98":1,"104":2,"111":1,"121":1,"128":1,"136":1,"141":2,"162":2,"176":3,"177":3,"178":4,"179":2,"181":2,"188":2,"211":1,"212":3,"215":1,"219":2,"220":1,"221":2,"222":1,"223":2,"273":1,"419":1,"517":1,"574":1,"626":1,"642":1,"661":1}}],["instructions",{"0":{"27":1,"40":1,"49":1,"646":1,"647":1,"648":1,"649":1,"661":1},"1":{"41":1,"42":1,"43":1,"44":1,"45":1,"46":1,"47":1,"48":1,"49":1,"647":1,"648":1,"649":1,"650":1},"2":{"13":1,"16":4,"28":1,"36":1,"39":5,"40":7,"41":3,"42":1,"44":1,"45":2,"46":1,"47":1,"49":5,"52":1,"62":1,"71":2,"97":2,"98":2,"100":2,"101":1,"104":1,"121":1,"128":1,"129":1,"136":1,"141":3,"165":1,"167":1,"176":1,"181":2,"185":1,"192":1,"200":1,"219":2,"224":1,"226":1,"233":2,"246":1,"262":1,"264":1,"265":2,"285":1,"353":1,"575":1,"626":4,"637":1,"641":1,"647":2,"648":2,"649":1,"650":3,"661":3}}],["instead",{"2":{"16":2,"17":1,"65":1,"87":1,"88":1,"90":1,"106":1,"107":1,"136":1,"137":3,"177":1,"185":1,"186":1,"212":1,"213":1,"215":1,"217":2,"220":1,"221":1,"224":1,"243":1,"252":1,"253":1}}],["instantaneous",{"2":{"287":1}}],["instantiation",{"2":{"273":1}}],["instantiate",{"2":{"162":1,"187":1,"218":2}}],["instances",{"2":{"137":3,"219":1,"684":1}}],["instance",{"0":{"95":1},"2":{"10":1,"12":1,"18":1,"95":1,"154":1,"166":1,"174":1,"176":1,"195":1,"199":1,"202":1,"218":1,"220":2,"223":1,"249":1,"272":1,"628":1,"650":1,"656":1}}],["installations",{"2":{"257":1,"280":1}}],["installation",{"0":{"174":1,"277":1,"280":1},"1":{"278":1,"279":1,"280":1,"281":1,"282":1,"283":1},"2":{"170":1,"174":2,"217":1,"277":1,"285":1}}],["installing",{"0":{"242":1},"2":{"157":1,"174":2,"238":1}}],["install",{"0":{"169":1,"172":1},"1":{"170":1,"171":1,"172":1},"2":{"3":1,"5":5,"17":1,"166":3,"169":1,"170":6,"172":4,"174":4,"195":1,"210":4,"227":1,"243":1,"249":2,"282":1,"283":2}}],["installed",{"2":{"3":1,"248":1,"249":3,"280":1,"281":1,"282":3,"283":1}}],["initiate",{"2":{"719":1,"729":1}}],["initiated",{"2":{"255":1}}],["initialize",{"2":{"175":1}}],["initialized",{"2":{"127":1,"196":4,"272":1}}],["initialise",{"2":{"221":1}}],["initialised",{"2":{"174":1}}],["initialisation",{"2":{"6":1}}],["initially",{"2":{"100":1}}],["initial",{"2":{"20":2,"21":3,"22":1,"24":1,"217":1,"633":1}}],["init",{"2":{"18":4,"143":1,"174":1,"181":2,"196":6}}],["introduction",{"0":{"225":1},"1":{"226":1,"227":1,"228":1},"2":{"229":1,"246":1}}],["introduced",{"2":{"238":1}}],["introduce",{"2":{"224":1,"226":1}}],["intuitive",{"2":{"212":1}}],["int",{"2":{"190":1,"191":1,"334":1,"335":1,"621":1,"622":1,"623":1,"624":1,"625":1}}],["int>",{"2":{"186":1}}],["intentional",{"2":{"221":1}}],["intended",{"2":{"255":1,"259":1,"285":1}}],["intend",{"2":{"14":1,"97":2}}],["integrity",{"2":{"245":1}}],["integration",{"0":{"284":1},"2":{"181":1,"265":1,"284":1,"285":1}}],["integers",{"2":{"50":1,"178":1,"749":1}}],["integer",{"2":{"25":2,"84":1,"214":2}}],["intellectual",{"2":{"165":1}}],["interoperate",{"2":{"643":1}}],["interchangeable",{"2":{"630":1}}],["intercept",{"2":{"266":1}}],["interval",{"2":{"568":2}}],["interdependent",{"2":{"231":1}}],["interior",{"2":{"218":1}}],["interim",{"2":{"100":1}}],["interruptedexception",{"2":{"193":1}}],["interpreter",{"2":{"215":1}}],["interpret",{"2":{"181":1}}],["interface",{"2":{"175":2,"181":1,"656":2}}],["interfaces",{"0":{"655":1},"1":{"656":1,"657":1,"658":1,"659":1},"2":{"103":1}}],["interacting",{"2":{"714":1}}],["interactions",{"2":{"71":1,"233":1,"257":1,"714":1}}],["interaction",{"2":{"39":1,"187":1}}],["interact",{"2":{"175":1,"186":1,"196":1,"200":2,"226":1,"263":1}}],["interesting",{"2":{"99":1}}],["interested",{"2":{"87":1}}],["interest",{"2":{"65":1,"229":1,"279":1,"631":1}}],["internalerror",{"2":{"606":1}}],["internally",{"2":{"268":1}}],["internal",{"2":{"18":1,"149":1,"176":1,"214":1,"218":1,"282":1}}],["intermediary",{"2":{"13":1}}],["into",{"0":{"242":1},"2":{"3":1,"4":2,"13":1,"16":2,"17":3,"20":1,"28":1,"39":1,"53":2,"61":2,"71":3,"81":1,"92":4,"93":1,"100":1,"104":2,"107":1,"138":1,"174":2,"175":1,"178":1,"188":1,"210":2,"218":2,"219":4,"222":1,"226":1,"238":1,"242":1,"246":2,"251":1,"261":1,"273":1,"282":1,"655":1,"658":4,"723":1,"725":1}}],["increasing",{"2":{"252":1}}],["increases",{"2":{"105":1,"106":1}}],["increase",{"2":{"98":1,"252":1}}],["incidents",{"2":{"250":1}}],["incident",{"2":{"246":1,"250":1}}],["inclined",{"2":{"186":1}}],["including",{"2":{"4":1,"71":1,"97":1,"135":1,"137":1,"167":2,"231":1,"246":1,"248":1,"252":1,"253":1,"268":1,"269":1,"660":1}}],["includes",{"2":{"86":1,"112":1,"235":1,"247":1,"653":1}}],["included",{"2":{"4":1,"149":1,"260":1}}],["include",{"2":{"4":1,"5":1,"42":1,"235":1,"249":1,"648":1,"655":1,"663":1,"682":1,"714":1}}],["incorrectly",{"2":{"272":1,"705":1}}],["incorrect",{"2":{"135":1,"221":1,"741":1}}],["incomplete",{"2":{"141":1}}],["incompatibility",{"2":{"6":1}}],["incoming",{"2":{"118":1,"119":1,"147":1,"637":2,"714":1}}],["input",{"2":{"4":1,"5":1,"109":1,"181":1,"239":7,"263":1,"666":1,"699":1}}],["in",{"0":{"4":1,"6":1,"167":1,"181":1,"193":1},"1":{"7":1,"8":1,"9":1,"182":1},"2":{"0":2,"2":2,"3":1,"4":1,"5":6,"6":3,"12":10,"13":2,"14":7,"16":4,"18":6,"20":3,"21":6,"22":4,"24":1,"25":3,"27":1,"28":6,"29":5,"32":1,"33":1,"36":1,"37":1,"38":1,"39":6,"40":1,"41":1,"42":9,"43":2,"46":1,"49":3,"50":2,"51":2,"52":1,"55":3,"56":3,"57":5,"58":1,"60":1,"62":2,"63":3,"67":2,"71":4,"72":1,"78":2,"80":1,"81":1,"82":1,"83":1,"85":1,"86":1,"87":2,"88":3,"89":3,"92":1,"94":4,"96":1,"97":9,"98":1,"99":4,"100":3,"101":2,"102":1,"103":2,"104":3,"105":4,"106":5,"108":1,"112":1,"116":2,"118":1,"119":1,"120":1,"121":1,"122":1,"124":5,"125":7,"126":4,"127":4,"128":6,"130":4,"131":1,"132":1,"134":3,"135":4,"136":1,"137":11,"138":3,"139":2,"141":10,"143":6,"146":3,"147":1,"148":1,"149":1,"150":1,"154":2,"157":1,"158":2,"159":1,"160":3,"161":1,"163":1,"166":1,"170":1,"171":1,"174":7,"175":10,"176":2,"177":3,"178":6,"179":1,"181":7,"183":2,"185":3,"186":1,"187":6,"188":2,"189":3,"190":1,"191":1,"192":2,"196":2,"197":1,"198":1,"200":6,"201":5,"202":2,"203":8,"208":1,"210":4,"211":6,"212":7,"213":1,"214":4,"215":3,"217":7,"218":6,"219":3,"220":3,"221":4,"224":5,"226":2,"227":1,"228":1,"229":3,"230":2,"231":2,"233":5,"234":1,"235":2,"236":2,"237":3,"238":7,"241":2,"243":1,"244":1,"245":1,"246":2,"247":2,"248":3,"249":6,"250":4,"251":1,"252":5,"253":7,"255":1,"256":3,"258":3,"259":1,"260":2,"263":2,"264":1,"265":6,"266":3,"268":3,"269":1,"270":2,"271":1,"272":4,"273":5,"278":1,"279":1,"280":1,"282":3,"283":1,"286":2,"287":2,"627":1,"628":2,"629":1,"630":2,"631":1,"634":1,"641":1,"643":2,"649":1,"650":2,"652":1,"653":1,"654":2,"655":1,"656":7,"658":4,"659":6,"660":2,"661":1,"662":2,"663":3,"665":1,"666":4,"667":2,"668":1,"669":1,"672":5,"675":1,"676":1,"679":1,"684":1,"689":1,"692":1,"693":1,"696":1,"697":1,"699":1,"702":1,"703":2,"705":2,"706":1,"712":1,"714":3,"725":1,"728":2,"735":2,"741":2,"748":1,"749":8,"750":1}}],["r3",{"2":{"236":1}}],["risking",{"2":{"254":1}}],["risk",{"2":{"247":2,"248":1,"260":1,"267":1}}],["risks",{"2":{"230":1,"248":1,"250":1}}],["rights",{"2":{"203":2,"249":1}}],["right",{"2":{"13":2,"16":1,"20":1,"21":1,"87":1,"273":1,"279":2}}],["r",{"2":{"218":1}}],["rc",{"2":{"173":1,"196":1,"217":4,"244":1}}],["rtx",{"2":{"253":4}}],["rtgs",{"0":{"236":1},"2":{"236":1}}],["rt",{"2":{"53":1}}],["rarity",{"2":{"631":1}}],["raise",{"2":{"273":1}}],["raised",{"2":{"187":1,"253":1}}],["rabbit",{"2":{"177":5,"178":2,"213":5,"214":1,"220":7,"221":3,"224":1,"282":1}}],["randomly",{"2":{"654":1}}],["randomness",{"2":{"238":1,"252":1}}],["random",{"2":{"238":1,"256":1}}],["randomise",{"2":{"148":1}}],["range",{"2":{"238":1,"252":1,"631":1}}],["ran",{"2":{"138":1,"282":1}}],["ram",{"2":{"106":1}}],["rather",{"2":{"46":1,"90":1,"250":1,"254":1,"273":1,"656":1,"684":1}}],["raw",{"2":{"2":1,"5":4,"176":1,"177":1,"178":3,"179":2,"181":1,"272":2,"405":1,"656":2}}],["rudimentary",{"2":{"233":1}}],["rules",{"2":{"259":1}}],["rule",{"2":{"42":2,"221":1,"286":1}}],["rustpub",{"2":{"657":1,"705":1,"707":1}}],["rustup",{"2":{"279":1,"280":4,"281":1,"282":7}}],["rustuse",{"2":{"94":1,"218":1,"224":1}}],["rustc",{"2":{"279":3,"280":1,"282":3}}],["rustfor",{"2":{"224":1}}],["rustimpl",{"2":{"659":1}}],["rustiroha",{"2":{"219":2,"223":1}}],["rustinstruction",{"2":{"96":1}}],["rustenum",{"2":{"77":1}}],["ruststruct",{"2":{"73":1,"75":1,"749":1}}],["rustlet",{"2":{"60":1,"61":1,"66":2,"67":1,"71":1,"92":1,"93":1,"94":2,"95":2,"220":2,"222":4}}],["rust",{"0":{"102":1,"216":1,"278":1,"279":1,"281":1,"282":1},"1":{"103":1,"104":1,"217":1,"218":1,"219":1,"220":1,"221":1,"222":1,"223":1,"224":1,"279":1,"280":1,"281":1,"282":1},"2":{"27":1,"29":1,"42":1,"43":2,"44":1,"52":1,"53":1,"57":1,"92":1,"97":1,"101":1,"102":1,"103":2,"104":1,"106":2,"107":1,"108":1,"136":1,"166":1,"170":1,"176":1,"181":1,"187":1,"188":1,"192":1,"210":1,"212":3,"214":1,"215":1,"217":5,"218":1,"219":1,"224":1,"227":1,"229":1,"231":1,"278":1,"281":1,"282":2,"635":1,"656":2,"657":1,"658":6,"664":1,"666":2,"741":1,"746":1}}],["runs",{"2":{"196":1,"204":1,"628":1}}],["runblocking",{"2":{"187":3}}],["runtimeexception",{"2":{"190":1}}],["runtime",{"0":{"63":1},"2":{"53":1,"63":3,"101":1,"111":1,"174":1,"232":1}}],["running",{"2":{"12":1,"13":1,"16":1,"18":1,"22":1,"162":1,"196":2,"207":1,"230":1,"234":1,"244":4,"253":1,"264":1,"272":1,"282":1,"650":1,"703":1,"717":1}}],["run",{"0":{"18":1},"2":{"0":1,"6":1,"13":2,"14":3,"16":4,"18":2,"20":1,"21":3,"22":1,"39":1,"41":1,"88":5,"89":1,"100":1,"104":3,"134":2,"141":1,"174":2,"181":3,"196":1,"200":4,"201":2,"202":3,"203":1,"204":2,"207":2,"232":1,"238":2,"239":4,"241":2,"243":1,"279":1,"280":1,"281":1,"282":2,"283":1,"637":1,"641":1}}],["rfc",{"2":{"12":1,"725":1}}],["rm",{"2":{"7":1}}],["rotation",{"2":{"638":2}}],["roadmap",{"2":{"250":1}}],["rogue",{"2":{"249":1}}],["roses",{"2":{"214":2,"221":4,"223":3}}],["rose",{"2":{"128":3,"164":2,"180":1,"189":1,"190":1,"204":1,"214":1,"663":2}}],["routing",{"0":{"750":1},"1":{"752":1,"753":1}}],["routine",{"2":{"245":1,"248":1,"260":1}}],["routed",{"2":{"750":1}}],["route",{"2":{"637":1}}],["round",{"2":{"88":1,"97":1,"128":2,"175":1,"221":1,"728":1,"735":1,"749":1}}],["roughly",{"2":{"73":1,"181":1}}],["rolepermissionchanged",{"0":{"527":1},"2":{"523":2}}],["rolepermissiontoken",{"2":{"409":1,"521":1}}],["roleeventset",{"0":{"525":1},"2":{"524":1}}],["roleeventfilter",{"0":{"524":1},"2":{"341":1}}],["roleevent",{"0":{"523":1},"2":{"340":1}}],["rolegranted",{"2":{"290":1,"292":1}}],["rolerevoked",{"2":{"290":1,"292":1}}],["role=observingpeer",{"2":{"196":3}}],["role=validatingpeer",{"2":{"196":3}}],["role=proxytail",{"2":{"196":3}}],["role=leader",{"2":{"196":4}}],["roleid",{"0":{"408":1,"474":1,"520":1,"526":1},"2":{"60":1,"296":1,"393":1,"396":1,"407":1,"408":1,"409":1,"414":2,"474":1,"519":1,"520":1,"521":1,"522":1,"523":1,"524":1,"527":1,"602":1,"670":1,"671":1}}],["role",{"0":{"60":1,"61":1,"407":1,"507":1,"519":1,"522":1,"602":1,"667":1},"1":{"668":1,"669":1,"670":1,"671":1},"2":{"41":1,"45":1,"53":22,"56":1,"59":3,"60":8,"61":5,"71":6,"128":1,"132":1,"160":2,"164":1,"237":1,"246":1,"260":1,"296":1,"340":1,"341":1,"393":1,"409":2,"415":2,"453":1,"509":2,"521":2,"523":1,"527":1,"604":2,"670":3,"671":1}}],["roles",{"0":{"59":1},"1":{"60":1,"61":1},"2":{"29":1,"33":1,"41":3,"42":1,"45":2,"53":1,"56":1,"59":1,"64":2,"111":2,"128":1,"129":1,"160":2,"260":1,"662":1,"667":1,"668":2,"669":2,"670":1,"671":1}}],["root",{"2":{"6":1,"134":1,"196":1,"238":1,"243":1}}],["robust",{"2":{"0":1,"232":1,"238":1,"259":1,"656":1,"658":2}}],["rs`",{"2":{"664":1}}],["rsiroha",{"2":{"221":1}}],["rsuse",{"2":{"219":1,"220":1}}],["rslet",{"2":{"218":1,"221":1}}],["rsprintln",{"2":{"4":1}}],["rsfn",{"2":{"4":1}}],["rs",{"2":{"2":1,"4":2,"104":1,"217":1,"218":2,"219":4,"221":3,"223":1}}],["reuse",{"2":{"259":1}}],["reinstate",{"2":{"250":1}}],["reinvent",{"2":{"101":1}}],["rewrite",{"2":{"229":1}}],["regulations",{"2":{"260":1}}],["regularly",{"2":{"260":2}}],["regular",{"2":{"243":1,"248":1,"253":1,"258":1,"260":1}}],["regarding",{"2":{"628":1}}],["regard",{"2":{"256":1}}],["regardless",{"2":{"221":1,"225":1,"282":1}}],["registry=https",{"2":{"174":1}}],["registry",{"2":{"174":4}}],["registration",{"2":{"42":1,"43":1,"57":1,"69":1,"188":1,"201":1,"202":2,"219":1,"221":2}}],["registrable",{"2":{"42":2}}],["registerassettx",{"2":{"193":6}}],["registerasset",{"2":{"189":3,"190":1}}],["registerassetdefinition",{"2":{"189":3,"193":3}}],["registeraccount",{"2":{"188":3,"190":1,"193":1}}],["registeraccountinstructioncommitted",{"2":{"193":1}}],["registeraccountinstruction",{"2":{"177":1}}],["registerdomaininstructioncommitted",{"2":{"193":1}}],["registerdomain",{"2":{"174":1,"176":2,"181":2,"187":3,"193":1}}],["registers",{"2":{"160":1}}],["registerbox",{"0":{"509":1},"2":{"52":1,"53":2,"60":1,"72":1,"92":4,"96":1,"104":1,"176":4,"177":2,"178":2,"181":2,"219":4,"220":1,"416":1}}],["registering",{"0":{"141":1,"159":1,"176":1,"177":1,"178":1,"187":1,"188":1,"189":1,"212":1,"213":1,"214":1,"219":1,"220":1,"221":1},"1":{"160":1,"161":1,"162":1},"2":{"27":1,"29":1,"41":1,"42":6,"52":1,"53":2,"128":1,"129":1,"141":7,"160":3,"166":2,"177":2,"187":1,"188":2,"189":1,"213":2,"219":1,"220":2}}],["registered",{"2":{"25":1,"27":1,"36":2,"41":1,"42":4,"43":1,"57":1,"59":1,"61":1,"69":1,"72":1,"78":1,"84":1,"86":1,"97":3,"111":5,"116":1,"128":1,"129":1,"141":1,"146":2,"159":1,"175":1,"177":1,"187":2,"188":1,"190":1,"203":2,"204":2,"221":2,"256":1,"646":1,"668":1,"669":1,"673":1,"676":1,"679":1,"689":1,"699":1,"700":1,"735":1}}],["register",{"0":{"42":1,"60":1,"92":1,"93":1,"136":1,"201":1,"202":1,"204":1,"502":1,"503":1,"504":1,"505":1,"506":1,"507":1,"508":1},"2":{"22":1,"29":6,"39":1,"40":2,"41":9,"42":8,"52":1,"53":6,"60":2,"72":2,"78":1,"81":1,"83":1,"84":1,"85":1,"93":1,"96":1,"98":1,"104":1,"111":1,"128":8,"129":1,"136":2,"141":4,"146":1,"162":2,"164":8,"176":5,"177":2,"178":2,"181":2,"187":1,"188":2,"189":1,"190":1,"201":3,"202":3,"204":2,"212":6,"213":4,"219":4,"220":1,"221":4,"227":2,"256":2,"416":1,"420":1,"509":7,"661":1,"663":1}}],["region",{"2":{"4":2}}],["redeploy",{"2":{"663":1}}],["reducing",{"2":{"253":1,"644":1}}],["reduced",{"2":{"94":1}}],["reduces",{"2":{"93":1,"94":1,"105":1}}],["reduce",{"2":{"5":1,"67":1,"105":2,"107":1,"109":1,"110":1,"137":1,"655":1,"684":1}}],["redundancy",{"2":{"250":1}}],["redacted",{"2":{"161":1}}],["rendering",{"2":{"137":1}}],["reflected",{"2":{"627":1}}],["reflect",{"2":{"228":1,"260":1}}],["reflects",{"2":{"221":1}}],["ref",{"2":{"181":2}}],["refresh",{"2":{"93":1}}],["refers",{"2":{"44":1}}],["refer",{"2":{"13":1,"27":1,"36":1,"41":1,"42":1,"43":2,"44":1,"139":1,"140":1,"141":1,"143":1,"174":1,"181":1,"628":1,"662":1}}],["reference",{"0":{"70":1},"2":{"11":1,"12":3,"58":1,"125":1,"143":1,"181":1,"188":1,"256":1,"265":2,"666":1,"725":3}}],["requiring",{"2":{"243":1,"259":1}}],["requirement",{"2":{"203":1,"243":1}}],["requirements",{"2":{"175":4,"183":2}}],["requires",{"2":{"137":1,"256":1,"269":1,"656":1,"715":1,"734":1,"744":1,"747":1}}],["required",{"2":{"62":1,"65":1,"143":2,"151":1,"252":2,"265":1,"266":1,"268":1}}],["require",{"2":{"41":1,"52":1,"63":1,"265":1,"266":1}}],["requested",{"2":{"177":1,"213":1,"220":1,"715":1,"717":1}}],["requestwithquerybox",{"2":{"176":1,"180":3}}],["requests",{"0":{"716":1,"722":1,"725":1,"732":1,"737":1,"740":1,"745":1,"748":1,"752":1},"2":{"18":1,"148":1,"174":1,"181":1,"259":1,"714":1,"740":1}}],["request",{"2":{"12":1,"50":1,"53":2,"67":2,"120":2,"150":2,"161":1,"175":2,"176":1,"183":2,"221":1,"238":1,"270":1,"637":1,"643":1,"651":1,"716":1,"717":1,"720":1,"722":1,"726":2,"730":1,"732":1,"733":1,"737":1,"740":1,"741":3,"745":1,"748":2,"749":1}}],["rejection",{"2":{"32":1,"707":1}}],["rejectedtransaction",{"2":{"707":1}}],["rejected",{"2":{"32":2,"71":1,"98":1,"181":2,"192":1,"215":1,"219":1,"327":1,"578":1,"707":1,"728":4,"735":1,"749":3,"750":1,"753":4}}],["remotely",{"2":{"263":1}}],["remote",{"2":{"263":6}}],["removable",{"2":{"249":1}}],["removes",{"2":{"105":1}}],["removed",{"2":{"45":1,"51":2,"56":1,"137":1,"249":1,"264":1,"266":1,"311":1,"313":1,"487":1,"489":1}}],["removekeyvaluebox",{"0":{"515":1},"2":{"416":1}}],["removekeyvalue",{"0":{"46":1,"510":1,"511":1,"512":1,"513":1,"514":1},"2":{"40":1,"41":1,"52":1,"416":1,"420":1,"515":5,"661":1}}],["remove",{"0":{"106":1},"2":{"6":1,"7":1,"39":1,"40":1,"55":1,"98":1,"105":1,"108":1,"110":1,"128":1,"163":1,"232":2,"249":1,"265":1,"282":3,"661":1,"663":6}}],["remain",{"2":{"251":1,"266":1,"267":1,"272":1}}],["remains",{"2":{"249":1,"250":1,"254":1,"261":1}}],["remaining",{"2":{"20":1,"98":1,"234":1}}],["remembering",{"2":{"269":1}}],["remembers",{"2":{"263":1}}],["remember",{"2":{"20":1,"177":1,"212":1,"213":1,"215":1,"220":1,"249":1,"250":1,"679":1}}],["reach",{"2":{"253":1}}],["reaches",{"2":{"84":2,"163":1}}],["react",{"2":{"250":1}}],["reasonable",{"2":{"268":1}}],["reasons",{"2":{"42":1,"154":1,"163":1}}],["reasoning",{"2":{"28":1}}],["reason",{"2":{"28":2,"32":1,"62":1,"79":1,"88":1,"97":1,"148":1,"155":1,"175":1,"181":1,"231":1,"272":1,"419":1,"573":1,"618":1,"707":1}}],["readily",{"2":{"666":2}}],["readiness",{"2":{"250":1}}],["reading",{"2":{"125":1}}],["readers",{"2":{"287":1}}],["reader",{"2":{"224":1}}],["reads",{"2":{"186":1}}],["readable",{"2":{"150":1,"201":1}}],["read",{"2":{"16":1,"39":1,"40":1,"143":1,"171":1,"211":1,"227":1,"253":1,"268":1,"651":1}}],["ready",{"2":{"16":2,"34":1,"186":1,"265":1}}],["realm",{"2":{"237":1,"251":1}}],["really",{"2":{"18":1,"88":1,"89":1,"253":1}}],["real",{"0":{"22":1},"2":{"0":1,"4":1,"16":1,"22":1,"88":1,"171":1,"261":1}}],["re",{"0":{"108":1},"2":{"16":2,"39":2,"79":1,"88":2,"90":1,"108":2,"120":1,"132":1,"137":2,"150":1,"175":1,"200":1,"218":1,"219":1,"222":4,"244":1,"256":1,"263":1,"279":1,"282":1,"667":1}}],["retrieved",{"2":{"287":1,"717":1,"748":3}}],["retrieve",{"0":{"721":1},"1":{"722":1,"723":1},"2":{"238":1,"726":1,"750":1}}],["retrying",{"2":{"151":1}}],["retry",{"2":{"143":2,"151":2}}],["retain",{"2":{"97":1,"224":1}}],["retains",{"2":{"14":1}}],["returned",{"2":{"723":1,"740":1,"750":1}}],["return",{"2":{"63":1,"67":2,"68":1,"181":4,"190":1,"219":1,"666":2,"669":1,"670":1,"671":1,"726":1}}],["returns",{"2":{"12":1,"62":1,"72":1,"221":1,"666":4,"668":2,"669":2,"670":2,"671":2,"673":1,"674":2,"676":1,"677":2,"678":2,"679":2,"680":3,"681":2,"683":2,"684":2,"685":2,"686":1,"687":2,"688":1,"689":2,"690":1,"691":2,"692":1,"693":1,"694":1,"696":2,"697":2,"698":1,"700":3,"701":1,"702":2,"704":2,"705":2,"707":2,"708":2,"710":1,"711":1,"712":1,"713":1,"717":1,"723":1,"733":1,"735":1,"738":1,"741":1,"746":1,"749":1}}],["reset",{"2":{"272":1}}],["research",{"2":{"268":1}}],["researching",{"2":{"259":1}}],["reserved",{"2":{"74":1,"261":1,"660":5}}],["resilient",{"2":{"238":1}}],["resident",{"2":{"186":1}}],["resistant",{"2":{"18":1}}],["resource",{"2":{"238":1}}],["resources",{"2":{"137":1,"258":1,"259":1,"260":1,"628":1}}],["resolve",{"2":{"6":1}}],["respond",{"2":{"79":1,"250":1,"263":1,"728":2}}],["responsible",{"2":{"78":1,"119":1,"160":1,"636":1,"714":1}}],["responsibility",{"2":{"63":1,"160":1,"211":1}}],["responses",{"0":{"717":1,"723":1,"726":1,"733":1,"735":1,"738":1,"741":1,"746":1,"749":1,"753":1},"2":{"246":1}}],["response",{"2":{"65":1,"250":1,"263":2,"268":2,"287":1,"717":1,"723":1,"726":1,"730":1,"733":1,"735":2,"738":1,"740":1,"741":2,"746":1,"749":2,"753":1}}],["respectively",{"2":{"279":1,"666":1}}],["respective",{"2":{"17":1,"174":1}}],["restore",{"2":{"272":1}}],["restored",{"2":{"272":1}}],["restricted",{"2":{"260":1}}],["restrict",{"2":{"137":1,"141":1,"249":1,"260":1}}],["restriction",{"2":{"221":2}}],["restrictions",{"2":{"42":1,"137":1}}],["restricting",{"2":{"89":1}}],["rest",{"2":{"92":1,"221":1,"247":1}}],["restarting",{"2":{"7":1,"8":1,"9":1}}],["restarted",{"2":{"6":1}}],["restart",{"2":{"6":3,"7":1,"8":1,"9":2,"128":2}}],["resulting",{"2":{"252":1}}],["results",{"0":{"266":1},"2":{"50":1,"65":1,"68":1,"69":1,"104":1,"125":1,"137":1,"176":1,"282":1,"665":1,"741":1}}],["result",{"2":{"12":1,"14":1,"53":1,"67":3,"127":1,"135":1,"175":1,"176":4,"178":1,"180":9,"189":1,"190":1,"200":2,"201":1,"202":1,"203":1,"204":1,"207":1,"214":1,"238":1,"286":1}}],["recurring",{"2":{"260":1}}],["recipients",{"2":{"664":1}}],["recipient",{"2":{"255":1,"664":2}}],["recipes",{"2":{"5":3}}],["receipt",{"2":{"705":1}}],["receiving",{"2":{"218":1}}],["receive",{"0":{"270":1},"2":{"56":1,"202":1,"637":1,"683":1,"725":1,"728":1}}],["received",{"2":{"46":1,"259":2}}],["recent",{"2":{"189":1,"720":1}}],["recreating",{"2":{"181":1}}],["reconnect",{"2":{"268":1}}],["recognize",{"2":{"260":1}}],["recognise",{"2":{"259":1}}],["recovery",{"0":{"250":1},"2":{"250":4,"253":1}}],["records",{"2":{"627":2}}],["record",{"2":{"137":4,"249":2,"627":1,"644":1}}],["recorded",{"2":{"39":1,"106":1}}],["recommendations",{"2":{"252":2,"325":1}}],["recommended",{"0":{"248":1},"2":{"16":1,"17":1,"82":1,"226":1,"264":1,"283":1,"650":1}}],["recommend",{"2":{"10":1,"16":1,"67":1,"101":1,"174":2,"176":1,"217":3,"264":1,"286":1}}],["recommited",{"2":{"7":1,"128":1}}],["recommit",{"0":{"7":1},"2":{"6":1,"7":1,"128":1}}],["recall",{"2":{"36":1,"679":1}}],["reputation",{"0":{"644":1},"1":{"647":1},"2":{"626":1,"644":1}}],["reputable",{"2":{"249":1}}],["reporting",{"2":{"749":1}}],["reported",{"2":{"250":1}}],["report",{"2":{"250":1,"260":1,"283":1,"735":1,"749":1}}],["repo",{"2":{"199":1}}],["repository",{"2":{"2":1,"166":1,"171":1,"174":3,"185":1,"196":1,"210":2,"714":1}}],["repositories",{"2":{"0":1,"5":1,"185":2}}],["repairs",{"2":{"137":1}}],["repetitive",{"2":{"263":1}}],["repetitionerror",{"0":{"517":1},"2":{"418":1}}],["repetition",{"0":{"84":1},"2":{"77":1,"81":1,"418":1}}],["repetitions",{"2":{"5":1,"41":2,"43":1,"84":2,"98":1}}],["repeatedly",{"2":{"123":1}}],["repeated",{"2":{"84":2}}],["repeat",{"2":{"84":1,"98":2}}],["repeats",{"0":{"77":1,"516":1},"2":{"75":2,"77":2,"88":1,"93":2,"95":1,"297":2}}],["reprc",{"2":{"658":6}}],["represent",{"2":{"749":1}}],["represented",{"2":{"287":1,"656":1,"657":1}}],["represents",{"2":{"251":1,"287":1,"658":1}}],["representation",{"2":{"42":1,"112":1,"120":1,"134":1,"150":1,"273":1,"629":1,"653":1}}],["reproducible",{"2":{"234":1,"248":1}}],["reproduced",{"2":{"28":1}}],["reproduce",{"2":{"28":2}}],["repr",{"2":{"103":1,"292":1,"307":1,"313":1,"338":1,"345":1,"361":1,"489":1,"525":1,"592":1,"656":1,"658":1}}],["replacing",{"2":{"18":1,"250":1}}],["replaced",{"2":{"63":1,"103":1,"137":1}}],["replace",{"2":{"16":2,"18":1,"20":1,"21":1,"185":1,"219":1}}],["replicate",{"2":{"13":1,"106":1}}],["revolves",{"2":{"656":1}}],["revokebox",{"0":{"521":1},"2":{"416":1}}],["revoked",{"2":{"59":1,"650":1,"654":1}}],["revoke",{"0":{"45":1,"518":1,"519":1,"520":1},"2":{"40":1,"41":3,"45":2,"56":1,"59":1,"416":1,"420":1,"521":3,"661":1,"664":1}}],["reviewed",{"2":{"260":2}}],["review",{"2":{"250":1}}],["revisions",{"2":{"5":2}}],["reverse",{"2":{"117":1}}],["rev",{"2":{"5":4}}],["relevant",{"2":{"250":1}}],["releases",{"2":{"99":1,"272":1}}],["release",{"2":{"6":2,"14":4,"16":2,"22":3,"104":1,"105":1,"106":1,"134":1,"175":1,"185":1,"217":1,"228":1,"238":1,"256":1}}],["rely",{"2":{"175":1}}],["reliable",{"2":{"235":1}}],["reliability",{"2":{"97":1}}],["relies",{"2":{"103":1}}],["relatable",{"2":{"260":1}}],["relationship",{"2":{"29":3}}],["relatively",{"2":{"189":1,"219":1}}],["relative",{"2":{"2":1}}],["related",{"2":{"25":1,"33":1,"86":1,"103":1,"107":1,"108":1,"137":2,"187":1,"200":8,"238":1,"249":2,"263":2,"268":1,"626":1,"638":1,"647":1,"649":1,"749":1}}],["reloading",{"2":{"6":1}}],["reload",{"0":{"6":1},"1":{"7":1,"8":1,"9":1},"2":{"6":1,"244":2}}],["reloaded",{"2":{"3":1}}],["mnemonic",{"0":{"269":1},"2":{"269":2}}],["mv",{"2":{"242":1,"243":1}}],["m",{"2":{"130":2,"283":1}}],["ml",{"2":{"128":5,"164":5}}],["msg",{"2":{"429":1}}],["ms",{"2":{"122":2,"151":2,"207":6,"323":2,"575":2,"735":3}}],["myself",{"2":{"221":1}}],["mypy",{"2":{"214":1}}],["my",{"2":{"83":1}}],["mirror",{"2":{"665":1}}],["migration",{"2":{"272":1}}],["might",{"2":{"3":1,"6":1,"65":1,"105":1,"113":1,"120":1,"141":1,"150":1,"164":1,"175":1,"218":2,"219":1,"221":1,"268":1,"272":1,"278":1,"728":2,"749":1}}],["mitnick",{"2":{"253":1}}],["mitigating",{"2":{"260":1}}],["mitigation",{"2":{"247":1}}],["mitigate",{"2":{"250":1}}],["mitigated",{"2":{"217":1,"268":1}}],["mismatch",{"0":{"447":1},"2":{"272":1,"596":1}}],["mistakes",{"2":{"273":1,"658":1}}],["mistake",{"2":{"221":1}}],["missingsegment",{"2":{"438":1}}],["missing",{"2":{"135":1,"287":1}}],["milliseconds",{"2":{"57":1,"122":1}}],["mix",{"2":{"20":1,"21":1}}],["mind",{"2":{"227":1,"235":1,"249":1,"252":2,"660":1}}],["mindful",{"2":{"20":1,"21":1,"82":1,"249":2,"259":1,"666":1}}],["min",{"2":{"143":1,"426":1}}],["minimizing",{"2":{"267":1}}],["minimizes",{"2":{"250":1}}],["minimize",{"2":{"233":1}}],["minimise",{"2":{"174":1,"248":1}}],["minimum",{"2":{"135":1,"151":1,"217":1,"252":1}}],["minimalist",{"0":{"231":1},"2":{"231":1,"249":1}}],["minimal",{"0":{"19":1},"1":{"20":1,"21":1},"2":{"217":1,"717":1}}],["minutes",{"2":{"88":1}}],["minute",{"2":{"88":1}}],["mintunmintable",{"2":{"445":1}}],["mintabilityerror",{"0":{"445":1},"2":{"418":1}}],["mintability",{"2":{"418":1}}],["mintabilitychanged",{"2":{"305":1,"307":1}}],["mintable=false",{"2":{"214":1}}],["mintable",{"0":{"446":1,"632":1,"633":1},"2":{"24":2,"25":2,"43":1,"128":2,"141":1,"164":2,"178":9,"187":1,"189":7,"214":3,"221":4,"304":2,"450":2,"632":1,"633":1,"684":1}}],["mintasset",{"2":{"193":1}}],["mintassettx",{"2":{"193":2}}],["mintassetinstructioncommitted",{"2":{"193":1}}],["mintbox",{"0":{"444":1},"2":{"92":4,"178":2,"221":2,"416":1}}],["mint",{"0":{"43":1,"204":1,"440":1,"441":1,"442":1,"443":1},"2":{"36":1,"40":3,"41":5,"43":1,"44":1,"56":1,"84":1,"98":1,"128":3,"164":2,"178":5,"189":1,"204":3,"214":5,"221":10,"294":2,"416":1,"420":1,"444":2,"661":2,"663":1,"664":2}}],["minting",{"0":{"178":1,"189":1,"214":1,"221":1},"2":{"27":1,"41":1,"43":2,"129":1,"166":1,"179":1,"189":1,"191":1,"204":1,"205":1,"206":1,"221":1,"222":1,"223":1}}],["minted",{"2":{"27":1,"43":2,"190":1,"204":1,"214":2,"221":1}}],["mkdir",{"2":{"17":1,"171":1}}],["merkle",{"0":{"640":1},"2":{"626":1}}],["merkletree",{"0":{"411":1,"431":1,"465":1},"2":{"323":1,"465":1}}],["mere",{"2":{"253":1}}],["merely",{"2":{"29":1,"656":1}}],["memorize",{"2":{"269":1}}],["memory",{"2":{"101":1,"112":1,"137":1,"264":1,"268":1,"653":1}}],["menu",{"2":{"265":4}}],["mentioned",{"2":{"97":1}}],["medieval",{"2":{"627":1}}],["media",{"2":{"259":1,"270":1}}],["medical",{"2":{"137":1}}],["me",{"2":{"249":2}}],["mechanisms",{"2":{"263":1}}],["mechanism",{"2":{"249":1}}],["measure",{"2":{"250":1}}],["measures",{"0":{"248":1},"2":{"167":1,"245":1,"247":2,"249":3,"260":4,"268":1}}],["meantime",{"2":{"217":1}}],["meant",{"2":{"88":1,"89":1,"150":1,"241":1}}],["meanings",{"2":{"666":1}}],["meaningful",{"2":{"125":2}}],["meaning",{"2":{"43":1,"62":1,"116":1,"126":1,"128":1,"176":1,"229":1,"272":1,"666":2}}],["means",{"2":{"16":1,"18":1,"20":1,"21":1,"41":1,"56":1,"84":1,"94":1,"125":1,"126":1,"135":1,"178":2,"214":1,"217":1,"221":1,"230":2,"249":1,"254":1,"256":1,"283":1,"628":1,"663":1,"717":1}}],["mean",{"2":{"6":1,"125":1,"703":1}}],["meanwhile",{"2":{"5":1}}],["messaging",{"2":{"249":1}}],["messages",{"2":{"153":3,"154":1,"218":1,"255":1,"259":3,"270":1,"273":1,"286":1,"714":1,"720":1}}],["message",{"2":{"6":1,"154":1,"183":1,"193":1,"200":1,"201":2,"202":1,"273":1,"362":1,"705":1}}],["messy",{"2":{"16":1,"19":1}}],["met",{"2":{"138":1,"641":1}}],["metric",{"2":{"110":1}}],["metrics",{"0":{"10":1,"11":1,"12":1,"734":1},"1":{"11":1,"12":1,"735":1},"2":{"10":1,"11":1,"12":2,"120":4,"150":4,"232":1,"714":2,"734":1,"735":5}}],["metaphor",{"2":{"39":1}}],["metadatalimits",{"2":{"485":1}}],["metadatavaluebox",{"0":{"439":1,"561":1,"611":1},"2":{"432":1,"433":1,"434":1,"435":1,"436":1,"437":1,"439":1,"499":1,"532":1,"533":1,"534":1,"535":1,"536":1,"561":1,"575":1,"611":1}}],["metadataerror",{"0":{"438":1},"2":{"418":1}}],["metadatakey",{"2":{"393":1}}],["metadata=",{"2":{"214":1}}],["metadataremoved",{"2":{"51":1,"290":1,"292":1,"305":1,"307":1,"311":1,"313":1,"343":1,"345":1,"590":1,"592":1}}],["metadatainserted",{"2":{"51":1,"290":1,"292":1,"305":1,"307":1,"311":1,"313":1,"343":1,"345":1,"590":1,"592":1}}],["metadatachanged",{"0":{"51":1,"433":1,"434":1,"435":1,"436":1,"437":1},"2":{"51":1,"290":2,"305":2,"311":2,"343":2,"590":2}}],["metadata",{"0":{"50":1,"53":1,"80":1,"137":1,"432":1,"582":1},"1":{"51":1,"52":1,"53":1,"54":1,"55":1},"2":{"25":2,"29":1,"40":1,"41":5,"50":5,"51":1,"53":4,"54":1,"57":1,"60":2,"65":1,"69":4,"75":2,"80":3,"93":2,"95":1,"101":1,"128":8,"137":16,"164":8,"176":3,"177":3,"178":3,"181":3,"187":4,"188":3,"189":3,"193":8,"200":3,"201":1,"202":5,"219":5,"289":2,"297":2,"304":2,"315":1,"316":1,"342":2,"418":1,"439":1,"449":2,"450":2,"451":2,"575":1,"582":1,"661":1,"663":8,"678":1,"692":1,"693":1,"712":1}}],["metal",{"0":{"13":1,"18":1},"1":{"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1},"2":{"13":2,"14":1}}],["methodname",{"2":{"659":2}}],["methods",{"2":{"65":1,"134":1,"174":1,"175":3,"231":1,"237":1,"244":1,"247":1,"262":1,"658":2}}],["method",{"2":{"17":1,"175":1,"178":1,"188":2,"189":3,"190":3,"191":2,"211":1,"243":1,"249":1,"253":1,"254":1,"263":1,"268":2,"269":1,"656":1,"659":2,"715":1,"721":1,"724":1,"731":1,"734":1,"736":1,"739":1,"744":1,"747":1,"751":1}}],["month",{"2":{"253":1}}],["monitoring",{"2":{"215":1,"246":1,"259":1,"260":2}}],["monitor",{"2":{"10":2,"37":1,"120":1,"137":1,"150":1,"196":1,"215":1,"266":1,"272":1,"714":1}}],["mozilla",{"2":{"249":1}}],["moving",{"0":{"243":1},"1":{"244":1},"2":{"248":1}}],["move",{"2":{"21":1,"242":1,"243":1}}],["moment",{"2":{"81":1,"675":1}}],["mouse",{"2":{"52":7,"53":16,"60":4,"61":3,"71":3,"179":2}}],["mount",{"2":{"8":1,"181":2}}],["mostly",{"2":{"238":1,"647":1}}],["most",{"2":{"18":2,"42":1,"56":2,"69":1,"100":1,"103":2,"105":1,"136":1,"137":1,"139":2,"148":1,"152":1,"163":1,"170":1,"181":1,"185":1,"192":1,"198":1,"203":1,"210":1,"214":1,"217":1,"219":2,"224":2,"242":1,"243":1,"247":1,"248":2,"268":1,"269":1,"271":1,"286":1,"656":1,"658":1,"672":2,"675":2,"699":1,"720":1}}],["modular",{"2":{"232":1}}],["module",{"2":{"118":1,"119":1,"147":1,"154":1,"186":1,"215":1,"217":1,"232":1,"636":1,"637":1,"659":3,"665":1,"714":2}}],["modules",{"0":{"645":1},"2":{"90":1,"174":2,"626":1,"635":1,"650":1}}],["modern",{"2":{"252":1,"253":2}}],["mode=strict",{"2":{"196":1}}],["modes",{"2":{"167":1}}],["model=",{"2":{"181":1}}],["models",{"2":{"176":1,"249":1}}],["model",{"0":{"29":1,"288":1},"1":{"289":1,"290":1,"291":1,"292":1,"293":1,"294":1,"295":1,"296":1,"297":1,"298":1,"299":1,"300":1,"301":1,"302":1,"303":1,"304":1,"305":1,"306":1,"307":1,"308":1,"309":1,"310":1,"311":1,"312":1,"313":1,"314":1,"315":1,"316":1,"317":1,"318":1,"319":1,"320":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"329":1,"330":1,"331":1,"332":1,"333":1,"334":1,"335":1,"336":1,"337":1,"338":1,"339":1,"340":1,"341":1,"342":1,"343":1,"344":1,"345":1,"346":1,"347":1,"348":1,"349":1,"350":1,"351":1,"352":1,"353":1,"354":1,"355":1,"356":1,"357":1,"358":1,"359":1,"360":1,"361":1,"362":1,"363":1,"364":1,"365":1,"366":1,"367":1,"368":1,"369":1,"370":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"378":1,"379":1,"380":1,"381":1,"382":1,"383":1,"384":1,"385":1,"386":1,"387":1,"388":1,"389":1,"390":1,"391":1,"392":1,"393":1,"394":1,"395":1,"396":1,"397":1,"398":1,"399":1,"400":1,"401":1,"402":1,"403":1,"404":1,"405":1,"406":1,"407":1,"408":1,"409":1,"410":1,"411":1,"412":1,"413":1,"414":1,"415":1,"416":1,"417":1,"418":1,"419":1,"420":1,"421":1,"422":1,"423":1,"424":1,"425":1,"426":1,"427":1,"428":1,"429":1,"430":1,"431":1,"432":1,"433":1,"434":1,"435":1,"436":1,"437":1,"438":1,"439":1,"440":1,"441":1,"442":1,"443":1,"444":1,"445":1,"446":1,"447":1,"448":1,"449":1,"450":1,"451":1,"452":1,"453":1,"454":1,"455":1,"456":1,"457":1,"458":1,"459":1,"460":1,"461":1,"462":1,"463":1,"464":1,"465":1,"466":1,"467":1,"468":1,"469":1,"470":1,"471":1,"472":1,"473":1,"474":1,"475":1,"476":1,"477":1,"478":1,"479":1,"480":1,"481":1,"482":1,"483":1,"484":1,"485":1,"486":1,"487":1,"488":1,"489":1,"490":1,"491":1,"492":1,"493":1,"494":1,"495":1,"496":1,"497":1,"498":1,"499":1,"500":1,"501":1,"502":1,"503":1,"504":1,"505":1,"506":1,"507":1,"508":1,"509":1,"510":1,"511":1,"512":1,"513":1,"514":1,"515":1,"516":1,"517":1,"518":1,"519":1,"520":1,"521":1,"522":1,"523":1,"524":1,"525":1,"526":1,"527":1,"528":1,"529":1,"530":1,"531":1,"532":1,"533":1,"534":1,"535":1,"536":1,"537":1,"538":1,"539":1,"540":1,"541":1,"542":1,"543":1,"544":1,"545":1,"546":1,"547":1,"548":1,"549":1,"550":1,"551":1,"552":1,"553":1,"554":1,"555":1,"556":1,"557":1,"558":1,"559":1,"560":1,"561":1,"562":1,"563":1,"564":1,"565":1,"566":1,"567":1,"568":1,"569":1,"570":1,"571":1,"572":1,"573":1,"574":1,"575":1,"576":1,"577":1,"578":1,"579":1,"580":1,"581":1,"582":1,"583":1,"584":1,"585":1,"586":1,"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"593":1,"594":1,"595":1,"596":1,"597":1,"598":1,"599":1,"600":1,"601":1,"602":1,"603":1,"604":1,"605":1,"606":1,"607":1,"608":1,"609":1,"610":1,"611":1,"612":1,"613":1,"614":1,"615":1,"616":1,"617":1,"618":1,"619":1,"620":1,"621":1,"622":1,"623":1,"624":1,"625":1},"2":{"53":1,"60":1,"99":1,"103":1,"104":1,"173":1,"174":6,"175":3,"176":2,"177":1,"178":2,"179":1,"180":1,"181":4,"185":1,"212":2,"213":2,"214":2,"217":4,"218":1,"219":1,"220":2,"221":1,"224":1,"656":1,"746":1}}],["mode",{"2":{"14":7,"22":1,"106":1,"141":1,"143":2,"187":1,"272":1}}],["modification",{"2":{"709":1}}],["modifications",{"2":{"6":2,"105":1}}],["modified",{"2":{"141":1,"650":1}}],["modifies",{"2":{"53":1}}],["modifying",{"2":{"39":1,"125":1,"650":1,"651":1}}],["modify",{"2":{"9":1,"39":1,"40":1,"203":1}}],["moreover",{"2":{"101":1,"104":1,"221":1,"656":1}}],["more",{"0":{"168":1},"2":{"0":1,"3":1,"13":2,"14":1,"18":1,"21":1,"24":1,"29":2,"36":1,"39":1,"42":1,"57":1,"65":1,"80":1,"81":1,"83":1,"88":1,"89":1,"97":4,"98":1,"99":1,"101":1,"103":1,"104":1,"107":1,"124":1,"132":1,"134":1,"137":1,"139":1,"140":1,"141":1,"143":1,"151":1,"154":2,"160":1,"168":2,"175":2,"176":1,"177":2,"178":3,"188":2,"197":1,"200":1,"202":1,"204":1,"208":1,"211":2,"214":4,"219":1,"220":2,"221":2,"222":1,"226":2,"232":2,"233":1,"238":6,"246":1,"247":1,"252":2,"260":1,"261":1,"263":3,"268":1,"632":1,"640":1,"642":1,"646":1,"651":1,"658":1,"662":1,"666":1,"667":1,"672":1,"714":2,"735":1,"749":1}}],["mut",{"2":{"657":2,"659":1}}],["mutable",{"2":{"218":2,"659":1}}],["multihash",{"0":{"273":1},"2":{"185":1,"202":2,"238":1,"239":5,"256":1}}],["multiformats",{"2":{"185":1}}],["multi",{"2":{"165":1,"200":1,"218":1,"231":1,"253":1,"273":2}}],["multiple",{"2":{"5":1,"62":2,"174":1,"203":1,"212":1,"242":1,"253":1,"287":1,"666":1}}],["mundane",{"2":{"28":1}}],["must",{"2":{"18":1,"88":1,"97":1,"116":1,"121":1,"125":1,"132":1,"135":4,"137":2,"138":1,"159":1,"160":1,"161":1,"174":1,"199":1,"200":1,"204":1,"210":1,"212":1,"214":1,"215":1,"219":1,"238":2,"247":1,"248":1,"256":3,"658":1,"666":1,"699":1,"717":2,"719":1,"720":1,"729":1,"730":1,"738":1}}],["musl",{"2":{"6":4,"241":1}}],["much",{"2":{"14":1,"39":1,"46":1,"65":1,"88":1,"90":1,"97":3,"101":1,"137":1,"141":1,"154":1,"163":1,"203":1,"214":1,"248":1,"273":1}}],["md`",{"2":{"5":1}}],["md",{"2":{"2":2,"4":1,"5":2,"714":2}}],["malware",{"2":{"258":1,"266":1}}],["malformed",{"2":{"211":1,"753":2}}],["malicious",{"2":{"163":1,"230":1,"245":1,"247":1,"252":1,"259":2,"264":1,"268":1,"634":2,"644":1}}],["maven",{"2":{"185":1}}],["mavencentral",{"2":{"185":1}}],["maxcapacity",{"2":{"438":1}}],["maxtransactionsinblock=512",{"2":{"128":1,"164":1}}],["max",{"0":{"153":1},"2":{"121":2,"143":4,"152":1,"153":2,"426":1,"428":1,"574":2,"660":1}}],["maximumfaultypeersamount",{"2":{"705":1}}],["maximum",{"2":{"121":2,"146":1,"252":2,"660":1,"705":3}}],["major",{"2":{"99":1,"138":2}}],["majority",{"2":{"86":1}}],["market",{"2":{"268":1}}],["marking",{"2":{"231":1}}],["mark",{"2":{"219":1}}],["markdown",{"0":{"4":1},"2":{"5":1}}],["march",{"2":{"91":1,"92":5}}],["madhatterasset",{"2":{"189":2,"190":2,"191":3}}],["madhatterkeypair",{"2":{"188":2,"190":1,"191":1}}],["madhatter",{"2":{"188":5,"189":5,"190":12,"191":12}}],["mad",{"2":{"91":1,"92":6,"93":4,"97":1,"104":2,"117":1,"256":4}}],["made",{"2":{"6":1,"28":1,"186":1,"211":1}}],["masks",{"2":{"65":1,"292":1,"307":1,"313":1,"338":1,"345":1,"361":1,"489":1,"525":1,"592":1}}],["making",{"0":{"244":1},"2":{"53":1,"137":1,"214":1,"238":1,"243":1,"247":1,"714":1}}],["makes",{"2":{"14":1,"16":1,"74":1,"88":1,"154":1,"160":1,"163":1,"176":1,"187":1,"217":1,"268":1,"273":1}}],["make",{"2":{"0":1,"6":1,"16":2,"20":1,"21":1,"22":2,"24":1,"97":3,"99":1,"135":1,"137":2,"146":1,"148":1,"175":2,"178":1,"187":1,"197":1,"200":1,"214":3,"217":1,"231":1,"238":1,"242":1,"244":1,"254":1,"256":1,"260":1,"265":1,"268":1,"271":1,"272":1,"279":1,"282":1,"283":1,"649":1,"658":1}}],["matherror",{"0":{"430":1},"2":{"418":1}}],["mathematically",{"2":{"230":2}}],["mathematical",{"2":{"36":1}}],["math",{"2":{"418":1}}],["matrix",{"0":{"287":1},"2":{"287":5}}],["maturin",{"2":{"210":2}}],["matter",{"2":{"157":1,"178":1,"245":1}}],["matcher",{"2":{"291":1,"306":1,"312":1,"337":1,"344":1,"488":1,"524":1,"591":1}}],["matches",{"2":{"38":1,"94":3,"203":1,"263":1,"698":1}}],["matching",{"2":{"72":1,"128":1}}],["match",{"2":{"57":1,"68":1,"94":2,"97":1,"161":1,"185":1,"220":1,"224":1,"286":1,"686":1}}],["mapof",{"2":{"187":1,"188":1,"189":1}}],["mapnamevalue",{"2":{"176":2,"177":2,"178":2,"181":2}}],["map",{"2":{"37":1,"176":3,"177":2,"178":2,"180":3,"181":3,"187":2,"188":2,"189":2,"215":1,"557":1,"558":1,"559":1,"560":1,"561":1,"682":1}}],["magic",{"2":{"28":2}}],["macos",{"2":{"170":1,"171":1}}],["macro",{"2":{"103":1}}],["macros",{"2":{"103":1}}],["machine",{"2":{"97":1,"106":1,"169":1,"260":1,"268":2,"628":1}}],["machines",{"2":{"18":1,"137":2,"260":1,"263":2}}],["mac",{"2":{"16":2}}],["mangling",{"0":{"659":1},"2":{"658":1}}],["mantissa",{"2":{"457":1}}],["manipulate",{"2":{"261":1}}],["manipulating",{"2":{"13":1}}],["manufacturers",{"2":{"631":1}}],["manufacturing",{"2":{"137":3}}],["manual",{"2":{"100":1,"109":1,"238":1,"282":1}}],["manually",{"2":{"3":1,"125":1,"159":1,"161":2,"175":1,"656":1}}],["mandatory",{"2":{"110":1}}],["managed",{"2":{"656":1}}],["manager",{"0":{"264":1},"1":{"265":1,"266":1},"2":{"252":2,"264":2,"266":1,"282":1}}],["managers",{"2":{"174":1,"264":1,"269":1}}],["manage",{"2":{"165":3,"172":1,"203":3,"663":1}}],["manageable",{"2":{"107":1,"110":1}}],["management",{"0":{"142":1,"156":1},"1":{"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1},"2":{"13":1,"140":1,"167":1,"208":1,"247":1,"649":1}}],["manner",{"2":{"103":1,"649":1}}],["many",{"2":{"90":1,"94":1,"97":1,"137":3,"176":2,"212":1,"221":2,"236":1,"249":2,"262":1,"268":2,"269":1,"273":1}}],["maybe",{"2":{"228":1}}],["may",{"2":{"6":1,"97":1,"166":1,"175":1,"203":1,"241":1,"249":3,"250":1,"252":3,"253":2,"266":1,"270":1,"272":1,"283":1,"628":1,"631":1,"703":1,"728":1}}],["maintenance",{"2":{"631":1}}],["maintain",{"2":{"160":1,"260":1}}],["maintaining",{"2":{"19":1,"238":1}}],["maintainers",{"2":{"2":2,"5":2}}],["mainly",{"2":{"262":1}}],["main",{"2":{"2":1,"4":1,"101":1,"104":1,"172":1,"174":1,"181":2,"185":2,"187":2,"188":1,"189":3,"190":1,"191":1,"196":9,"656":1,"658":1,"714":1}}],["tl",{"2":{"128":1,"164":1}}],["ttl",{"0":{"122":1},"2":{"122":1}}],["tweet",{"2":{"253":1}}],["twice",{"2":{"248":1}}],["twiggy",{"2":{"109":1}}],["two",{"2":{"3":1,"6":1,"18":1,"49":1,"56":1,"57":1,"81":1,"87":1,"97":2,"118":1,"125":1,"127":1,"128":1,"138":2,"141":1,"154":1,"172":1,"174":1,"192":1,"210":1,"217":2,"220":1,"224":1,"227":1,"229":1,"233":1,"250":1,"252":1,"262":1,"263":1,"270":1,"273":1,"282":1,"631":1,"658":1,"660":1,"719":1,"729":1,"740":1}}],["txs",{"2":{"735":5,"749":4,"750":2}}],["tx",{"2":{"53":2,"61":1,"71":1,"219":2,"735":16}}],["typing",{"2":{"97":1,"212":1,"214":1}}],["typically",{"2":{"188":1,"218":1,"253":1,"630":1,"631":1}}],["typical",{"2":{"42":1,"69":1,"74":1,"141":1,"268":1}}],["type2",{"2":{"659":1}}],["type1",{"2":{"659":1}}],["type=asset",{"2":{"214":1}}],["type=",{"2":{"204":1,"735":3}}],["typed",{"2":{"178":1,"212":1,"214":1,"221":1,"231":1}}],["typeerror",{"0":{"596":1},"2":{"175":1,"417":1}}],["typeof",{"2":{"175":2}}],["types",{"0":{"25":1,"85":1,"124":1},"1":{"86":1,"87":1,"88":1,"89":1,"90":1,"125":1,"126":1,"127":1},"2":{"25":2,"31":1,"33":1,"37":1,"50":1,"57":3,"81":1,"85":1,"87":1,"97":1,"99":1,"103":1,"124":3,"125":1,"126":3,"137":2,"143":3,"174":1,"188":1,"207":2,"214":1,"215":2,"217":1,"219":1,"656":1,"658":2,"660":1,"666":1,"746":1}}],["typescript",{"0":{"173":1},"1":{"174":1,"175":1,"176":1,"177":1,"178":1,"179":1,"180":1,"181":1,"182":1,"183":1},"2":{"5":2,"27":1,"29":1,"42":1,"43":1,"166":1,"175":1,"176":1,"227":1}}],["type",{"2":{"12":5,"16":1,"25":1,"38":1,"46":1,"50":2,"52":1,"57":2,"62":1,"67":1,"79":1,"83":1,"85":2,"86":1,"87":1,"94":3,"97":1,"103":3,"125":3,"126":1,"128":2,"137":2,"141":1,"164":2,"174":1,"175":2,"178":2,"180":2,"189":3,"211":1,"212":1,"214":4,"215":2,"221":6,"253":1,"282":2,"289":1,"290":1,"291":1,"292":1,"293":1,"294":1,"295":1,"296":1,"297":1,"298":1,"299":1,"300":1,"301":1,"302":1,"303":1,"304":2,"305":1,"306":1,"307":1,"308":1,"309":1,"310":1,"311":1,"312":1,"313":1,"314":1,"315":1,"316":1,"317":1,"318":1,"319":1,"320":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"329":1,"330":1,"331":1,"332":1,"333":1,"334":1,"335":1,"336":1,"337":1,"338":1,"339":1,"340":1,"341":1,"342":1,"343":1,"344":1,"345":1,"346":1,"347":1,"348":1,"349":1,"350":1,"351":1,"352":1,"353":1,"354":1,"355":1,"356":1,"357":1,"358":1,"359":1,"360":1,"361":1,"362":1,"363":1,"364":1,"365":1,"366":1,"367":1,"368":4,"369":4,"370":4,"371":4,"372":4,"373":4,"374":4,"375":4,"376":4,"377":4,"378":4,"379":4,"380":1,"381":1,"382":1,"383":1,"384":1,"385":1,"386":1,"387":1,"388":1,"389":1,"390":1,"391":1,"392":1,"393":1,"394":4,"395":1,"396":1,"397":1,"398":1,"399":1,"400":1,"401":1,"402":1,"403":1,"404":1,"405":1,"406":1,"407":1,"408":1,"409":1,"410":1,"411":1,"412":1,"413":1,"414":1,"415":1,"416":1,"417":2,"418":1,"419":1,"420":1,"421":1,"422":1,"423":1,"424":1,"425":1,"426":1,"427":1,"428":1,"429":1,"430":1,"431":1,"432":1,"433":1,"434":1,"435":1,"436":1,"437":1,"438":1,"439":1,"440":1,"441":1,"442":1,"443":1,"444":1,"445":1,"446":1,"447":1,"448":1,"449":1,"450":2,"451":1,"452":1,"453":1,"454":1,"455":1,"456":1,"457":1,"458":1,"459":1,"460":1,"461":1,"462":1,"463":1,"464":1,"465":1,"466":1,"467":1,"468":1,"469":1,"470":1,"471":1,"472":1,"473":1,"474":1,"475":1,"476":1,"477":1,"478":1,"479":1,"480":1,"481":1,"482":1,"483":1,"484":1,"485":1,"486":1,"487":1,"488":1,"489":1,"490":1,"491":1,"492":1,"493":1,"494":1,"495":1,"496":1,"497":1,"498":1,"499":1,"500":1,"501":1,"502":1,"503":1,"504":1,"505":1,"506":1,"507":1,"508":1,"509":1,"510":1,"511":1,"512":1,"513":1,"514":1,"515":1,"516":1,"517":2,"518":1,"519":1,"520":1,"521":1,"522":1,"523":1,"524":1,"525":1,"526":1,"527":1,"528":1,"529":1,"530":1,"531":1,"532":1,"533":1,"534":1,"535":1,"536":1,"537":1,"538":1,"539":1,"540":1,"541":1,"542":1,"543":1,"544":1,"545":1,"546":1,"547":1,"548":1,"549":1,"550":1,"551":1,"552":1,"553":1,"554":1,"555":1,"556":1,"557":1,"558":1,"559":1,"560":1,"561":1,"562":1,"563":1,"564":1,"565":1,"566":1,"567":1,"568":1,"569":1,"570":1,"571":1,"572":1,"573":1,"574":1,"575":1,"576":1,"577":1,"578":1,"579":1,"580":1,"581":1,"582":1,"583":1,"584":1,"585":1,"586":1,"587":2,"588":1,"589":1,"590":1,"591":1,"592":1,"593":1,"594":1,"595":1,"596":1,"597":1,"598":1,"599":1,"600":1,"601":1,"602":1,"603":1,"604":1,"605":1,"606":1,"607":1,"608":1,"609":1,"610":1,"611":1,"612":1,"613":1,"614":1,"615":1,"616":1,"617":1,"618":1,"619":1,"620":1,"621":1,"622":1,"623":1,"624":1,"625":1,"630":1,"632":1,"642":1,"658":12,"666":9,"682":1,"683":1,"684":1,"691":1,"714":1,"735":8,"741":2,"749":2}}],["tuning",{"2":{"143":1}}],["tune",{"2":{"131":1,"151":1}}],["tuned",{"2":{"28":1}}],["turorials",{"2":{"208":1}}],["turing",{"2":{"97":1,"101":1}}],["turned",{"2":{"140":1,"158":1}}],["turn",{"2":{"85":1,"273":1,"643":1}}],["tuple",{"2":{"38":1,"94":1,"348":1}}],["tutorials",{"2":{"166":2,"224":1}}],["tutorial",{"0":{"228":1},"2":{"14":1,"16":1,"19":1,"40":1,"78":1,"169":1,"171":1,"174":2,"175":1,"194":1,"198":1,"202":1,"215":1,"224":1,"225":1,"226":1,"227":1,"228":3,"282":1}}],["tbd",{"2":{"23":1,"30":1,"275":1,"276":1,"284":1}}],["tell",{"2":{"273":1}}],["telegram",{"2":{"270":3,"271":1,"274":1,"277":1,"284":1,"285":1}}],["telemetry`",{"2":{"181":1}}],["telemetryurl",{"2":{"175":2,"181":2,"187":2}}],["telemetry",{"0":{"120":1,"150":1},"2":{"12":1,"18":5,"65":1,"118":1,"120":3,"143":4,"150":2,"175":2,"186":3,"196":1,"231":1,"232":1,"715":1,"734":1,"747":1}}],["text",{"2":{"256":1}}],["tech",{"2":{"174":1}}],["techniques",{"2":{"259":1}}],["technical",{"0":{"78":1},"2":{"75":1,"78":1,"93":1,"95":1,"97":1}}],["technologies",{"2":{"236":1}}],["technology",{"2":{"36":1,"225":1,"226":1,"237":1,"627":1}}],["temporarily",{"2":{"264":1}}],["temporary",{"2":{"43":1}}],["tempting",{"2":{"177":1,"213":1,"220":1}}],["template>",{"2":{"181":8}}],["template",{"2":{"113":1,"143":1,"164":1}}],["teacher",{"0":{"639":1},"2":{"626":1}}],["team",{"2":{"268":2,"270":2}}],["tea",{"2":{"92":11,"93":4,"94":4,"97":2,"204":7,"205":2,"206":1,"683":1}}],["terminated",{"2":{"266":1}}],["terminal",{"2":{"20":1,"187":1,"196":2,"204":1,"207":2,"244":1}}],["terminology",{"2":{"187":1,"188":1}}],["term",{"2":{"160":1}}],["terms",{"2":{"39":1,"41":1,"56":1,"89":1,"174":1,"178":1,"181":1,"189":1,"192":1,"214":1,"221":1,"224":1}}],["testops",{"2":{"287":2}}],["testconstskt",{"2":{"193":1}}],["testcontainers",{"2":{"186":7}}],["testengine",{"2":{"186":1,"193":4}}],["tested",{"2":{"0":1,"235":1,"268":1}}],["tests",{"2":{"62":2,"181":1,"235":1}}],["test",{"2":{"53":8,"137":1,"181":1,"187":2,"193":7,"197":2,"217":1}}],["testing",{"0":{"235":1},"2":{"14":1,"231":1,"235":3}}],["tremendously",{"2":{"249":1}}],["treating",{"2":{"261":1}}],["treated",{"2":{"238":1,"650":1}}],["treatments",{"2":{"137":1}}],["tree",{"0":{"640":2},"2":{"171":1,"626":2,"640":1}}],["troubleshoot",{"2":{"272":1}}],["troubleshooting",{"0":{"271":1,"274":1,"277":1,"278":1,"283":1,"284":1,"285":1},"1":{"272":1,"273":1,"275":1,"276":1,"278":1,"279":2,"280":2,"281":2,"282":2,"283":1,"286":1},"2":{"218":1,"271":1,"274":1,"277":1,"282":1,"284":1,"285":1}}],["trouble",{"2":{"120":1,"150":1}}],["try",{"2":{"92":4,"93":1,"104":1,"211":1,"218":1,"273":2,"283":1,"658":2}}],["trying",{"2":{"5":1,"101":1,"174":1,"230":2}}],["trivial",{"2":{"666":2}}],["tries",{"2":{"178":1,"261":1}}],["tried",{"2":{"28":1}}],["trigger$domain",{"2":{"660":1}}],["trigger$my",{"2":{"83":1}}],["triggernumberofexecutionschanged",{"0":{"594":1},"2":{"590":2}}],["triggercompletedoutcome",{"0":{"588":1},"2":{"586":1}}],["triggercompletedoutcometype",{"0":{"479":1,"589":1},"2":{"479":1,"587":1}}],["triggercompletedeventfilter",{"0":{"587":1},"2":{"350":1}}],["triggercompletedevent",{"0":{"586":1},"2":{"349":1}}],["triggercompleted",{"2":{"349":1,"350":1}}],["triggereventset",{"0":{"592":1},"2":{"591":1}}],["triggereventfilter",{"0":{"591":1},"2":{"341":1}}],["triggerevent",{"0":{"590":1},"2":{"340":1}}],["triggered",{"2":{"89":1}}],["triggerrepetitions",{"2":{"332":1,"444":1}}],["triggeringeventfilterbox",{"0":{"595":1},"2":{"297":1}}],["triggerid",{"0":{"437":1,"480":1,"593":1},"2":{"73":1,"74":1,"93":1,"331":1,"354":1,"355":1,"356":1,"393":1,"401":1,"402":1,"414":2,"437":1,"443":1,"480":1,"514":1,"536":1,"585":1,"586":1,"587":1,"590":4,"591":1,"594":1,"603":1,"710":1,"711":1,"712":1}}],["triggers",{"0":{"72":1,"81":1,"83":1,"85":1,"86":1,"87":1,"88":1,"89":1,"90":1,"91":1,"642":1},"1":{"73":1,"74":1,"75":1,"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":2,"83":2,"84":2,"85":1,"86":2,"87":2,"88":3,"89":3,"90":2,"91":1,"92":2,"93":2,"94":2,"95":2,"96":2,"97":2,"98":1,"99":1},"2":{"33":1,"34":1,"40":2,"41":5,"42":1,"43":1,"48":1,"50":1,"72":2,"79":1,"81":1,"82":8,"83":5,"85":8,"86":1,"87":7,"88":6,"89":4,"90":1,"97":5,"98":3,"99":1,"111":1,"137":1,"167":1,"207":1,"626":1,"642":1,"661":2,"699":1,"710":2,"713":1}}],["trigger",{"0":{"35":1,"73":1,"74":1,"75":1,"93":1,"95":1,"331":1,"443":1,"508":1,"514":1,"536":1,"585":1,"603":1,"709":1},"1":{"74":1,"75":1,"76":2,"77":2,"78":2,"79":2,"80":2,"710":1,"711":1,"712":1,"713":1},"2":{"31":1,"35":1,"41":4,"43":1,"72":3,"73":2,"74":4,"75":1,"78":2,"79":2,"80":1,"81":5,"83":2,"84":5,"85":3,"86":1,"88":8,"90":1,"91":1,"93":1,"95":3,"96":3,"98":9,"233":1,"332":1,"340":1,"341":1,"354":1,"355":1,"356":1,"393":1,"415":2,"444":1,"508":1,"509":2,"515":2,"537":2,"586":1,"587":1,"594":1,"604":2,"711":2,"712":2,"713":1}}],["truly",{"2":{"126":1}}],["true",{"2":{"18":4,"72":1,"94":1,"105":1,"123":1,"181":1,"186":3,"187":1,"214":1}}],["trustworthy",{"2":{"248":1,"256":1}}],["trusts",{"2":{"177":1,"213":1,"220":1}}],["trustedpeers",{"2":{"186":1}}],["trusted",{"0":{"146":1},"2":{"18":4,"22":1,"42":1,"111":1,"127":1,"135":4,"143":4,"146":3,"149":1,"248":1,"249":1,"261":1,"286":1}}],["trust",{"2":{"18":1,"146":1,"245":1}}],["train",{"2":{"260":1}}],["training",{"2":{"247":1,"260":1}}],["traitname",{"2":{"659":2}}],["traits",{"2":{"217":1,"658":1,"659":1,"741":1}}],["trait",{"2":{"62":2,"103":1,"212":1,"655":1,"658":4,"659":1}}],["trade",{"2":{"106":1,"137":3}}],["traditional",{"2":{"100":1}}],["traps",{"2":{"105":1}}],["tracing",{"2":{"217":1}}],["trace",{"2":{"39":1,"153":1,"427":1,"723":1}}],["track",{"2":{"65":1,"89":1,"212":1,"214":1,"215":1,"249":2,"258":1,"260":1,"644":1}}],["tracking",{"2":{"12":1,"249":1,"282":1,"725":1}}],["tracked",{"2":{"12":1,"39":1,"725":1}}],["transmitting",{"2":{"254":1}}],["transparent",{"2":{"233":1}}],["transport",{"2":{"175":3}}],["translation",{"2":{"196":1}}],["transcribed",{"2":{"105":1}}],["transferexpr",{"2":{"222":1}}],["transferasset",{"2":{"190":3}}],["transferassetinstruction",{"2":{"179":1}}],["transferable",{"2":{"79":1}}],["transferbox",{"0":{"584":1},"2":{"93":1,"179":2,"416":1}}],["transfers",{"2":{"93":1,"179":1}}],["transferring",{"0":{"179":1,"190":1,"222":1},"2":{"41":1,"44":1,"89":1,"190":1,"222":5}}],["transferred",{"2":{"27":1,"41":1,"50":1,"86":1,"97":1,"190":2,"191":1,"203":1,"255":1}}],["transfer",{"0":{"44":1,"203":1,"205":1,"580":1,"581":1,"582":1,"583":1},"2":{"40":2,"41":3,"44":3,"57":1,"94":1,"128":1,"137":1,"164":1,"179":2,"190":3,"203":4,"205":2,"222":3,"315":2,"416":1,"420":1,"584":2,"658":1,"661":2,"663":2}}],["transactionreceipttime",{"2":{"705":1}}],["transactionrejectionreason",{"0":{"477":1,"577":1},"2":{"477":1,"578":1,"579":1}}],["transactionlimiterror",{"0":{"573":1},"2":{"577":1}}],["transactionlimits",{"0":{"574":1},"2":{"485":2}}],["transactionlimits=4096",{"2":{"128":1,"164":1}}],["transactionpayload",{"0":{"543":1,"545":1,"565":1,"575":1},"2":{"545":1,"551":2,"565":1}}],["transactionqueryoutput",{"0":{"576":1},"2":{"499":1}}],["transactioneventfilter",{"0":{"572":1},"2":{"495":1}}],["transactionevent",{"0":{"571":1},"2":{"494":1}}],["transactionvalue",{"0":{"579":1,"616":1},"2":{"325":1,"576":1,"616":1,"707":2,"708":1}}],["transactionbuilder",{"2":{"175":1,"193":10}}],["transaction",{"0":{"96":1,"121":1,"122":1,"123":1,"706":1,"728":1,"751":1},"1":{"707":1,"708":1,"729":1,"730":1,"732":1,"733":1,"735":1,"737":1,"738":1,"740":1,"741":1,"752":1,"753":1},"2":{"28":2,"32":1,"39":2,"50":1,"53":2,"61":1,"71":5,"72":1,"96":1,"97":1,"98":1,"113":1,"121":2,"122":2,"123":1,"138":1,"143":3,"164":1,"174":1,"176":1,"177":1,"181":2,"192":6,"193":8,"212":1,"215":3,"219":11,"220":1,"221":3,"224":2,"255":1,"256":1,"393":1,"494":1,"495":1,"499":1,"576":1,"627":1,"664":1,"705":1,"707":3,"708":1,"728":4,"735":1,"751":1,"753":6}}],["transactionstatus",{"0":{"478":1,"578":1},"2":{"478":1,"571":1,"572":1}}],["transactions",{"0":{"71":1,"736":1},"1":{"737":1,"738":1},"2":{"12":5,"28":1,"32":1,"41":1,"50":1,"71":3,"80":1,"87":1,"89":3,"122":1,"123":1,"128":1,"135":1,"143":1,"164":1,"165":1,"175":4,"207":4,"215":1,"219":1,"237":1,"245":1,"254":1,"256":2,"323":1,"325":1,"646":1,"706":1,"707":1,"714":1,"728":1,"735":1,"736":1,"738":1,"749":3}}],["tail",{"2":{"705":1}}],["tailor",{"2":{"238":1}}],["tasks",{"2":{"249":1}}],["tally",{"2":{"214":1}}],["talking",{"2":{"163":1}}],["talk",{"2":{"25":1,"99":1,"141":1,"181":1,"192":1,"224":1,"672":1}}],["table",{"2":{"273":1}}],["tab",{"2":{"207":1,"265":1}}],["tag",{"2":{"180":1,"181":1,"186":1,"256":1}}],["tad",{"2":{"101":1}}],["taken",{"2":{"100":1,"107":1,"159":1,"174":1,"178":1,"247":1,"248":1}}],["takes",{"2":{"14":1,"88":1,"97":3,"100":1,"103":1,"253":1,"652":1}}],["take",{"2":{"8":1,"9":1,"18":1,"22":1,"28":1,"50":1,"65":1,"72":1,"97":1,"101":1,"105":1,"106":1,"125":1,"178":1,"226":1,"231":1,"253":2}}],["targets",{"2":{"173":2}}],["target",{"2":{"5":1,"6":3,"16":4,"17":1,"22":1,"41":3,"108":1,"110":1,"111":1,"174":10,"175":1,"181":1,"185":1,"210":1,"241":1,"242":1,"243":1,"248":1,"433":1,"434":1,"435":1,"436":1,"437":1}}],["t",{"2":{"5":1,"16":3,"28":2,"57":1,"69":1,"82":2,"84":1,"88":6,"97":2,"101":1,"102":2,"103":1,"106":1,"125":1,"128":1,"137":2,"141":1,"153":1,"154":1,"160":2,"163":1,"175":3,"176":1,"177":4,"178":1,"186":1,"196":1,"203":3,"211":2,"213":4,"214":4,"215":4,"217":1,"219":2,"220":4,"221":4,"224":1,"226":1,"232":1,"243":1,"248":1,"253":1,"272":1,"273":3,"278":2,"280":2,"282":1,"283":1,"285":1,"633":1,"656":2,"658":1}}],["thwart",{"2":{"253":1}}],["thus",{"2":{"28":1,"90":1,"110":1,"126":1,"161":1,"175":2,"189":1,"210":2,"221":1,"243":1,"267":1,"650":1}}],["throws",{"2":{"193":5}}],["throw",{"2":{"176":2,"190":1}}],["throughout",{"2":{"247":1,"707":1}}],["throughput",{"2":{"88":1}}],["through",{"2":{"13":1,"27":1,"29":1,"42":1,"43":1,"72":1,"88":1,"94":1,"98":1,"127":1,"141":1,"162":1,"169":1,"189":1,"198":1,"217":1,"226":1,"229":1,"253":2,"266":1,"694":1}}],["threats",{"2":{"250":1,"260":2,"261":1}}],["threat",{"2":{"247":1,"249":1}}],["threading",{"2":{"231":1}}],["threshold",{"2":{"97":1,"143":1}}],["three",{"2":{"18":2,"20":1,"21":2,"25":1,"127":1,"270":1,"272":1}}],["those",{"2":{"62":1,"65":1,"78":1,"125":2,"175":2,"229":1,"238":1,"267":1}}],["thoughtfully",{"2":{"231":1}}],["thought",{"2":{"141":1}}],["though",{"2":{"18":1,"25":1,"103":1,"134":1,"135":1,"256":1}}],["thoroughly",{"2":{"10":1,"260":1}}],["thankfully",{"2":{"103":1}}],["than",{"2":{"14":1,"88":2,"89":1,"97":2,"98":1,"101":2,"154":1,"175":1,"177":1,"178":1,"188":1,"220":1,"222":1,"232":1,"256":1,"282":2,"666":1,"684":1}}],["that",{"2":{"4":1,"6":1,"10":1,"13":1,"14":1,"16":8,"17":1,"18":4,"20":4,"21":2,"22":6,"28":6,"32":1,"36":2,"37":1,"38":1,"39":3,"40":1,"41":3,"42":6,"43":2,"46":1,"50":1,"51":1,"52":1,"55":1,"57":3,"60":1,"62":5,"63":2,"65":3,"66":1,"68":1,"69":2,"72":3,"78":4,"79":1,"80":1,"81":3,"84":2,"85":1,"86":1,"87":1,"88":8,"89":2,"91":2,"93":2,"94":8,"97":11,"98":5,"99":2,"100":3,"101":3,"103":3,"104":3,"105":1,"106":1,"107":1,"108":1,"110":2,"111":1,"116":3,"121":1,"123":1,"125":6,"126":3,"127":1,"128":5,"134":2,"135":5,"137":6,"141":8,"143":1,"146":2,"153":1,"154":3,"156":1,"159":1,"160":1,"161":1,"163":1,"166":1,"167":1,"170":1,"171":2,"172":1,"174":4,"175":8,"176":6,"177":6,"178":7,"181":4,"185":2,"186":1,"187":3,"188":1,"192":1,"200":2,"201":3,"202":1,"203":5,"204":2,"208":1,"210":3,"211":4,"212":2,"213":4,"214":6,"215":9,"217":11,"218":4,"219":7,"220":7,"221":11,"222":4,"226":1,"229":1,"230":4,"231":2,"232":1,"233":2,"234":1,"235":2,"238":5,"241":1,"242":2,"243":1,"244":1,"245":1,"246":2,"247":2,"248":4,"249":10,"250":5,"252":3,"253":3,"255":3,"256":9,"258":2,"259":1,"260":8,"263":4,"265":3,"266":3,"267":1,"268":2,"270":1,"272":4,"273":4,"278":1,"279":1,"280":3,"281":1,"282":7,"283":3,"285":1,"286":1,"627":3,"641":1,"642":1,"644":2,"645":1,"652":1,"654":1,"655":2,"656":3,"658":9,"659":1,"660":1,"663":1,"664":1,"669":1,"670":1,"671":2,"679":1,"680":2,"681":1,"682":1,"683":2,"686":1,"687":1,"688":1,"689":1,"690":1,"691":2,"694":1,"698":2,"707":1,"709":2,"710":2,"714":1,"717":1,"725":1,"726":1,"741":1}}],["thin",{"2":{"176":1,"666":1}}],["thinks",{"2":{"221":1}}],["thinking",{"2":{"137":1}}],["think",{"2":{"94":1,"137":2,"221":1}}],["thing",{"2":{"28":1,"116":1}}],["things",{"2":{"6":1,"18":1,"28":1,"31":1,"42":1,"72":1,"82":1,"97":1,"103":1,"177":1,"185":1,"213":1,"220":1,"254":1,"278":1,"656":1}}],["third",{"2":{"16":1,"230":1,"259":1,"645":1}}],["this",{"2":{"4":1,"5":2,"6":1,"10":1,"12":2,"13":1,"14":1,"16":5,"17":1,"18":1,"19":1,"20":3,"21":3,"28":4,"36":2,"39":1,"40":1,"41":2,"42":1,"44":1,"46":1,"48":1,"50":1,"51":1,"65":1,"66":1,"71":1,"75":1,"76":1,"78":2,"79":1,"80":2,"81":2,"85":1,"86":2,"87":1,"88":1,"89":2,"90":1,"92":1,"94":4,"95":1,"97":3,"99":1,"100":1,"101":2,"103":1,"104":2,"106":2,"108":3,"112":1,"117":1,"119":1,"120":2,"124":1,"125":2,"126":2,"127":1,"128":3,"137":7,"143":2,"146":1,"149":1,"150":1,"151":1,"154":1,"159":1,"160":1,"163":2,"166":1,"167":1,"169":1,"171":2,"173":2,"174":4,"175":7,"176":1,"177":1,"178":2,"181":9,"182":1,"183":1,"185":2,"187":6,"188":3,"189":6,"190":4,"191":3,"192":4,"194":1,"196":1,"198":1,"200":2,"202":1,"203":4,"210":1,"211":1,"212":2,"213":3,"214":3,"215":2,"217":1,"218":2,"219":1,"220":1,"221":6,"223":1,"224":4,"225":1,"226":2,"227":1,"228":1,"229":1,"230":1,"234":1,"236":2,"237":1,"238":3,"241":2,"243":1,"246":1,"247":3,"248":3,"249":5,"250":3,"252":1,"253":3,"254":1,"255":2,"256":4,"257":2,"258":1,"259":1,"262":1,"263":3,"264":1,"265":1,"266":1,"268":5,"269":1,"271":1,"272":4,"273":2,"274":1,"277":1,"281":1,"282":1,"283":4,"284":1,"285":1,"286":2,"287":2,"288":1,"627":1,"633":1,"647":1,"652":1,"653":1,"654":1,"656":2,"658":4,"662":1,"663":11,"664":1,"666":2,"675":1,"678":1,"679":1,"680":1,"683":1,"691":2,"700":2,"703":1,"705":1,"714":1,"715":1,"719":1,"723":1,"725":1,"729":1,"734":1,"735":2,"740":1,"741":1,"744":1,"747":1,"748":1,"752":1}}],["theoretically",{"2":{"137":1,"264":1}}],["theory",{"2":{"78":1,"91":1,"97":1,"101":1,"141":1,"210":1}}],["their",{"2":{"21":1,"24":1,"56":1,"57":2,"65":1,"67":1,"112":1,"115":1,"127":1,"132":1,"135":1,"137":3,"139":1,"145":1,"146":2,"148":1,"158":1,"160":1,"174":1,"177":1,"178":1,"189":1,"190":1,"213":1,"214":1,"217":1,"220":1,"221":2,"229":2,"246":2,"247":3,"248":3,"249":3,"250":1,"252":1,"255":1,"259":1,"260":1,"268":1,"628":1,"630":1,"631":2,"650":1,"653":1,"659":1,"666":1,"672":1,"704":1,"725":1,"750":1}}],["these",{"2":{"6":1,"16":2,"29":1,"33":1,"39":1,"42":1,"45":1,"46":1,"47":1,"57":1,"72":1,"74":1,"83":1,"86":1,"89":1,"90":1,"100":1,"116":1,"117":1,"126":1,"127":3,"128":1,"137":1,"138":2,"174":1,"175":2,"201":1,"208":1,"214":1,"217":2,"224":1,"237":1,"249":1,"250":1,"252":1,"258":1,"260":1,"262":1,"273":2,"282":1,"287":1,"627":1,"646":1,"648":1,"649":1,"650":1,"666":2,"728":1}}],["then",{"2":{"5":1,"21":1,"39":1,"88":1,"97":1,"104":1,"128":1,"174":2,"175":1,"177":2,"187":1,"188":1,"189":2,"191":1,"192":1,"213":1,"219":2,"220":2,"221":2,"222":2,"223":1,"224":1,"238":1,"244":1,"248":1,"263":1,"264":1,"265":5,"279":1,"282":3,"663":2,"720":2,"725":1,"728":1}}],["thereby",{"2":{"268":1}}],["therefore",{"2":{"203":1,"245":1,"252":1,"253":1,"256":1}}],["there",{"0":{"282":1},"2":{"3":1,"16":1,"18":1,"22":1,"25":1,"28":1,"31":1,"33":1,"39":1,"41":2,"42":1,"52":1,"56":2,"57":1,"62":6,"65":1,"81":1,"87":1,"97":1,"100":1,"103":2,"125":2,"135":1,"137":3,"177":1,"183":1,"188":1,"192":1,"197":1,"199":1,"200":1,"204":1,"210":1,"212":1,"213":1,"214":1,"217":1,"219":3,"220":1,"221":3,"224":1,"233":1,"235":1,"242":1,"252":1,"253":1,"256":1,"259":1,"263":1,"268":2,"270":1,"272":2,"273":1,"282":2,"658":1,"660":1}}],["they",{"2":{"0":1,"20":1,"21":1,"28":2,"39":3,"43":1,"56":2,"65":1,"82":1,"87":1,"88":1,"90":1,"97":2,"100":1,"105":1,"137":6,"153":1,"174":1,"177":1,"183":1,"200":1,"201":1,"213":1,"220":1,"221":1,"226":1,"247":1,"249":2,"256":1,"266":1,"630":1,"647":1,"658":1,"665":1,"667":1,"720":1,"728":2,"749":1}}],["themselves",{"2":{"671":1}}],["theme",{"2":{"214":1}}],["them",{"2":{"0":1,"5":1,"8":1,"9":1,"14":1,"18":2,"21":1,"24":1,"28":2,"41":1,"70":1,"85":1,"92":1,"97":1,"105":1,"125":2,"126":1,"129":1,"137":2,"167":2,"174":1,"175":1,"177":1,"179":1,"190":1,"191":1,"206":1,"213":1,"220":1,"221":1,"222":1,"248":2,"253":1,"256":3,"259":1,"260":2,"261":1,"264":1,"728":1}}],["the",{"0":{"73":1,"137":1,"160":1,"162":1,"242":1,"243":1,"244":2,"256":1,"281":1,"286":1},"1":{"74":1,"75":1,"76":1,"77":1,"78":1,"79":1,"80":1,"244":1},"2":{"0":3,"2":5,"3":3,"4":3,"5":8,"6":18,"7":3,"8":3,"9":2,"10":2,"12":9,"13":4,"14":8,"16":24,"17":7,"18":10,"19":4,"20":13,"21":21,"22":11,"24":8,"25":4,"27":2,"28":33,"29":9,"31":1,"32":5,"33":1,"34":1,"35":1,"36":6,"38":1,"39":18,"40":5,"41":6,"42":11,"43":6,"44":1,"45":1,"46":2,"49":1,"50":5,"51":4,"52":2,"53":1,"54":1,"56":1,"57":15,"58":2,"59":3,"60":1,"61":1,"62":12,"63":7,"65":14,"67":6,"68":2,"69":4,"70":1,"71":5,"72":5,"73":1,"74":1,"75":2,"76":1,"77":1,"78":7,"79":2,"80":2,"81":3,"82":2,"83":3,"84":6,"85":5,"86":4,"87":7,"88":23,"89":6,"90":2,"91":6,"92":5,"93":1,"94":12,"96":2,"97":31,"98":12,"99":4,"100":5,"101":14,"103":15,"104":12,"105":7,"106":8,"107":2,"108":4,"109":2,"110":8,"111":7,"112":3,"113":1,"114":1,"115":2,"116":6,"117":7,"118":1,"119":6,"120":4,"121":3,"122":3,"124":2,"125":10,"126":11,"127":7,"128":27,"129":2,"130":5,"131":2,"134":14,"135":23,"136":5,"137":41,"138":3,"139":2,"141":8,"143":8,"144":1,"145":2,"146":9,"147":1,"148":7,"149":4,"150":6,"151":9,"152":1,"153":2,"154":4,"155":4,"156":1,"157":1,"158":1,"159":2,"160":8,"161":8,"162":4,"163":5,"166":7,"167":4,"168":3,"169":1,"170":2,"171":4,"172":6,"174":31,"175":21,"176":8,"177":16,"178":14,"179":2,"181":9,"182":1,"183":10,"185":20,"186":8,"187":14,"188":8,"189":10,"190":9,"191":5,"192":9,"195":2,"196":11,"197":4,"198":2,"199":3,"200":33,"201":9,"202":16,"203":25,"204":6,"205":1,"207":5,"208":4,"210":10,"211":12,"212":7,"213":13,"214":10,"215":17,"217":30,"218":10,"219":16,"220":15,"221":28,"222":7,"223":2,"224":11,"225":1,"226":6,"227":4,"228":5,"229":6,"230":6,"231":2,"232":3,"233":9,"234":3,"236":2,"237":4,"238":26,"241":7,"242":4,"243":8,"244":19,"245":2,"246":6,"247":8,"248":7,"249":18,"250":6,"251":2,"252":35,"253":16,"254":2,"255":14,"256":18,"257":1,"258":1,"259":11,"260":8,"261":1,"262":5,"263":27,"264":12,"265":23,"266":10,"267":5,"268":19,"269":1,"270":5,"271":3,"272":36,"273":17,"274":1,"277":1,"279":5,"280":4,"281":2,"282":13,"283":5,"284":1,"285":3,"286":6,"287":11,"627":2,"628":5,"629":3,"630":3,"631":4,"632":1,"633":3,"634":1,"636":1,"637":2,"638":1,"640":1,"643":2,"644":1,"649":2,"650":2,"651":1,"652":1,"653":2,"654":2,"655":3,"656":16,"657":2,"658":21,"659":22,"660":3,"661":2,"662":1,"663":9,"664":13,"665":4,"666":26,"667":1,"668":1,"669":2,"670":5,"671":3,"672":2,"674":2,"675":2,"676":1,"677":2,"678":5,"679":5,"680":2,"681":1,"683":6,"684":5,"685":3,"686":2,"687":1,"688":2,"689":1,"690":2,"691":3,"692":5,"693":5,"694":5,"696":1,"697":1,"698":2,"699":3,"700":3,"701":2,"702":4,"703":5,"704":2,"705":4,"706":1,"707":3,"708":1,"709":1,"710":2,"711":2,"712":5,"713":1,"714":12,"715":2,"716":1,"717":10,"719":2,"720":9,"722":1,"723":4,"725":7,"726":4,"728":18,"729":2,"730":2,"732":1,"733":3,"734":2,"735":2,"737":1,"738":1,"740":1,"741":9,"744":2,"745":1,"746":2,"747":2,"748":9,"749":16,"750":4,"752":1}}],["tirelessly",{"2":{"97":1}}],["tiny",{"2":{"97":1}}],["tinkering",{"2":{"22":1}}],["timeinterval",{"0":{"476":1,"570":1},"2":{"476":1,"568":2}}],["timeeventfilter",{"0":{"569":1},"2":{"350":1,"595":1}}],["timeevent",{"0":{"568":1},"2":{"349":1}}],["timeunit",{"2":{"193":15}}],["timeout=60s",{"2":{"196":1}}],["timeoutexception",{"2":{"193":2}}],["timeouts",{"2":{"161":1}}],["timeout",{"0":{"122":1},"2":{"113":1,"122":2,"143":1,"164":1,"187":2,"188":1,"189":2,"190":1,"191":1}}],["timed",{"2":{"89":1}}],["timestamp",{"2":{"87":1,"323":1,"500":1}}],["times",{"2":{"57":1,"84":2,"98":4,"252":1,"253":1,"627":1}}],["time",{"0":{"34":1,"87":1},"1":{"88":1,"89":1},"2":{"3":1,"28":2,"31":1,"34":2,"43":1,"57":2,"84":1,"85":1,"87":3,"88":8,"94":2,"97":3,"105":2,"107":1,"113":1,"122":2,"137":1,"143":2,"148":1,"153":1,"160":3,"164":1,"177":1,"178":12,"179":2,"186":1,"189":4,"190":8,"191":12,"200":1,"201":1,"207":3,"213":1,"214":6,"220":1,"221":10,"222":1,"232":1,"233":1,"252":2,"253":2,"263":1,"270":2,"272":1,"349":1,"350":1,"575":2,"595":1,"631":1,"637":1,"642":1,"705":3,"710":1,"717":1,"735":2}}],["tips",{"2":{"271":1,"274":1,"277":1,"284":1}}],["tip",{"2":{"3":1,"5":1,"16":2,"17":1,"18":1,"20":1,"162":1,"166":1,"168":1,"170":1,"171":1,"175":1,"181":1,"196":1,"200":1,"202":1,"203":1,"207":1,"210":1,"217":1,"238":2,"252":1,"264":1,"684":1}}],["tscomponents",{"2":{"181":1}}],["tsconst",{"2":{"5":1,"177":3,"180":3}}],["tsclient",{"2":{"181":1}}],["tsawait",{"2":{"176":2}}],["tsasync",{"2":{"176":2}}],["tsx",{"2":{"174":3}}],["tsimport",{"2":{"5":1,"174":1,"175":6,"176":1,"177":1,"178":2,"179":1,"180":1,"181":4,"183":1}}],["tsexport",{"2":{"2":1,"5":2}}],["ts",{"2":{"2":2,"3":1,"5":6,"174":4,"181":9}}],["today",{"2":{"656":1}}],["todo",{"2":{"113":1,"143":1,"164":1,"180":1,"288":1}}],["torelance",{"2":{"654":1}}],["toriipre",{"2":{"181":7}}],["toriirequirements",{"2":{"175":4,"176":3,"180":4}}],["toriirequirementsfortelemetry",{"2":{"175":4}}],["toriirequirementsforapiwebsocket",{"2":{"175":4,"183":2}}],["toriirequirementsforapihttp",{"2":{"175":6,"176":2,"180":2}}],["torii",{"0":{"119":1,"120":1,"637":1,"714":1},"1":{"715":1,"716":1,"717":1,"718":1,"719":1,"720":1,"721":1,"722":1,"723":1,"724":1,"725":1,"726":1,"727":1,"728":1,"729":1,"730":1,"731":1,"732":1,"733":1,"734":1,"735":1,"736":1,"737":1,"738":1,"739":1,"740":1,"741":1,"742":1,"743":1,"744":1,"745":1,"746":1,"747":1,"748":1,"749":1,"750":1,"751":1,"752":1,"753":1},"2":{"11":1,"12":1,"18":12,"20":3,"21":3,"113":1,"118":3,"119":3,"120":3,"127":1,"143":1,"147":1,"150":1,"164":1,"175":22,"181":7,"183":2,"218":2,"626":1,"714":2}}],["touch",{"2":{"270":1}}],["towards",{"2":{"247":1}}],["tokio",{"2":{"217":1,"231":1}}],["token",{"2":{"41":1,"57":7,"62":1,"111":1,"141":1,"204":1,"492":1,"527":1,"663":1,"664":3,"673":1}}],["tokens",{"0":{"57":1,"58":1,"663":1},"1":{"58":1,"664":1},"2":{"33":1,"40":1,"41":3,"42":1,"43":2,"55":1,"56":4,"57":1,"58":1,"59":1,"64":2,"111":1,"128":1,"129":1,"137":1,"141":1,"204":1,"661":1,"662":2,"663":1,"669":1,"670":1,"674":1}}],["to=",{"2":{"205":1}}],["toirohapublickey",{"2":{"186":2,"188":2,"190":1}}],["tostring",{"2":{"181":1}}],["toggle",{"2":{"181":1}}],["together",{"2":{"39":1,"213":1,"257":1}}],["toaccount",{"2":{"179":2}}],["tolerance",{"0":{"230":1,"634":1},"2":{"626":1}}],["tolerant",{"2":{"146":1,"230":3}}],["tolerate",{"2":{"18":3,"230":1}}],["toml",{"2":{"103":2,"105":2,"113":1,"115":1,"132":1,"143":5,"164":2,"199":2,"200":7,"203":4,"217":2,"218":1}}],["toocomplex",{"2":{"606":1}}],["tooling",{"2":{"231":1}}],["toolchain>",{"2":{"282":1}}],["toolchains",{"2":{"280":2,"282":2}}],["toolchain",{"0":{"278":1,"283":1},"1":{"279":1,"280":1,"281":1,"282":1},"2":{"170":1,"279":1,"280":2,"281":1,"282":4}}],["tool",{"2":{"109":1,"134":1,"172":2,"202":1,"237":1,"241":1,"246":1,"263":1,"272":1,"714":1}}],["tools",{"0":{"109":1},"2":{"101":1,"231":2,"241":2,"265":1,"649":1}}],["too",{"2":{"36":1,"57":1,"88":1,"146":1,"154":1,"200":1,"248":1,"253":1,"741":1}}],["top",{"2":{"120":1,"150":1,"265":1}}],["topology",{"2":{"20":2,"21":1,"325":1}}],["topics",{"2":{"246":1,"247":1,"263":1}}],["topic",{"2":{"12":1,"28":1,"46":1,"124":1,"247":2,"257":1,"263":2}}],["totalquantitychanged",{"2":{"305":1,"307":1}}],["total",{"2":{"12":7,"97":1,"247":1,"310":1,"342":1,"694":1,"735":3}}],["to",{"0":{"6":1,"12":1,"109":1,"183":1,"243":1,"244":1},"1":{"7":1,"8":1,"9":1,"244":1},"2":{"0":2,"3":2,"4":2,"5":5,"6":5,"7":1,"8":2,"9":1,"10":1,"12":3,"13":4,"14":9,"16":22,"18":14,"19":1,"20":7,"21":9,"22":7,"24":1,"25":1,"27":2,"28":9,"29":2,"32":1,"33":1,"34":1,"36":2,"37":1,"39":6,"40":3,"41":5,"42":9,"43":6,"44":7,"45":1,"48":1,"49":1,"50":1,"52":2,"53":6,"55":1,"56":7,"57":5,"59":2,"60":2,"61":1,"62":5,"63":3,"65":11,"66":2,"67":4,"68":1,"69":5,"72":3,"74":1,"76":1,"78":3,"79":2,"80":1,"81":1,"82":2,"83":4,"84":2,"85":2,"86":1,"87":2,"88":14,"89":4,"90":2,"91":1,"93":2,"94":6,"95":1,"96":1,"97":16,"98":2,"99":4,"100":2,"101":7,"102":2,"103":6,"104":7,"105":2,"108":3,"109":2,"110":5,"113":1,"114":1,"116":2,"117":2,"119":1,"120":5,"121":1,"122":4,"123":1,"125":1,"126":1,"127":1,"128":2,"129":2,"130":2,"131":1,"132":1,"134":5,"135":10,"136":2,"137":20,"138":3,"139":3,"140":1,"141":12,"143":6,"144":1,"146":8,"148":6,"150":7,"151":6,"153":2,"154":5,"155":1,"156":1,"158":1,"159":3,"160":6,"161":3,"163":4,"164":1,"166":3,"167":4,"168":2,"169":1,"170":4,"171":1,"172":5,"174":16,"175":22,"176":9,"177":11,"178":10,"179":2,"181":5,"183":8,"185":6,"186":1,"187":9,"188":9,"189":10,"190":9,"191":5,"192":4,"194":1,"195":1,"196":7,"197":3,"199":3,"200":14,"201":3,"202":9,"203":10,"204":3,"205":1,"206":1,"207":6,"208":1,"210":2,"211":2,"212":3,"213":10,"214":8,"215":7,"217":10,"218":8,"219":7,"220":12,"221":10,"222":8,"223":2,"224":8,"225":2,"226":2,"227":3,"228":3,"229":3,"230":6,"231":5,"232":3,"233":3,"234":2,"235":2,"237":2,"238":8,"241":4,"242":3,"243":5,"244":4,"245":2,"246":4,"247":5,"248":7,"249":18,"250":5,"251":2,"252":15,"253":15,"254":2,"255":1,"256":11,"257":2,"258":2,"259":9,"260":20,"261":2,"262":4,"263":14,"264":4,"265":6,"266":1,"267":2,"268":16,"270":4,"272":13,"273":4,"279":2,"280":2,"281":2,"282":4,"283":3,"285":1,"286":2,"287":3,"324":1,"328":1,"333":1,"351":1,"352":1,"410":1,"411":1,"412":1,"413":1,"422":1,"423":1,"424":1,"425":1,"432":1,"448":1,"454":1,"455":1,"456":1,"541":1,"542":1,"543":1,"566":1,"569":1,"575":1,"619":1,"620":1,"627":1,"628":2,"630":1,"631":2,"634":3,"637":1,"640":1,"643":2,"645":1,"649":3,"651":1,"655":3,"656":10,"658":7,"659":3,"660":1,"661":2,"662":1,"663":29,"664":3,"665":1,"666":3,"668":1,"669":1,"671":1,"672":2,"674":1,"675":1,"677":1,"678":1,"680":1,"682":1,"683":1,"684":3,"687":1,"692":1,"693":1,"701":1,"702":1,"705":3,"706":1,"712":1,"714":4,"715":1,"716":1,"718":1,"719":1,"720":3,"722":1,"723":1,"725":2,"726":2,"727":1,"728":6,"729":1,"732":1,"734":1,"735":1,"737":1,"741":2,"744":1,"745":1,"747":1,"748":2,"749":1,"750":2,"753":3}}]],"serializationVersion":2}';export{e as default}; diff --git a/assets/chunks/CompatibilityMatrixTable.CQKxYpI6.js b/assets/chunks/CompatibilityMatrixTable.CQKxYpI6.js new file mode 100644 index 00000000..464e96af --- /dev/null +++ b/assets/chunks/CompatibilityMatrixTable.CQKxYpI6.js @@ -0,0 +1 @@ +import{u as y}from"./vue-kakuyaku.C7Ook2cc.js";import b from"./CompatibilityMatrixTableIcon.DMA2bqrA.js";import{d as k,k as x,o as t,c as e,m as i,F as d,G as u,t as p,J as v,p as m,e as C,q as I,s as S,_ as T}from"./framework.B6c1f-8R.js";import"./IconCheck.DOTyKktD.js";const M=l=>(I("data-v-ba4f590a"),l=l(),S(),l),g={key:0},j=["title"],B={key:1,class:"border rounded p-2 my-4"},F={key:0,class:"flex space-x-2 items-center"},L=M(()=>i("span",null,"Loading data...",-1)),N=[L],V={key:1},w=k({__name:"CompatibilityMatrixTable",setup(l){const h="https://docs-compat.iroha2.tachi.soramitsu.co.jp/compat-matrix",o=y(()=>fetch(h,{}).then(r=>r.json()),{immediate:!0}),c=x(()=>{if(!o.state.fulfilled)return null;const r=o.state.fulfilled.value,_=["Story",...r.included_sdks.map(a=>a.name)],s=r.stories.map(a=>({story:a.name,results:a.results.map(n=>n.status)}));return{headers:_,rows:s}});return(r,_)=>c.value?(t(),e("table",g,[i("thead",null,[(t(!0),e(d,null,u(c.value.headers,s=>(t(),e("th",{key:s},p(s),1))),128))]),i("tbody",null,[(t(!0),e(d,null,u(c.value.rows,(s,a)=>(t(),e("tr",{key:a},[i("td",null,p(s.story),1),(t(!0),e(d,null,u(s.results,(n,f)=>(t(),e("td",{key:f,class:"status-cell",title:`Status: ${n}`},[v(b,{status:n},null,8,["status"])],8,j))),128))]))),128))])])):(t(),e("div",B,[m(o).state.pending?(t(),e("div",F,N)):m(o).state.rejected?(t(),e("div",V," Failed to load compatibility matrix data: "+p(m(o).state.rejected.reason),1)):C("",!0)]))}}),E=T(w,[["__scopeId","data-v-ba4f590a"]]);export{E as default}; diff --git a/assets/chunks/CompatibilityMatrixTableIcon.DMA2bqrA.js b/assets/chunks/CompatibilityMatrixTableIcon.DMA2bqrA.js new file mode 100644 index 00000000..6ee03b3c --- /dev/null +++ b/assets/chunks/CompatibilityMatrixTableIcon.DMA2bqrA.js @@ -0,0 +1 @@ +import{I as d}from"./IconCheck.DOTyKktD.js";import{_ as s,o as a,c as r,m as i,d as q,k as u,b as _,n as m,K as p}from"./framework.B6c1f-8R.js";const h={name:"MaterialSymbolsCancelOutlineRounded"},f={xmlns:"http://www.w3.org/2000/svg",width:"1em",height:"1em",viewBox:"0 0 24 24"},T=i("path",{fill:"currentColor",d:"m12 13.4l2.9 2.9q.275.275.7.275t.7-.275q.275-.275.275-.7t-.275-.7L13.4 12l2.9-2.9q.275-.275.275-.7t-.275-.7q-.275-.275-.7-.275t-.7.275L12 10.6L9.1 7.7q-.275-.275-.7-.275t-.7.275q-.275.275-.275.7t.275.7l2.9 2.9l-2.9 2.9q-.275.275-.275.7t.275.7q.275.275.7.275t.7-.275l2.9-2.9Zm0 8.6q-2.075 0-3.9-.788t-3.175-2.137q-1.35-1.35-2.137-3.175T2 12q0-2.075.788-3.9t2.137-3.175q1.35-1.35 3.175-2.137T12 2q2.075 0 3.9.788t3.175 2.137q1.35 1.35 2.138 3.175T22 12q0 2.075-.788 3.9t-2.137 3.175q-1.35 1.35-3.175 2.138T12 22Zm0-2q3.35 0 5.675-2.325T20 12q0-3.35-2.325-5.675T12 4Q8.65 4 6.325 6.325T4 12q0 3.35 2.325 5.675T12 20Zm0-8Z"},null,-1),$=[T];function w(e,n,o,t,c,l){return a(),r("svg",f,$)}const C=s(h,[["render",w]]),v={name:"MaterialSymbolsQuestionMarkRounded"},x={xmlns:"http://www.w3.org/2000/svg",width:"1em",height:"1em",viewBox:"0 0 24 24"},g=i("path",{fill:"currentColor",d:"M12.025 16q-.6 0-1.012-.425t-.363-1q.075-1.05.5-1.825t1.35-1.6q1.025-.9 1.563-1.563t.537-1.512q0-1.025-.687-1.7T12 5.7q-.8 0-1.363.338t-.912.837q-.35.5-.862.675t-.988-.025q-.575-.25-.787-.825t.087-1.075Q7.9 4.5 9.125 3.75T12 3q2.625 0 4.038 1.462t1.412 3.513q0 1.25-.537 2.138t-1.688 2.012q-.85.8-1.2 1.3t-.475 1.15q-.1.625-.525 1.025t-1 .4ZM12 22q-.825 0-1.413-.588T10 20q0-.825.588-1.413T12 18q.825 0 1.413.588T14 20q0 .825-.588 1.413T12 22Z"},null,-1),k=[g];function M(e,n,o,t,c,l){return a(),r("svg",x,k)}const b=s(v,[["render",M]]),B=q({__name:"CompatibilityMatrixTableIcon",props:{status:{},inline:{type:Boolean,default:!1}},setup(e){const n=e,o=u(()=>{switch(n.status){case"ok":return d;case"failed":return C;case"no-data":return b}});return(t,c)=>(a(),_(p(o.value),{"data-status":t.status,class:m({"inline-icon":t.inline})},null,8,["data-status","class"]))}}),Z=s(B,[["__scopeId","data-v-dad59778"]]);export{Z as default}; diff --git a/assets/chunks/IconCheck.DOTyKktD.js b/assets/chunks/IconCheck.DOTyKktD.js new file mode 100644 index 00000000..5d675e99 --- /dev/null +++ b/assets/chunks/IconCheck.DOTyKktD.js @@ -0,0 +1 @@ +import{_ as t,o as e,c as o,m as s}from"./framework.B6c1f-8R.js";const c={name:"MaterialSymbolsCheckCircleOutlineRounded"},n={xmlns:"http://www.w3.org/2000/svg",width:"1em",height:"1em",viewBox:"0 0 24 24"},r=s("path",{fill:"currentColor",d:"m10.6 13.8l-2.15-2.15q-.275-.275-.7-.275t-.7.275q-.275.275-.275.7t.275.7L9.9 15.9q.3.3.7.3t.7-.3l5.65-5.65q.275-.275.275-.7t-.275-.7q-.275-.275-.7-.275t-.7.275L10.6 13.8ZM12 22q-2.075 0-3.9-.788t-3.175-2.137q-1.35-1.35-2.137-3.175T2 12q0-2.075.788-3.9t2.137-3.175q1.35-1.35 3.175-2.137T12 2q2.075 0 3.9.788t3.175 2.137q1.35 1.35 2.138 3.175T22 12q0 2.075-.788 3.9t-2.137 3.175q-1.35 1.35-3.175 2.138T12 22Zm0-2q3.35 0 5.675-2.325T20 12q0-3.35-2.325-5.675T12 4Q8.65 4 6.325 6.325T4 12q0 3.35 2.325 5.675T12 20Zm0-8Z"},null,-1),a=[r];function q(l,_,i,m,d,h){return e(),o("svg",n,a)}const T=t(c,[["render",q]]);export{T as I}; diff --git a/assets/chunks/MermaidRender.B5IXDZbC.js b/assets/chunks/MermaidRender.B5IXDZbC.js new file mode 100644 index 00000000..54f7eb21 --- /dev/null +++ b/assets/chunks/MermaidRender.B5IXDZbC.js @@ -0,0 +1 @@ +import{a as g,u as k}from"./vue-kakuyaku.C7Ook2cc.js";import{d as y,k as u,h as x,ar as D,as as R,u as S,at as b,o as r,c as n,F as m,m as s,t as p}from"./framework.B6c1f-8R.js";import v from"https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs";async function j(d,t,l){v.initialize({startOnLoad:!0,theme:l.theme});const{svg:a}=await v.render(d,t);return{svg:a}}const B={ref:"root"},L=["innerHTML"],M={class:"custom-block danger"},T=s("p",{class:"custom-block-title"}," Unable to render the diagram ",-1),$={class:"language-mermaid"},C={key:1,class:"flex justify-center p-8"},I=y({__name:"MermaidRender",props:{id:{},text:{}},setup(d){const t=d,l=u(()=>decodeURIComponent(t.text)),a=x(!1);D(R("root"),([{isIntersecting:e}])=>{a.value||(a.value=e)});const{isDark:f}=S(),c=b(()=>f.value?"dark":"light"),_=g(()=>a.value&&{key:`${t.id}-${t.text}-${c.value}`,payload:{id:t.id,text:l.value,theme:c.value}},({payload:{id:e,text:i,theme:h}})=>k(()=>j(e,i,{theme:h}),{immediate:!0})),o=u(()=>{var e;return(e=_.value)==null?void 0:e.expose.state});return(e,i)=>(r(),n("div",B,[o.value&&!o.value.pending?(r(),n(m,{key:0},[o.value.fulfilled?(r(),n("pre",{key:0,"data-mermaid":"",class:"flex justify-center",innerHTML:o.value.fulfilled.value.svg},null,8,L)):(r(),n(m,{key:1},[s("div",M,[T,s("p",null,p(o.value.rejected.reason),1)]),s("div",$,[s("pre",null,[s("code",null,p(l.value),1)])])],64))],64)):(r(),n("div",C," Rendering the diagram... "))],512))}});export{I as default}; diff --git a/assets/chunks/ShareFeedback.DipQI5HM.js b/assets/chunks/ShareFeedback.DipQI5HM.js new file mode 100644 index 00000000..bd3bfb88 --- /dev/null +++ b/assets/chunks/ShareFeedback.DipQI5HM.js @@ -0,0 +1,8 @@ +import{O as P,z as U,h as g,k as h,au as it,ak as S,F as Z,d as x,l as C,A as D,y as ee,H as ut,$ as K,p as M,av as dt,aw as ct,ax as ft,S as pt,_ as te,o as A,c as O,m as b,r as De,ay as vt,az as mt,J as _,w as F,a as q,G as ht,aA as fe,aB as gt,t as bt,aC as Pe,e as wt,q as yt,s as Et}from"./framework.B6c1f-8R.js";import{b as $t,w as St,c as _t}from"./vue-kakuyaku.C7Ook2cc.js";import{I as kt}from"./IconCheck.DOTyKktD.js";let xt=Symbol("headlessui.useid"),Tt=0;function ie(){return P(xt,()=>`${++Tt}`)()}function E(e){var t;if(e==null||e.value==null)return null;let n=(t=e.value.$el)!=null?t:e.value;return n instanceof Node?n:null}function B(e,t,...n){if(e in t){let o=t[e];return typeof o=="function"?o(...n):o}let l=new Error(`Tried to handle "${e}" but there is no handler defined. Only defined handlers are: ${Object.keys(t).map(o=>`"${o}"`).join(", ")}.`);throw Error.captureStackTrace&&Error.captureStackTrace(l,B),l}var Lt=Object.defineProperty,Pt=(e,t,n)=>t in e?Lt(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,Fe=(e,t,n)=>(Pt(e,typeof t!="symbol"?t+"":t,n),n);let Ft=class{constructor(){Fe(this,"current",this.detect()),Fe(this,"currentId",0)}set(t){this.current!==t&&(this.currentId=0,this.current=t)}reset(){this.set(this.detect())}nextId(){return++this.currentId}get isServer(){return this.current==="server"}get isClient(){return this.current==="client"}detect(){return typeof window>"u"||typeof document>"u"?"server":"client"}},ue=new Ft;function G(e){if(ue.isServer)return null;if(e instanceof Node)return e.ownerDocument;if(e!=null&&e.hasOwnProperty("value")){let t=E(e);if(t)return t.ownerDocument}return document}let ge=["[contentEditable=true]","[tabindex]","a[href]","area[href]","button:not([disabled])","iframe","input:not([disabled])","select:not([disabled])","textarea:not([disabled])"].map(e=>`${e}:not([tabindex='-1'])`).join(",");var j=(e=>(e[e.First=1]="First",e[e.Previous=2]="Previous",e[e.Next=4]="Next",e[e.Last=8]="Last",e[e.WrapAround=16]="WrapAround",e[e.NoScroll=32]="NoScroll",e))(j||{}),Ne=(e=>(e[e.Error=0]="Error",e[e.Overflow=1]="Overflow",e[e.Success=2]="Success",e[e.Underflow=3]="Underflow",e))(Ne||{}),At=(e=>(e[e.Previous=-1]="Previous",e[e.Next=1]="Next",e))(At||{});function Ot(e=document.body){return e==null?[]:Array.from(e.querySelectorAll(ge)).sort((t,n)=>Math.sign((t.tabIndex||Number.MAX_SAFE_INTEGER)-(n.tabIndex||Number.MAX_SAFE_INTEGER)))}var je=(e=>(e[e.Strict=0]="Strict",e[e.Loose=1]="Loose",e))(je||{});function Ct(e,t=0){var n;return e===((n=G(e))==null?void 0:n.body)?!1:B(t,{0(){return e.matches(ge)},1(){let l=e;for(;l!==null;){if(l.matches(ge))return!0;l=l.parentElement}return!1}})}var Dt=(e=>(e[e.Keyboard=0]="Keyboard",e[e.Mouse=1]="Mouse",e))(Dt||{});typeof window<"u"&&typeof document<"u"&&(document.addEventListener("keydown",e=>{e.metaKey||e.altKey||e.ctrlKey||(document.documentElement.dataset.headlessuiFocusVisible="")},!0),document.addEventListener("click",e=>{e.detail===1?delete document.documentElement.dataset.headlessuiFocusVisible:e.detail===0&&(document.documentElement.dataset.headlessuiFocusVisible="")},!0));function H(e){e==null||e.focus({preventScroll:!0})}let Nt=["textarea","input"].join(",");function jt(e){var t,n;return(n=(t=e==null?void 0:e.matches)==null?void 0:t.call(e,Nt))!=null?n:!1}function Mt(e,t=n=>n){return e.slice().sort((n,l)=>{let o=t(n),r=t(l);if(o===null||r===null)return 0;let a=o.compareDocumentPosition(r);return a&Node.DOCUMENT_POSITION_FOLLOWING?-1:a&Node.DOCUMENT_POSITION_PRECEDING?1:0})}function ae(e,t,{sorted:n=!0,relativeTo:l=null,skipElements:o=[]}={}){var r;let a=(r=Array.isArray(e)?e.length>0?e[0].ownerDocument:document:e==null?void 0:e.ownerDocument)!=null?r:document,s=Array.isArray(e)?n?Mt(e):e:Ot(e);o.length>0&&s.length>1&&(s=s.filter(f=>!o.includes(f))),l=l??a.activeElement;let i=(()=>{if(t&5)return 1;if(t&10)return-1;throw new Error("Missing Focus.First, Focus.Previous, Focus.Next or Focus.Last")})(),u=(()=>{if(t&1)return 0;if(t&2)return Math.max(0,s.indexOf(l))-1;if(t&4)return Math.max(0,s.indexOf(l))+1;if(t&8)return s.length-1;throw new Error("Missing Focus.First, Focus.Previous, Focus.Next or Focus.Last")})(),d=t&32?{preventScroll:!0}:{},m=0,p=s.length,c;do{if(m>=p||m+p<=0)return 0;let f=u+m;if(t&16)f=(f+p)%p;else{if(f<0)return 3;if(f>=p)return 1}c=s[f],c==null||c.focus(d),m+=i}while(c!==a.activeElement);return t&6&&jt(c)&&c.select(),2}function Me(){return/iPhone/gi.test(window.navigator.platform)||/Mac/gi.test(window.navigator.platform)&&window.navigator.maxTouchPoints>0}function Rt(){return/Android/gi.test(window.navigator.userAgent)}function It(){return Me()||Rt()}function oe(e,t,n){ue.isServer||U(l=>{document.addEventListener(e,t,n),l(()=>document.removeEventListener(e,t,n))})}function Re(e,t,n){ue.isServer||U(l=>{window.addEventListener(e,t,n),l(()=>window.removeEventListener(e,t,n))})}function Ht(e,t,n=h(()=>!0)){function l(r,a){if(!n.value||r.defaultPrevented)return;let s=a(r);if(s===null||!s.getRootNode().contains(s))return;let i=function u(d){return typeof d=="function"?u(d()):Array.isArray(d)||d instanceof Set?d:[d]}(e);for(let u of i){if(u===null)continue;let d=u instanceof HTMLElement?u:E(u);if(d!=null&&d.contains(s)||r.composed&&r.composedPath().includes(d))return}return!Ct(s,je.Loose)&&s.tabIndex!==-1&&r.preventDefault(),t(r,s)}let o=g(null);oe("pointerdown",r=>{var a,s;n.value&&(o.value=((s=(a=r.composedPath)==null?void 0:a.call(r))==null?void 0:s[0])||r.target)},!0),oe("mousedown",r=>{var a,s;n.value&&(o.value=((s=(a=r.composedPath)==null?void 0:a.call(r))==null?void 0:s[0])||r.target)},!0),oe("click",r=>{It()||o.value&&(l(r,()=>o.value),o.value=null)},!0),oe("touchend",r=>l(r,()=>r.target instanceof HTMLElement?r.target:null),!0),Re("blur",r=>l(r,()=>window.document.activeElement instanceof HTMLIFrameElement?window.document.activeElement:null),!0)}var be=(e=>(e[e.None=0]="None",e[e.RenderStrategy=1]="RenderStrategy",e[e.Static=2]="Static",e))(be||{}),Bt=(e=>(e[e.Unmount=0]="Unmount",e[e.Hidden=1]="Hidden",e))(Bt||{});function N({visible:e=!0,features:t=0,ourProps:n,theirProps:l,...o}){var r;let a=He(l,n),s=Object.assign(o,{props:a});if(e||t&2&&a.static)return pe(s);if(t&1){let i=(r=a.unmount)==null||r?0:1;return B(i,{0(){return null},1(){return pe({...o,props:{...a,hidden:!0,style:{display:"none"}}})}})}return pe(s)}function pe({props:e,attrs:t,slots:n,slot:l,name:o}){var r,a;let{as:s,...i}=Ut(e,["unmount","static"]),u=(r=n.default)==null?void 0:r.call(n,l),d={};if(l){let m=!1,p=[];for(let[c,f]of Object.entries(l))typeof f=="boolean"&&(m=!0),f===!0&&p.push(c);m&&(d["data-headlessui-state"]=p.join(" "))}if(s==="template"){if(u=Ie(u??[]),Object.keys(i).length>0||Object.keys(t).length>0){let[m,...p]=u??[];if(!Vt(m)||p.length>0)throw new Error(['Passing props on "template"!',"",`The current component <${o} /> is rendering a "template".`,"However we need to passthrough the following props:",Object.keys(i).concat(Object.keys(t)).map(v=>v.trim()).filter((v,$,k)=>k.indexOf(v)===$).sort((v,$)=>v.localeCompare($)).map(v=>` - ${v}`).join(` +`),"","You can apply a few solutions:",['Add an `as="..."` prop, to ensure that we render an actual element instead of a "template".',"Render a single element as the child so that we can forward the props onto that element."].map(v=>` - ${v}`).join(` +`)].join(` +`));let c=He((a=m.props)!=null?a:{},i,d),f=it(m,c,!0);for(let v in c)v.startsWith("on")&&(f.props||(f.props={}),f.props[v]=c[v]);return f}return Array.isArray(u)&&u.length===1?u[0]:u}return S(s,Object.assign({},i,d),{default:()=>u})}function Ie(e){return e.flatMap(t=>t.type===Z?Ie(t.children):[t])}function He(...e){if(e.length===0)return{};if(e.length===1)return e[0];let t={},n={};for(let l of e)for(let o in l)o.startsWith("on")&&typeof l[o]=="function"?(n[o]!=null||(n[o]=[]),n[o].push(l[o])):t[o]=l[o];if(t.disabled||t["aria-disabled"])return Object.assign(t,Object.fromEntries(Object.keys(n).map(l=>[l,void 0])));for(let l in n)Object.assign(t,{[l](o,...r){let a=n[l];for(let s of a){if(o instanceof Event&&o.defaultPrevented)return;s(o,...r)}}});return t}function Ut(e,t=[]){let n=Object.assign({},e);for(let l of t)l in n&&delete n[l];return n}function Vt(e){return e==null?!1:typeof e.type=="string"||typeof e.type=="object"||typeof e.type=="function"}var se=(e=>(e[e.None=1]="None",e[e.Focusable=2]="Focusable",e[e.Hidden=4]="Hidden",e))(se||{});let we=x({name:"Hidden",props:{as:{type:[Object,String],default:"div"},features:{type:Number,default:1}},setup(e,{slots:t,attrs:n}){return()=>{var l;let{features:o,...r}=e,a={"aria-hidden":(o&2)===2?!0:(l=r["aria-hidden"])!=null?l:void 0,style:{position:"fixed",top:1,left:1,width:1,height:0,padding:0,margin:-1,overflow:"hidden",clip:"rect(0, 0, 0, 0)",whiteSpace:"nowrap",borderWidth:"0",...(o&4)===4&&(o&2)!==2&&{display:"none"}}};return N({ourProps:a,theirProps:r,slot:{},attrs:n,slots:t,name:"Hidden"})}}}),Wt=Symbol("Context");var Q=(e=>(e[e.Open=1]="Open",e[e.Closed=2]="Closed",e[e.Closing=4]="Closing",e[e.Opening=8]="Opening",e))(Q||{});function qt(){return P(Wt,null)}var Be=(e=>(e.Space=" ",e.Enter="Enter",e.Escape="Escape",e.Backspace="Backspace",e.Delete="Delete",e.ArrowLeft="ArrowLeft",e.ArrowUp="ArrowUp",e.ArrowRight="ArrowRight",e.ArrowDown="ArrowDown",e.Home="Home",e.End="End",e.PageUp="PageUp",e.PageDown="PageDown",e.Tab="Tab",e))(Be||{});function Kt(e){function t(){document.readyState!=="loading"&&(e(),document.removeEventListener("DOMContentLoaded",t))}typeof window<"u"&&typeof document<"u"&&(document.addEventListener("DOMContentLoaded",t),t())}let R=[];Kt(()=>{function e(t){t.target instanceof HTMLElement&&t.target!==document.body&&R[0]!==t.target&&(R.unshift(t.target),R=R.filter(n=>n!=null&&n.isConnected),R.splice(10))}window.addEventListener("click",e,{capture:!0}),window.addEventListener("mousedown",e,{capture:!0}),window.addEventListener("focus",e,{capture:!0}),document.body.addEventListener("click",e,{capture:!0}),document.body.addEventListener("mousedown",e,{capture:!0}),document.body.addEventListener("focus",e,{capture:!0})});function Se(e){typeof queueMicrotask=="function"?queueMicrotask(e):Promise.resolve().then(e).catch(t=>setTimeout(()=>{throw t}))}function _e(){let e=[],t={addEventListener(n,l,o,r){return n.addEventListener(l,o,r),t.add(()=>n.removeEventListener(l,o,r))},requestAnimationFrame(...n){let l=requestAnimationFrame(...n);t.add(()=>cancelAnimationFrame(l))},nextFrame(...n){t.requestAnimationFrame(()=>{t.requestAnimationFrame(...n)})},setTimeout(...n){let l=setTimeout(...n);t.add(()=>clearTimeout(l))},microTask(...n){let l={current:!0};return Se(()=>{l.current&&n[0]()}),t.add(()=>{l.current=!1})},style(n,l,o){let r=n.style.getPropertyValue(l);return Object.assign(n.style,{[l]:o}),this.add(()=>{Object.assign(n.style,{[l]:r})})},group(n){let l=_e();return n(l),this.add(()=>l.dispose())},add(n){return e.push(n),()=>{let l=e.indexOf(n);if(l>=0)for(let o of e.splice(l,1))o()}},dispose(){for(let n of e.splice(0))n()}};return t}function Ue(e,t,n,l){ue.isServer||U(o=>{e=e??window,e.addEventListener(t,n,l),o(()=>e.removeEventListener(t,n,l))})}var X=(e=>(e[e.Forwards=0]="Forwards",e[e.Backwards=1]="Backwards",e))(X||{});function Gt(){let e=g(0);return Re("keydown",t=>{t.key==="Tab"&&(e.value=t.shiftKey?1:0)}),e}function Ve(e){if(!e)return new Set;if(typeof e=="function")return new Set(e());let t=new Set;for(let n of e.value){let l=E(n);l instanceof HTMLElement&&t.add(l)}return t}var We=(e=>(e[e.None=1]="None",e[e.InitialFocus=2]="InitialFocus",e[e.TabLock=4]="TabLock",e[e.FocusLock=8]="FocusLock",e[e.RestoreFocus=16]="RestoreFocus",e[e.All=30]="All",e))(We||{});let Y=Object.assign(x({name:"FocusTrap",props:{as:{type:[Object,String],default:"div"},initialFocus:{type:Object,default:null},features:{type:Number,default:30},containers:{type:[Object,Function],default:g(new Set)}},inheritAttrs:!1,setup(e,{attrs:t,slots:n,expose:l}){let o=g(null);l({el:o,$el:o});let r=h(()=>G(o)),a=g(!1);C(()=>a.value=!0),D(()=>a.value=!1),Yt({ownerDocument:r},h(()=>a.value&&!!(e.features&16)));let s=Jt({ownerDocument:r,container:o,initialFocus:h(()=>e.initialFocus)},h(()=>a.value&&!!(e.features&2)));Qt({ownerDocument:r,container:o,containers:e.containers,previousActiveElement:s},h(()=>a.value&&!!(e.features&8)));let i=Gt();function u(c){let f=E(o);f&&(v=>v())(()=>{B(i.value,{[X.Forwards]:()=>{ae(f,j.First,{skipElements:[c.relatedTarget]})},[X.Backwards]:()=>{ae(f,j.Last,{skipElements:[c.relatedTarget]})}})})}let d=g(!1);function m(c){c.key==="Tab"&&(d.value=!0,requestAnimationFrame(()=>{d.value=!1}))}function p(c){if(!a.value)return;let f=Ve(e.containers);E(o)instanceof HTMLElement&&f.add(E(o));let v=c.relatedTarget;v instanceof HTMLElement&&v.dataset.headlessuiFocusGuard!=="true"&&(qe(f,v)||(d.value?ae(E(o),B(i.value,{[X.Forwards]:()=>j.Next,[X.Backwards]:()=>j.Previous})|j.WrapAround,{relativeTo:c.target}):c.target instanceof HTMLElement&&H(c.target)))}return()=>{let c={},f={ref:o,onKeydown:m,onFocusout:p},{features:v,initialFocus:$,containers:k,...W}=e;return S(Z,[!!(v&4)&&S(we,{as:"button",type:"button","data-headlessui-focus-guard":!0,onFocus:u,features:se.Focusable}),N({ourProps:f,theirProps:{...t,...W},slot:c,attrs:t,slots:n,name:"FocusTrap"}),!!(v&4)&&S(we,{as:"button",type:"button","data-headlessui-focus-guard":!0,onFocus:u,features:se.Focusable})])}}}),{features:We});function zt(e){let t=g(R.slice());return ee([e],([n],[l])=>{l===!0&&n===!1?Se(()=>{t.value.splice(0)}):l===!1&&n===!0&&(t.value=R.slice())},{flush:"post"}),()=>{var n;return(n=t.value.find(l=>l!=null&&l.isConnected))!=null?n:null}}function Yt({ownerDocument:e},t){let n=zt(t);C(()=>{U(()=>{var l,o;t.value||((l=e.value)==null?void 0:l.activeElement)===((o=e.value)==null?void 0:o.body)&&H(n())},{flush:"post"})}),D(()=>{t.value&&H(n())})}function Jt({ownerDocument:e,container:t,initialFocus:n},l){let o=g(null),r=g(!1);return C(()=>r.value=!0),D(()=>r.value=!1),C(()=>{ee([t,n,l],(a,s)=>{if(a.every((u,d)=>(s==null?void 0:s[d])===u)||!l.value)return;let i=E(t);i&&Se(()=>{var u,d;if(!r.value)return;let m=E(n),p=(u=e.value)==null?void 0:u.activeElement;if(m){if(m===p){o.value=p;return}}else if(i.contains(p)){o.value=p;return}m?H(m):ae(i,j.First|j.NoScroll)===Ne.Error&&console.warn("There are no focusable elements inside the "),o.value=(d=e.value)==null?void 0:d.activeElement})},{immediate:!0,flush:"post"})}),o}function Qt({ownerDocument:e,container:t,containers:n,previousActiveElement:l},o){var r;Ue((r=e.value)==null?void 0:r.defaultView,"focus",a=>{if(!o.value)return;let s=Ve(n);E(t)instanceof HTMLElement&&s.add(E(t));let i=l.value;if(!i)return;let u=a.target;u&&u instanceof HTMLElement?qe(s,u)?(l.value=u,H(u)):(a.preventDefault(),a.stopPropagation(),H(i)):H(l.value)},!0)}function qe(e,t){for(let n of e)if(n.contains(t))return!0;return!1}function Xt(e){let t=ut(e.getSnapshot());return D(e.subscribe(()=>{t.value=e.getSnapshot()})),t}function Zt(e,t){let n=e(),l=new Set;return{getSnapshot(){return n},subscribe(o){return l.add(o),()=>l.delete(o)},dispatch(o,...r){let a=t[o].call(n,...r);a&&(n=a,l.forEach(s=>s()))}}}function en(){let e;return{before({doc:t}){var n;let l=t.documentElement;e=((n=t.defaultView)!=null?n:window).innerWidth-l.clientWidth},after({doc:t,d:n}){let l=t.documentElement,o=l.clientWidth-l.offsetWidth,r=e-o;n.style(l,"paddingRight",`${r}px`)}}}function tn(){return Me()?{before({doc:e,d:t,meta:n}){function l(o){return n.containers.flatMap(r=>r()).some(r=>r.contains(o))}t.microTask(()=>{var o;if(window.getComputedStyle(e.documentElement).scrollBehavior!=="auto"){let s=_e();s.style(e.documentElement,"scrollBehavior","auto"),t.add(()=>t.microTask(()=>s.dispose()))}let r=(o=window.scrollY)!=null?o:window.pageYOffset,a=null;t.addEventListener(e,"click",s=>{if(s.target instanceof HTMLElement)try{let i=s.target.closest("a");if(!i)return;let{hash:u}=new URL(i.href),d=e.querySelector(u);d&&!l(d)&&(a=d)}catch{}},!0),t.addEventListener(e,"touchstart",s=>{if(s.target instanceof HTMLElement)if(l(s.target)){let i=s.target;for(;i.parentElement&&l(i.parentElement);)i=i.parentElement;t.style(i,"overscrollBehavior","contain")}else t.style(s.target,"touchAction","none")}),t.addEventListener(e,"touchmove",s=>{if(s.target instanceof HTMLElement)if(l(s.target)){let i=s.target;for(;i.parentElement&&i.dataset.headlessuiPortal!==""&&!(i.scrollHeight>i.clientHeight||i.scrollWidth>i.clientWidth);)i=i.parentElement;i.dataset.headlessuiPortal===""&&s.preventDefault()}else s.preventDefault()},{passive:!1}),t.add(()=>{var s;let i=(s=window.scrollY)!=null?s:window.pageYOffset;r!==i&&window.scrollTo(0,r),a&&a.isConnected&&(a.scrollIntoView({block:"nearest"}),a=null)})})}}:{}}function nn(){return{before({doc:e,d:t}){t.style(e.documentElement,"overflow","hidden")}}}function ln(e){let t={};for(let n of e)Object.assign(t,n(t));return t}let I=Zt(()=>new Map,{PUSH(e,t){var n;let l=(n=this.get(e))!=null?n:{doc:e,count:0,d:_e(),meta:new Set};return l.count++,l.meta.add(t),this.set(e,l),this},POP(e,t){let n=this.get(e);return n&&(n.count--,n.meta.delete(t)),this},SCROLL_PREVENT({doc:e,d:t,meta:n}){let l={doc:e,d:t,meta:ln(n)},o=[tn(),en(),nn()];o.forEach(({before:r})=>r==null?void 0:r(l)),o.forEach(({after:r})=>r==null?void 0:r(l))},SCROLL_ALLOW({d:e}){e.dispose()},TEARDOWN({doc:e}){this.delete(e)}});I.subscribe(()=>{let e=I.getSnapshot(),t=new Map;for(let[n]of e)t.set(n,n.documentElement.style.overflow);for(let n of e.values()){let l=t.get(n.doc)==="hidden",o=n.count!==0;(o&&!l||!o&&l)&&I.dispatch(n.count>0?"SCROLL_PREVENT":"SCROLL_ALLOW",n),n.count===0&&I.dispatch("TEARDOWN",n)}});function on(e,t,n){let l=Xt(I),o=h(()=>{let r=e.value?l.value.get(e.value):void 0;return r?r.count>0:!1});return ee([e,t],([r,a],[s],i)=>{if(!r||!a)return;I.dispatch("PUSH",r,n);let u=!1;i(()=>{u||(I.dispatch("POP",s??r,n),u=!0)})},{immediate:!0}),o}let ve=new Map,J=new Map;function Ae(e,t=g(!0)){U(n=>{var l;if(!t.value)return;let o=E(e);if(!o)return;n(function(){var a;if(!o)return;let s=(a=J.get(o))!=null?a:1;if(s===1?J.delete(o):J.set(o,s-1),s!==1)return;let i=ve.get(o);i&&(i["aria-hidden"]===null?o.removeAttribute("aria-hidden"):o.setAttribute("aria-hidden",i["aria-hidden"]),o.inert=i.inert,ve.delete(o))});let r=(l=J.get(o))!=null?l:0;J.set(o,r+1),r===0&&(ve.set(o,{"aria-hidden":o.getAttribute("aria-hidden"),inert:o.inert}),o.setAttribute("aria-hidden","true"),o.inert=!0)})}function rn({defaultContainers:e=[],portals:t,mainTreeNodeRef:n}={}){let l=g(null),o=G(l);function r(){var a,s,i;let u=[];for(let d of e)d!==null&&(d instanceof HTMLElement?u.push(d):"value"in d&&d.value instanceof HTMLElement&&u.push(d.value));if(t!=null&&t.value)for(let d of t.value)u.push(d);for(let d of(a=o==null?void 0:o.querySelectorAll("html > *, body > *"))!=null?a:[])d!==document.body&&d!==document.head&&d instanceof HTMLElement&&d.id!=="headlessui-portal-root"&&(d.contains(E(l))||d.contains((i=(s=E(l))==null?void 0:s.getRootNode())==null?void 0:i.host)||u.some(m=>d.contains(m))||u.push(d));return u}return{resolveContainers:r,contains(a){return r().some(s=>s.contains(a))},mainTreeNodeRef:l,MainTreeNode(){return n!=null?null:S(we,{features:se.Hidden,ref:l})}}}let Ke=Symbol("ForcePortalRootContext");function an(){return P(Ke,!1)}let Oe=x({name:"ForcePortalRoot",props:{as:{type:[Object,String],default:"template"},force:{type:Boolean,default:!1}},setup(e,{slots:t,attrs:n}){return K(Ke,e.force),()=>{let{force:l,...o}=e;return N({theirProps:o,ourProps:{},slot:{},slots:t,attrs:n,name:"ForcePortalRoot"})}}}),Ge=Symbol("StackContext");var ye=(e=>(e[e.Add=0]="Add",e[e.Remove=1]="Remove",e))(ye||{});function sn(){return P(Ge,()=>{})}function un({type:e,enabled:t,element:n,onUpdate:l}){let o=sn();function r(...a){l==null||l(...a),o(...a)}C(()=>{ee(t,(a,s)=>{a?r(0,e,n):s===!0&&r(1,e,n)},{immediate:!0,flush:"sync"})}),D(()=>{t.value&&r(1,e,n)}),K(Ge,r)}let ze=Symbol("DescriptionContext");function dn(){let e=P(ze,null);if(e===null)throw new Error("Missing parent");return e}function cn({slot:e=g({}),name:t="Description",props:n={}}={}){let l=g([]);function o(r){return l.value.push(r),()=>{let a=l.value.indexOf(r);a!==-1&&l.value.splice(a,1)}}return K(ze,{register:o,slot:e,name:t,props:n}),h(()=>l.value.length>0?l.value.join(" "):void 0)}let fn=x({name:"Description",props:{as:{type:[Object,String],default:"p"},id:{type:String,default:null}},setup(e,{attrs:t,slots:n}){var l;let o=(l=e.id)!=null?l:`headlessui-description-${ie()}`,r=dn();return C(()=>D(r.register(o))),()=>{let{name:a="Description",slot:s=g({}),props:i={}}=r,{...u}=e,d={...Object.entries(i).reduce((m,[p,c])=>Object.assign(m,{[p]:M(c)}),{}),id:o};return N({ourProps:d,theirProps:u,slot:s.value,attrs:t,slots:n,name:a})}}});function pn(e){let t=G(e);if(!t){if(e===null)return null;throw new Error(`[Headless UI]: Cannot find ownerDocument for contextElement: ${e}`)}let n=t.getElementById("headlessui-portal-root");if(n)return n;let l=t.createElement("div");return l.setAttribute("id","headlessui-portal-root"),t.body.appendChild(l)}let vn=x({name:"Portal",props:{as:{type:[Object,String],default:"div"}},setup(e,{slots:t,attrs:n}){let l=g(null),o=h(()=>G(l)),r=an(),a=P(Ye,null),s=g(r===!0||a==null?pn(l.value):a.resolveTarget()),i=g(!1);C(()=>{i.value=!0}),U(()=>{r||a!=null&&(s.value=a.resolveTarget())});let u=P(Ee,null),d=!1,m=ft();return ee(l,()=>{if(d||!u)return;let p=E(l);p&&(D(u.register(p),m),d=!0)}),D(()=>{var p,c;let f=(p=o.value)==null?void 0:p.getElementById("headlessui-portal-root");f&&s.value===f&&s.value.children.length<=0&&((c=s.value.parentElement)==null||c.removeChild(s.value))}),()=>{if(!i.value||s.value===null)return null;let p={ref:l,"data-headlessui-portal":""};return S(dt,{to:s.value},N({ourProps:p,theirProps:e,slot:{},attrs:n,slots:t,name:"Portal"}))}}}),Ee=Symbol("PortalParentContext");function mn(){let e=P(Ee,null),t=g([]);function n(r){return t.value.push(r),e&&e.register(r),()=>l(r)}function l(r){let a=t.value.indexOf(r);a!==-1&&t.value.splice(a,1),e&&e.unregister(r)}let o={register:n,unregister:l,portals:t};return[t,x({name:"PortalWrapper",setup(r,{slots:a}){return K(Ee,o),()=>{var s;return(s=a.default)==null?void 0:s.call(a)}}})]}let Ye=Symbol("PortalGroupContext"),hn=x({name:"PortalGroup",props:{as:{type:[Object,String],default:"template"},target:{type:Object,default:null}},setup(e,{attrs:t,slots:n}){let l=ct({resolveTarget(){return e.target}});return K(Ye,l),()=>{let{target:o,...r}=e;return N({theirProps:r,ourProps:{},slot:{},attrs:t,slots:n,name:"PortalGroup"})}}});var gn=(e=>(e[e.Open=0]="Open",e[e.Closed=1]="Closed",e))(gn||{});let $e=Symbol("DialogContext");function ke(e){let t=P($e,null);if(t===null){let n=new Error(`<${e} /> is missing a parent component.`);throw Error.captureStackTrace&&Error.captureStackTrace(n,ke),n}return t}let re="DC8F892D-2EBD-447C-A4C8-A03058436FF4",bn=x({name:"Dialog",inheritAttrs:!1,props:{as:{type:[Object,String],default:"div"},static:{type:Boolean,default:!1},unmount:{type:Boolean,default:!0},open:{type:[Boolean,String],default:re},initialFocus:{type:Object,default:null},id:{type:String,default:null},role:{type:String,default:"dialog"}},emits:{close:e=>!0},setup(e,{emit:t,attrs:n,slots:l,expose:o}){var r,a;let s=(r=e.id)!=null?r:`headlessui-dialog-${ie()}`,i=g(!1);C(()=>{i.value=!0});let u=!1,d=h(()=>e.role==="dialog"||e.role==="alertdialog"?e.role:(u||(u=!0,console.warn(`Invalid role [${d}] passed to . Only \`dialog\` and and \`alertdialog\` are supported. Using \`dialog\` instead.`)),"dialog")),m=g(0),p=qt(),c=h(()=>e.open===re&&p!==null?(p.value&Q.Open)===Q.Open:e.open),f=g(null),v=h(()=>G(f));if(o({el:f,$el:f}),!(e.open!==re||p!==null))throw new Error("You forgot to provide an `open` prop to the `Dialog`.");if(typeof c.value!="boolean")throw new Error(`You provided an \`open\` prop to the \`Dialog\`, but the value is not a boolean. Received: ${c.value===re?void 0:e.open}`);let $=h(()=>i.value&&c.value?0:1),k=h(()=>$.value===0),W=h(()=>m.value>1),xe=P($e,null)!==null,[Je,Qe]=mn(),{resolveContainers:de,mainTreeNodeRef:Te,MainTreeNode:Xe}=rn({portals:Je,defaultContainers:[h(()=>{var w;return(w=z.panelRef.value)!=null?w:f.value})]}),Ze=h(()=>W.value?"parent":"leaf"),Le=h(()=>p!==null?(p.value&Q.Closing)===Q.Closing:!1),et=h(()=>xe||Le.value?!1:k.value),tt=h(()=>{var w,y,T;return(T=Array.from((y=(w=v.value)==null?void 0:w.querySelectorAll("body > *"))!=null?y:[]).find(L=>L.id==="headlessui-portal-root"?!1:L.contains(E(Te))&&L instanceof HTMLElement))!=null?T:null});Ae(tt,et);let nt=h(()=>W.value?!0:k.value),lt=h(()=>{var w,y,T;return(T=Array.from((y=(w=v.value)==null?void 0:w.querySelectorAll("[data-headlessui-portal]"))!=null?y:[]).find(L=>L.contains(E(Te))&&L instanceof HTMLElement))!=null?T:null});Ae(lt,nt),un({type:"Dialog",enabled:h(()=>$.value===0),element:f,onUpdate:(w,y)=>{if(y==="Dialog")return B(w,{[ye.Add]:()=>m.value+=1,[ye.Remove]:()=>m.value-=1})}});let ot=cn({name:"DialogDescription",slot:h(()=>({open:c.value}))}),ne=g(null),z={titleId:ne,panelRef:g(null),dialogState:$,setTitleId(w){ne.value!==w&&(ne.value=w)},close(){t("close",!1)}};K($e,z);let rt=h(()=>!(!k.value||W.value));Ht(de,(w,y)=>{z.close(),pt(()=>y==null?void 0:y.focus())},rt);let at=h(()=>!(W.value||$.value!==0));Ue((a=v.value)==null?void 0:a.defaultView,"keydown",w=>{at.value&&(w.defaultPrevented||w.key===Be.Escape&&(w.preventDefault(),w.stopPropagation(),z.close()))});let st=h(()=>!(Le.value||$.value!==0||xe));return on(v,st,w=>{var y;return{containers:[...(y=w.containers)!=null?y:[],de]}}),U(w=>{if($.value!==0)return;let y=E(f);if(!y)return;let T=new ResizeObserver(L=>{for(let ce of L){let le=ce.target.getBoundingClientRect();le.x===0&&le.y===0&&le.width===0&&le.height===0&&z.close()}});T.observe(y),w(()=>T.disconnect())}),()=>{let{open:w,initialFocus:y,...T}=e,L={...n,ref:f,id:s,role:d.value,"aria-modal":$.value===0?!0:void 0,"aria-labelledby":ne.value,"aria-describedby":ot.value},ce={open:$.value===0};return S(Oe,{force:!0},()=>[S(vn,()=>S(hn,{target:f.value},()=>S(Oe,{force:!1},()=>S(Y,{initialFocus:y,containers:de,features:k.value?B(Ze.value,{parent:Y.features.RestoreFocus,leaf:Y.features.All&~Y.features.FocusLock}):Y.features.None},()=>S(Qe,{},()=>N({ourProps:L,theirProps:{...T,...n},slot:ce,attrs:n,slots:l,visible:$.value===0,features:be.RenderStrategy|be.Static,name:"Dialog"})))))),S(Xe)])}}}),wn=x({name:"DialogPanel",props:{as:{type:[Object,String],default:"div"},id:{type:String,default:null}},setup(e,{attrs:t,slots:n,expose:l}){var o;let r=(o=e.id)!=null?o:`headlessui-dialog-panel-${ie()}`,a=ke("DialogPanel");l({el:a.panelRef,$el:a.panelRef});function s(i){i.stopPropagation()}return()=>{let{...i}=e,u={id:r,ref:a.panelRef,onClick:s};return N({ourProps:u,theirProps:i,slot:{open:a.dialogState.value===0},attrs:t,slots:n,name:"DialogPanel"})}}}),yn=x({name:"DialogTitle",props:{as:{type:[Object,String],default:"h2"},id:{type:String,default:null}},setup(e,{attrs:t,slots:n}){var l;let o=(l=e.id)!=null?l:`headlessui-dialog-title-${ie()}`,r=ke("DialogTitle");return C(()=>{r.setTitleId(o),D(()=>r.setTitleId(null))}),()=>{let{...a}=e;return N({ourProps:{id:o},theirProps:a,slot:{open:r.dialogState.value===0},attrs:t,slots:n,name:"DialogTitle"})}}}),En=fn;/*! + * mande v2.0.7 + * (c) 2023 Eduardo San Martin Morote + * @license MIT + */function $n(e){let t=Object.keys(e).map(n=>[n,e[n]].map(encodeURIComponent).join("=")).join("&");return t?"?"+t:""}let Sn=/^\/+/;function _n(e,t){return e+(t&&(e.endsWith("/")?t.replace(Sn,""):t.startsWith("/")?t:"/"+t))}function kn(e){return Object.keys(e).reduce((t,n)=>(e[n]!=null&&(t[n]=e[n]),t),{})}const me={responseAs:"json",headers:{Accept:"application/json","Content-Type":"application/json"},stringify:JSON.stringify};function xn(e,t={},n){function l(r,a,s,i={}){let u,d;typeof a=="object"?(u="",i=s||a||{},d=a):(u=a,d=s);let m={...me,...o,method:r,...i,headers:kn({...me.headers,...o.headers,...i.headers})},p={...me.query,...o.query,...i.query},{responseAs:c}=m;u=_n(e,typeof u=="number"?""+u:u||""),u+=$n(p),r[0]==="P"&&d&&!m.body&&(m.body=d instanceof FormData?d:m.stringify(d));const f=typeof fetch<"u"?fetch:n;if(!f)throw new Error("No fetch function exists. Make sure to include a polyfill on Node.js.");return f(u,m).then(v=>Promise.all([v,c==="response"?v:v[c]().catch(()=>null)])).then(([v,$])=>{if(v.status>=200&&v.status<300)return c!=="response"&&v.status==204?null:$;let k=new Error(v.statusText);throw k.response=v,k.body=$,k})}const o={query:{},headers:{},...t};return{options:o,post:l.bind(null,"POST"),put:l.bind(null,"PUT"),patch:l.bind(null,"PATCH"),get:(r,a)=>l("GET",r,null,a),delete:(r,a)=>l("DELETE",r,null,a)}}const Tn={name:"MaterialSymbolsClose"},Ln={xmlns:"http://www.w3.org/2000/svg",width:"1em",height:"1em",viewBox:"0 0 24 24"},Pn=b("path",{fill:"currentColor",d:"M6.4 19L5 17.6l5.6-5.6L5 6.4L6.4 5l5.6 5.6L17.6 5L19 6.4L13.4 12l5.6 5.6l-1.4 1.4l-5.6-5.6L6.4 19Z"},null,-1),Fn=[Pn];function An(e,t,n,l,o,r){return A(),O("svg",Ln,Fn)}const On=te(Tn,[["render",An]]),Cn={name:"IcOutlineFeedback"},Dn={xmlns:"http://www.w3.org/2000/svg",width:"1em",height:"1em",viewBox:"0 0 24 24"},Nn=b("path",{fill:"currentColor",d:"M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H5.17l-.59.59l-.58.58V4h16v12zm-9-4h2v2h-2zm0-6h2v4h-2z"},null,-1),jn=[Nn];function Mn(e,t,n,l,o,r){return A(),O("svg",Dn,jn)}const Rn=te(Cn,[["render",Mn]]),In={},Hn={class:"v-btn-primary"};function Bn(e,t){return A(),O("button",Hn,[De(e.$slots,"default")])}const Ce=te(In,[["render",Bn]]),Un={},Vn={class:"font-medium rounded-lg bg-vp-bg px-3 py-1.5 hover:bg-vp-brand-soft hover:text-vp-brand-2"};function Wn(e,t){return A(),O("button",Vn,[De(e.$slots,"default")])}const he=te(Un,[["render",Wn]]);function qn(e){return h(()=>!vt(e))}const V=e=>(yt("data-v-701191ba"),e=e(),Et(),e),Kn=V(()=>b("span",null,"Share feedback",-1)),Gn=V(()=>b("div",{class:"fixed inset-0 bg-black/30 z-90","aria-hidden":"true"},null,-1)),zn={class:"fixed inset-0 flex items-center justify-center p-4 z-90"},Yn={class:"feedback-card_header flex items-center"},Jn={class:"p-4 flex items-center space-x-4"},Qn=V(()=>b("div",null,"Thank you for sharing your feedback!",-1)),Xn={class:"flex flex-row-reverse p-4"},Zn={key:1,class:"flex-1 overflow-y-scroll"},el={class:"p-4 space-y-4"},tl={class:"space-y-1"},nl=V(()=>b("legend",{class:"field-label"}," Feedback type* ",-1)),ll=["id","value"],ol=["for"],rl=V(()=>b("label",{for:"feedback-input-text",class:"field-label"},"Feedback*",-1)),al=["placeholder"],sl=V(()=>b("label",{for:"feedback-input-contact",class:"field-label"},[b("i",null,"(optional)"),q(" Contact information ")],-1)),il={key:0,class:"px-4 text-xs"},ul={class:"flex p-4 items-center space-x-2"},dl=V(()=>b("div",{class:"flex-1"},null,-1)),cl=x({__name:"ShareFeedback",props:{feedbackUrl:{}},setup(e){const t=e,n=g(!1),l=["bug","suggestion","other"],o={suggestion:"Suggestion ✨",bug:"Bug 🐞",other:"Other"},r=g(null),a=g(""),s=g(""),i=h(()=>{switch(r.value){case"bug":return"Report any bugs or issues you found in Iroha 2 documentation";default:return"What can we do to improve the overall documentation browsing experience?"}}),u=$t(),d=g(!1);St(u.state,()=>{d.value=!0,a.value=s.value=""}),_t(u.state,p=>{console.error("Feedback rejection reason:",p)}),mt(qn(n),()=>{d.value=!1});function m(){const p={kind:r.value,feedback:a.value,contact:s.value,location:window.location},c=xn(t.feedbackUrl);u.set(c.post(p))}return(p,c)=>(A(),O(Z,null,[_(Ce,{class:"inline-flex items-center space-x-2",onClick:c[0]||(c[0]=f=>n.value=!0)},{default:F(()=>[_(Rn),Kn]),_:1}),_(M(bn),{open:n.value,onClose:c[7]||(c[7]=f=>n.value=!1)},{default:F(()=>[Gn,b("div",zn,[_(M(wn),{class:"feedback-card shadow-lg flex flex-col"},{default:F(()=>[b("div",Yn,[_(M(yn),{class:"feedback-card_title flex-1"},{default:F(()=>[q(" Share feedback ")]),_:1}),_(he,{class:"text-base p-2 -m-2",onClick:c[1]||(c[1]=f=>n.value=!1)},{default:F(()=>[_(On)]),_:1})]),d.value?(A(),O(Z,{key:0},[b("div",Jn,[_(kt,{class:"text-3xl feedback-card_check"}),Qn]),b("div",Xn,[_(he,{onClick:c[2]||(c[2]=f=>n.value=!1)},{default:F(()=>[q(" Close ")]),_:1})])],64)):(A(),O("div",Zn,[b("div",el,[_(M(En),{class:"text-sm"},{default:F(()=>[q(" Please take a moment to help us improve the Iroha 2 Documentation. We take your input very seriously. ")]),_:1}),b("div",null,[b("fieldset",tl,[nl,(A(),O(Z,null,ht(l,f=>b("div",{key:f,class:"flex space-x-2 items-center"},[fe(b("input",{id:`feedback-kind-${f}`,"onUpdate:modelValue":c[3]||(c[3]=v=>r.value=v),class:"max-w-min",value:f,type:"radio",name:"feedback-kind"},null,8,ll),[[gt,r.value]]),b("label",{for:`feedback-kind-${f}`,class:"flex-1 text-sm"},bt(o[f]),9,ol)])),64))])]),b("div",null,[rl,fe(b("textarea",{id:"feedback-input-text","onUpdate:modelValue":c[4]||(c[4]=f=>a.value=f),placeholder:i.value,rows:"5"},null,8,al),[[Pe,a.value]])]),b("div",null,[sl,fe(b("input",{id:"feedback-input-contact","onUpdate:modelValue":c[5]||(c[5]=f=>s.value=f),placeholder:"Email address, Discord, or Telegram"},null,512),[[Pe,s.value]])])]),M(u).state.rejected?(A(),O("div",il," Unable to send feedback ")):wt("",!0),b("div",ul,[dl,_(he,{onClick:c[6]||(c[6]=f=>n.value=!1)},{default:F(()=>[q(" Cancel ")]),_:1}),_(Ce,{disabled:!a.value||!r.value||M(u).state.pending,onClick:m},{default:F(()=>[q(" Submit ")]),_:1},8,["disabled"])])]))]),_:1})])]),_:1},8,["open"])],64))}}),hl=te(cl,[["__scopeId","data-v-701191ba"]]);export{hl as default}; diff --git a/assets/chunks/VPLocalSearchBox.BGpAGtia.js b/assets/chunks/VPLocalSearchBox.BGpAGtia.js new file mode 100644 index 00000000..434d0c6c --- /dev/null +++ b/assets/chunks/VPLocalSearchBox.BGpAGtia.js @@ -0,0 +1,13 @@ +var kt=Object.defineProperty;var It=(o,e,t)=>e in o?kt(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var Oe=(o,e,t)=>(It(o,typeof e!="symbol"?e+"":e,t),t);import{Y as mt,h as oe,y as $e,aD as Dt,aE as Ot,d as _t,H as xe,aF as tt,k as Fe,aG as Rt,aH as Mt,z as Lt,aI as zt,l as _e,S as de,Q as Ee,aJ as Pt,aK as Bt,Z as Vt,j as $t,aL as Wt,o as ee,b as Kt,m as E,a2 as jt,p as U,aA as Jt,aC as Ut,ao as Ht,c as re,n as rt,e as Se,G as at,F as nt,a as ve,t as pe,av as Gt,q as Qt,s as qt,ap as it,aM as Yt,aa as Zt,ag as Xt,aN as er,_ as tr}from"./framework.B6c1f-8R.js";import{u as rr,c as ar}from"./theme.BX4Y5IZy.js";const nr={root:()=>mt(()=>import("./@localSearchIndexroot.BSq76Xc_.js"),__vite__mapDeps([]))};/*! +* tabbable 6.2.0 +* @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE +*/var yt=["input:not([inert])","select:not([inert])","textarea:not([inert])","a[href]:not([inert])","button:not([inert])","[tabindex]:not(slot):not([inert])","audio[controls]:not([inert])","video[controls]:not([inert])",'[contenteditable]:not([contenteditable="false"]):not([inert])',"details>summary:first-of-type:not([inert])","details:not([inert])"],Te=yt.join(","),gt=typeof Element>"u",ue=gt?function(){}:Element.prototype.matches||Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector,Ne=!gt&&Element.prototype.getRootNode?function(o){var e;return o==null||(e=o.getRootNode)===null||e===void 0?void 0:e.call(o)}:function(o){return o==null?void 0:o.ownerDocument},ke=function o(e,t){var r;t===void 0&&(t=!0);var n=e==null||(r=e.getAttribute)===null||r===void 0?void 0:r.call(e,"inert"),a=n===""||n==="true",i=a||t&&e&&o(e.parentNode);return i},ir=function(e){var t,r=e==null||(t=e.getAttribute)===null||t===void 0?void 0:t.call(e,"contenteditable");return r===""||r==="true"},bt=function(e,t,r){if(ke(e))return[];var n=Array.prototype.slice.apply(e.querySelectorAll(Te));return t&&ue.call(e,Te)&&n.unshift(e),n=n.filter(r),n},wt=function o(e,t,r){for(var n=[],a=Array.from(e);a.length;){var i=a.shift();if(!ke(i,!1))if(i.tagName==="SLOT"){var s=i.assignedElements(),u=s.length?s:i.children,l=o(u,!0,r);r.flatten?n.push.apply(n,l):n.push({scopeParent:i,candidates:l})}else{var h=ue.call(i,Te);h&&r.filter(i)&&(t||!e.includes(i))&&n.push(i);var d=i.shadowRoot||typeof r.getShadowRoot=="function"&&r.getShadowRoot(i),v=!ke(d,!1)&&(!r.shadowRootFilter||r.shadowRootFilter(i));if(d&&v){var m=o(d===!0?i.children:d.children,!0,r);r.flatten?n.push.apply(n,m):n.push({scopeParent:i,candidates:m})}else a.unshift.apply(a,i.children)}}return n},xt=function(e){return!isNaN(parseInt(e.getAttribute("tabindex"),10))},se=function(e){if(!e)throw new Error("No node provided");return e.tabIndex<0&&(/^(AUDIO|VIDEO|DETAILS)$/.test(e.tagName)||ir(e))&&!xt(e)?0:e.tabIndex},or=function(e,t){var r=se(e);return r<0&&t&&!xt(e)?0:r},sr=function(e,t){return e.tabIndex===t.tabIndex?e.documentOrder-t.documentOrder:e.tabIndex-t.tabIndex},Ft=function(e){return e.tagName==="INPUT"},ur=function(e){return Ft(e)&&e.type==="hidden"},lr=function(e){var t=e.tagName==="DETAILS"&&Array.prototype.slice.apply(e.children).some(function(r){return r.tagName==="SUMMARY"});return t},cr=function(e,t){for(var r=0;rsummary:first-of-type"),i=a?e.parentElement:e;if(ue.call(i,"details:not([open]) *"))return!0;if(!r||r==="full"||r==="legacy-full"){if(typeof n=="function"){for(var s=e;e;){var u=e.parentElement,l=Ne(e);if(u&&!u.shadowRoot&&n(u)===!0)return ot(e);e.assignedSlot?e=e.assignedSlot:!u&&l!==e.ownerDocument?e=l.host:e=u}e=s}if(vr(e))return!e.getClientRects().length;if(r!=="legacy-full")return!0}else if(r==="non-zero-area")return ot(e);return!1},mr=function(e){if(/^(INPUT|BUTTON|SELECT|TEXTAREA)$/.test(e.tagName))for(var t=e.parentElement;t;){if(t.tagName==="FIELDSET"&&t.disabled){for(var r=0;r=0)},gr=function o(e){var t=[],r=[];return e.forEach(function(n,a){var i=!!n.scopeParent,s=i?n.scopeParent:n,u=or(s,i),l=i?o(n.candidates):s;u===0?i?t.push.apply(t,l):t.push(s):r.push({documentOrder:a,tabIndex:u,item:n,isScope:i,content:l})}),r.sort(sr).reduce(function(n,a){return a.isScope?n.push.apply(n,a.content):n.push(a.content),n},[]).concat(t)},br=function(e,t){t=t||{};var r;return t.getShadowRoot?r=wt([e],t.includeContainer,{filter:We.bind(null,t),flatten:!1,getShadowRoot:t.getShadowRoot,shadowRootFilter:yr}):r=bt(e,t.includeContainer,We.bind(null,t)),gr(r)},wr=function(e,t){t=t||{};var r;return t.getShadowRoot?r=wt([e],t.includeContainer,{filter:Ie.bind(null,t),flatten:!0,getShadowRoot:t.getShadowRoot}):r=bt(e,t.includeContainer,Ie.bind(null,t)),r},le=function(e,t){if(t=t||{},!e)throw new Error("No node provided");return ue.call(e,Te)===!1?!1:We(t,e)},xr=yt.concat("iframe").join(","),Re=function(e,t){if(t=t||{},!e)throw new Error("No node provided");return ue.call(e,xr)===!1?!1:Ie(t,e)};/*! +* focus-trap 7.5.4 +* @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE +*/function st(o,e){var t=Object.keys(o);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(o);e&&(r=r.filter(function(n){return Object.getOwnPropertyDescriptor(o,n).enumerable})),t.push.apply(t,r)}return t}function ut(o){for(var e=1;e0){var r=e[e.length-1];r!==t&&r.pause()}var n=e.indexOf(t);n===-1||e.splice(n,1),e.push(t)},deactivateTrap:function(e,t){var r=e.indexOf(t);r!==-1&&e.splice(r,1),e.length>0&&e[e.length-1].unpause()}},Ar=function(e){return e.tagName&&e.tagName.toLowerCase()==="input"&&typeof e.select=="function"},Cr=function(e){return(e==null?void 0:e.key)==="Escape"||(e==null?void 0:e.key)==="Esc"||(e==null?void 0:e.keyCode)===27},ge=function(e){return(e==null?void 0:e.key)==="Tab"||(e==null?void 0:e.keyCode)===9},Tr=function(e){return ge(e)&&!e.shiftKey},Nr=function(e){return ge(e)&&e.shiftKey},ct=function(e){return setTimeout(e,0)},ft=function(e,t){var r=-1;return e.every(function(n,a){return t(n)?(r=a,!1):!0}),r},me=function(e){for(var t=arguments.length,r=new Array(t>1?t-1:0),n=1;n1?p-1:0),I=1;I=0)c=r.activeElement;else{var f=i.tabbableGroups[0],p=f&&f.firstTabbableNode;c=p||h("fallbackFocus")}if(!c)throw new Error("Your focus-trap needs to have at least one focusable element");return c},v=function(){if(i.containerGroups=i.containers.map(function(c){var f=br(c,a.tabbableOptions),p=wr(c,a.tabbableOptions),k=f.length>0?f[0]:void 0,I=f.length>0?f[f.length-1]:void 0,M=p.find(function(y){return le(y)}),z=p.slice().reverse().find(function(y){return le(y)}),P=!!f.find(function(y){return se(y)>0});return{container:c,tabbableNodes:f,focusableNodes:p,posTabIndexesFound:P,firstTabbableNode:k,lastTabbableNode:I,firstDomTabbableNode:M,lastDomTabbableNode:z,nextTabbableNode:function(x){var $=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,K=f.indexOf(x);return K<0?$?p.slice(p.indexOf(x)+1).find(function(G){return le(G)}):p.slice(0,p.indexOf(x)).reverse().find(function(G){return le(G)}):f[K+($?1:-1)]}}}),i.tabbableGroups=i.containerGroups.filter(function(c){return c.tabbableNodes.length>0}),i.tabbableGroups.length<=0&&!h("fallbackFocus"))throw new Error("Your focus-trap must have at least one container with at least one tabbable node in it at all times");if(i.containerGroups.find(function(c){return c.posTabIndexesFound})&&i.containerGroups.length>1)throw new Error("At least one node with a positive tabindex was found in one of your focus-trap's multiple containers. Positive tabindexes are only supported in single-container focus-traps.")},m=function w(c){var f=c.activeElement;if(f)return f.shadowRoot&&f.shadowRoot.activeElement!==null?w(f.shadowRoot):f},b=function w(c){if(c!==!1&&c!==m(document)){if(!c||!c.focus){w(d());return}c.focus({preventScroll:!!a.preventScroll}),i.mostRecentlyFocusedNode=c,Ar(c)&&c.select()}},S=function(c){var f=h("setReturnFocus",c);return f||(f===!1?!1:c)},g=function(c){var f=c.target,p=c.event,k=c.isBackward,I=k===void 0?!1:k;f=f||Ae(p),v();var M=null;if(i.tabbableGroups.length>0){var z=l(f,p),P=z>=0?i.containerGroups[z]:void 0;if(z<0)I?M=i.tabbableGroups[i.tabbableGroups.length-1].lastTabbableNode:M=i.tabbableGroups[0].firstTabbableNode;else if(I){var y=ft(i.tabbableGroups,function(B){var J=B.firstTabbableNode;return f===J});if(y<0&&(P.container===f||Re(f,a.tabbableOptions)&&!le(f,a.tabbableOptions)&&!P.nextTabbableNode(f,!1))&&(y=z),y>=0){var x=y===0?i.tabbableGroups.length-1:y-1,$=i.tabbableGroups[x];M=se(f)>=0?$.lastTabbableNode:$.lastDomTabbableNode}else ge(p)||(M=P.nextTabbableNode(f,!1))}else{var K=ft(i.tabbableGroups,function(B){var J=B.lastTabbableNode;return f===J});if(K<0&&(P.container===f||Re(f,a.tabbableOptions)&&!le(f,a.tabbableOptions)&&!P.nextTabbableNode(f))&&(K=z),K>=0){var G=K===i.tabbableGroups.length-1?0:K+1,Q=i.tabbableGroups[G];M=se(f)>=0?Q.firstTabbableNode:Q.firstDomTabbableNode}else ge(p)||(M=P.nextTabbableNode(f))}}else M=h("fallbackFocus");return M},A=function(c){var f=Ae(c);if(!(l(f,c)>=0)){if(me(a.clickOutsideDeactivates,c)){s.deactivate({returnFocus:a.returnFocusOnDeactivate});return}me(a.allowOutsideClick,c)||c.preventDefault()}},T=function(c){var f=Ae(c),p=l(f,c)>=0;if(p||f instanceof Document)p&&(i.mostRecentlyFocusedNode=f);else{c.stopImmediatePropagation();var k,I=!0;if(i.mostRecentlyFocusedNode)if(se(i.mostRecentlyFocusedNode)>0){var M=l(i.mostRecentlyFocusedNode),z=i.containerGroups[M].tabbableNodes;if(z.length>0){var P=z.findIndex(function(y){return y===i.mostRecentlyFocusedNode});P>=0&&(a.isKeyForward(i.recentNavEvent)?P+1=0&&(k=z[P-1],I=!1))}}else i.containerGroups.some(function(y){return y.tabbableNodes.some(function(x){return se(x)>0})})||(I=!1);else I=!1;I&&(k=g({target:i.mostRecentlyFocusedNode,isBackward:a.isKeyBackward(i.recentNavEvent)})),b(k||i.mostRecentlyFocusedNode||d())}i.recentNavEvent=void 0},F=function(c){var f=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1;i.recentNavEvent=c;var p=g({event:c,isBackward:f});p&&(ge(c)&&c.preventDefault(),b(p))},L=function(c){if(Cr(c)&&me(a.escapeDeactivates,c)!==!1){c.preventDefault(),s.deactivate();return}(a.isKeyForward(c)||a.isKeyBackward(c))&&F(c,a.isKeyBackward(c))},R=function(c){var f=Ae(c);l(f,c)>=0||me(a.clickOutsideDeactivates,c)||me(a.allowOutsideClick,c)||(c.preventDefault(),c.stopImmediatePropagation())},V=function(){if(i.active)return lt.activateTrap(n,s),i.delayInitialFocusTimer=a.delayInitialFocus?ct(function(){b(d())}):b(d()),r.addEventListener("focusin",T,!0),r.addEventListener("mousedown",A,{capture:!0,passive:!1}),r.addEventListener("touchstart",A,{capture:!0,passive:!1}),r.addEventListener("click",R,{capture:!0,passive:!1}),r.addEventListener("keydown",L,{capture:!0,passive:!1}),s},N=function(){if(i.active)return r.removeEventListener("focusin",T,!0),r.removeEventListener("mousedown",A,!0),r.removeEventListener("touchstart",A,!0),r.removeEventListener("click",R,!0),r.removeEventListener("keydown",L,!0),s},_=function(c){var f=c.some(function(p){var k=Array.from(p.removedNodes);return k.some(function(I){return I===i.mostRecentlyFocusedNode})});f&&b(d())},C=typeof window<"u"&&"MutationObserver"in window?new MutationObserver(_):void 0,O=function(){C&&(C.disconnect(),i.active&&!i.paused&&i.containers.map(function(c){C.observe(c,{subtree:!0,childList:!0})}))};return s={get active(){return i.active},get paused(){return i.paused},activate:function(c){if(i.active)return this;var f=u(c,"onActivate"),p=u(c,"onPostActivate"),k=u(c,"checkCanFocusTrap");k||v(),i.active=!0,i.paused=!1,i.nodeFocusedBeforeActivation=r.activeElement,f==null||f();var I=function(){k&&v(),V(),O(),p==null||p()};return k?(k(i.containers.concat()).then(I,I),this):(I(),this)},deactivate:function(c){if(!i.active)return this;var f=ut({onDeactivate:a.onDeactivate,onPostDeactivate:a.onPostDeactivate,checkCanReturnFocus:a.checkCanReturnFocus},c);clearTimeout(i.delayInitialFocusTimer),i.delayInitialFocusTimer=void 0,N(),i.active=!1,i.paused=!1,O(),lt.deactivateTrap(n,s);var p=u(f,"onDeactivate"),k=u(f,"onPostDeactivate"),I=u(f,"checkCanReturnFocus"),M=u(f,"returnFocus","returnFocusOnDeactivate");p==null||p();var z=function(){ct(function(){M&&b(S(i.nodeFocusedBeforeActivation)),k==null||k()})};return M&&I?(I(S(i.nodeFocusedBeforeActivation)).then(z,z),this):(z(),this)},pause:function(c){if(i.paused||!i.active)return this;var f=u(c,"onPause"),p=u(c,"onPostPause");return i.paused=!0,f==null||f(),N(),O(),p==null||p(),this},unpause:function(c){if(!i.paused||!i.active)return this;var f=u(c,"onUnpause"),p=u(c,"onPostUnpause");return i.paused=!1,f==null||f(),v(),V(),O(),p==null||p(),this},updateContainerElements:function(c){var f=[].concat(c).filter(Boolean);return i.containers=f.map(function(p){return typeof p=="string"?r.querySelector(p):p}),i.active&&v(),O(),this}},s.updateContainerElements(e),s};function Dr(o,e={}){let t;const{immediate:r,...n}=e,a=oe(!1),i=oe(!1),s=d=>t&&t.activate(d),u=d=>t&&t.deactivate(d),l=()=>{t&&(t.pause(),i.value=!0)},h=()=>{t&&(t.unpause(),i.value=!1)};return $e(()=>Dt(o),d=>{d&&(t=Ir(d,{...n,onActivate(){a.value=!0,e.onActivate&&e.onActivate()},onDeactivate(){a.value=!1,e.onDeactivate&&e.onDeactivate()}}),r&&s())},{flush:"post"}),Ot(()=>u()),{hasFocus:a,isPaused:i,activate:s,deactivate:u,pause:l,unpause:h}}class fe{constructor(e,t=!0,r=[],n=5e3){this.ctx=e,this.iframes=t,this.exclude=r,this.iframesTimeout=n}static matches(e,t){const r=typeof t=="string"?[t]:t,n=e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.oMatchesSelector||e.webkitMatchesSelector;if(n){let a=!1;return r.every(i=>n.call(e,i)?(a=!0,!1):!0),a}else return!1}getContexts(){let e,t=[];return typeof this.ctx>"u"||!this.ctx?e=[]:NodeList.prototype.isPrototypeOf(this.ctx)?e=Array.prototype.slice.call(this.ctx):Array.isArray(this.ctx)?e=this.ctx:typeof this.ctx=="string"?e=Array.prototype.slice.call(document.querySelectorAll(this.ctx)):e=[this.ctx],e.forEach(r=>{const n=t.filter(a=>a.contains(r)).length>0;t.indexOf(r)===-1&&!n&&t.push(r)}),t}getIframeContents(e,t,r=()=>{}){let n;try{const a=e.contentWindow;if(n=a.document,!a||!n)throw new Error("iframe inaccessible")}catch{r()}n&&t(n)}isIframeBlank(e){const t="about:blank",r=e.getAttribute("src").trim();return e.contentWindow.location.href===t&&r!==t&&r}observeIframeLoad(e,t,r){let n=!1,a=null;const i=()=>{if(!n){n=!0,clearTimeout(a);try{this.isIframeBlank(e)||(e.removeEventListener("load",i),this.getIframeContents(e,t,r))}catch{r()}}};e.addEventListener("load",i),a=setTimeout(i,this.iframesTimeout)}onIframeReady(e,t,r){try{e.contentWindow.document.readyState==="complete"?this.isIframeBlank(e)?this.observeIframeLoad(e,t,r):this.getIframeContents(e,t,r):this.observeIframeLoad(e,t,r)}catch{r()}}waitForIframes(e,t){let r=0;this.forEachIframe(e,()=>!0,n=>{r++,this.waitForIframes(n.querySelector("html"),()=>{--r||t()})},n=>{n||t()})}forEachIframe(e,t,r,n=()=>{}){let a=e.querySelectorAll("iframe"),i=a.length,s=0;a=Array.prototype.slice.call(a);const u=()=>{--i<=0&&n(s)};i||u(),a.forEach(l=>{fe.matches(l,this.exclude)?u():this.onIframeReady(l,h=>{t(l)&&(s++,r(h)),u()},u)})}createIterator(e,t,r){return document.createNodeIterator(e,t,r,!1)}createInstanceOnIframe(e){return new fe(e.querySelector("html"),this.iframes)}compareNodeIframe(e,t,r){const n=e.compareDocumentPosition(r),a=Node.DOCUMENT_POSITION_PRECEDING;if(n&a)if(t!==null){const i=t.compareDocumentPosition(r),s=Node.DOCUMENT_POSITION_FOLLOWING;if(i&s)return!0}else return!0;return!1}getIteratorNode(e){const t=e.previousNode();let r;return t===null?r=e.nextNode():r=e.nextNode()&&e.nextNode(),{prevNode:t,node:r}}checkIframeFilter(e,t,r,n){let a=!1,i=!1;return n.forEach((s,u)=>{s.val===r&&(a=u,i=s.handled)}),this.compareNodeIframe(e,t,r)?(a===!1&&!i?n.push({val:r,handled:!0}):a!==!1&&!i&&(n[a].handled=!0),!0):(a===!1&&n.push({val:r,handled:!1}),!1)}handleOpenIframes(e,t,r,n){e.forEach(a=>{a.handled||this.getIframeContents(a.val,i=>{this.createInstanceOnIframe(i).forEachNode(t,r,n)})})}iterateThroughNodes(e,t,r,n,a){const i=this.createIterator(t,e,n);let s=[],u=[],l,h,d=()=>({prevNode:h,node:l}=this.getIteratorNode(i),l);for(;d();)this.iframes&&this.forEachIframe(t,v=>this.checkIframeFilter(l,h,v,s),v=>{this.createInstanceOnIframe(v).forEachNode(e,m=>u.push(m),n)}),u.push(l);u.forEach(v=>{r(v)}),this.iframes&&this.handleOpenIframes(s,e,r,n),a()}forEachNode(e,t,r,n=()=>{}){const a=this.getContexts();let i=a.length;i||n(),a.forEach(s=>{const u=()=>{this.iterateThroughNodes(e,s,t,r,()=>{--i<=0&&n()})};this.iframes?this.waitForIframes(s,u):u()})}}let Or=class{constructor(e){this.ctx=e,this.ie=!1;const t=window.navigator.userAgent;(t.indexOf("MSIE")>-1||t.indexOf("Trident")>-1)&&(this.ie=!0)}set opt(e){this._opt=Object.assign({},{element:"",className:"",exclude:[],iframes:!1,iframesTimeout:5e3,separateWordSearch:!0,diacritics:!0,synonyms:{},accuracy:"partially",acrossElements:!1,caseSensitive:!1,ignoreJoiners:!1,ignoreGroups:0,ignorePunctuation:[],wildcards:"disabled",each:()=>{},noMatch:()=>{},filter:()=>!0,done:()=>{},debug:!1,log:window.console},e)}get opt(){return this._opt}get iterator(){return new fe(this.ctx,this.opt.iframes,this.opt.exclude,this.opt.iframesTimeout)}log(e,t="debug"){const r=this.opt.log;this.opt.debug&&typeof r=="object"&&typeof r[t]=="function"&&r[t](`mark.js: ${e}`)}escapeStr(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}createRegExp(e){return this.opt.wildcards!=="disabled"&&(e=this.setupWildcardsRegExp(e)),e=this.escapeStr(e),Object.keys(this.opt.synonyms).length&&(e=this.createSynonymsRegExp(e)),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),this.opt.diacritics&&(e=this.createDiacriticsRegExp(e)),e=this.createMergedBlanksRegExp(e),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.createJoinersRegExp(e)),this.opt.wildcards!=="disabled"&&(e=this.createWildcardsRegExp(e)),e=this.createAccuracyRegExp(e),e}createSynonymsRegExp(e){const t=this.opt.synonyms,r=this.opt.caseSensitive?"":"i",n=this.opt.ignoreJoiners||this.opt.ignorePunctuation.length?"\0":"";for(let a in t)if(t.hasOwnProperty(a)){const i=t[a],s=this.opt.wildcards!=="disabled"?this.setupWildcardsRegExp(a):this.escapeStr(a),u=this.opt.wildcards!=="disabled"?this.setupWildcardsRegExp(i):this.escapeStr(i);s!==""&&u!==""&&(e=e.replace(new RegExp(`(${this.escapeStr(s)}|${this.escapeStr(u)})`,`gm${r}`),n+`(${this.processSynomyms(s)}|${this.processSynomyms(u)})`+n))}return e}processSynomyms(e){return(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),e}setupWildcardsRegExp(e){return e=e.replace(/(?:\\)*\?/g,t=>t.charAt(0)==="\\"?"?":""),e.replace(/(?:\\)*\*/g,t=>t.charAt(0)==="\\"?"*":"")}createWildcardsRegExp(e){let t=this.opt.wildcards==="withSpaces";return e.replace(/\u0001/g,t?"[\\S\\s]?":"\\S?").replace(/\u0002/g,t?"[\\S\\s]*?":"\\S*")}setupIgnoreJoinersRegExp(e){return e.replace(/[^(|)\\]/g,(t,r,n)=>{let a=n.charAt(r+1);return/[(|)\\]/.test(a)||a===""?t:t+"\0"})}createJoinersRegExp(e){let t=[];const r=this.opt.ignorePunctuation;return Array.isArray(r)&&r.length&&t.push(this.escapeStr(r.join(""))),this.opt.ignoreJoiners&&t.push("\\u00ad\\u200b\\u200c\\u200d"),t.length?e.split(/\u0000+/).join(`[${t.join("")}]*`):e}createDiacriticsRegExp(e){const t=this.opt.caseSensitive?"":"i",r=this.opt.caseSensitive?["aàáảãạăằắẳẵặâầấẩẫậäåāą","AÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ","cçćč","CÇĆČ","dđď","DĐĎ","eèéẻẽẹêềếểễệëěēę","EÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ","iìíỉĩịîïī","IÌÍỈĨỊÎÏĪ","lł","LŁ","nñňń","NÑŇŃ","oòóỏõọôồốổỗộơởỡớờợöøō","OÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ","rř","RŘ","sšśșş","SŠŚȘŞ","tťțţ","TŤȚŢ","uùúủũụưừứửữựûüůū","UÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ","yýỳỷỹỵÿ","YÝỲỶỸỴŸ","zžżź","ZŽŻŹ"]:["aàáảãạăằắẳẵặâầấẩẫậäåāąAÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ","cçćčCÇĆČ","dđďDĐĎ","eèéẻẽẹêềếểễệëěēęEÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ","iìíỉĩịîïīIÌÍỈĨỊÎÏĪ","lłLŁ","nñňńNÑŇŃ","oòóỏõọôồốổỗộơởỡớờợöøōOÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ","rřRŘ","sšśșşSŠŚȘŞ","tťțţTŤȚŢ","uùúủũụưừứửữựûüůūUÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ","yýỳỷỹỵÿYÝỲỶỸỴŸ","zžżźZŽŻŹ"];let n=[];return e.split("").forEach(a=>{r.every(i=>{if(i.indexOf(a)!==-1){if(n.indexOf(i)>-1)return!1;e=e.replace(new RegExp(`[${i}]`,`gm${t}`),`[${i}]`),n.push(i)}return!0})}),e}createMergedBlanksRegExp(e){return e.replace(/[\s]+/gmi,"[\\s]+")}createAccuracyRegExp(e){const t="!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~¡¿";let r=this.opt.accuracy,n=typeof r=="string"?r:r.value,a=typeof r=="string"?[]:r.limiters,i="";switch(a.forEach(s=>{i+=`|${this.escapeStr(s)}`}),n){case"partially":default:return`()(${e})`;case"complementary":return i="\\s"+(i||this.escapeStr(t)),`()([^${i}]*${e}[^${i}]*)`;case"exactly":return`(^|\\s${i})(${e})(?=$|\\s${i})`}}getSeparatedKeywords(e){let t=[];return e.forEach(r=>{this.opt.separateWordSearch?r.split(" ").forEach(n=>{n.trim()&&t.indexOf(n)===-1&&t.push(n)}):r.trim()&&t.indexOf(r)===-1&&t.push(r)}),{keywords:t.sort((r,n)=>n.length-r.length),length:t.length}}isNumeric(e){return Number(parseFloat(e))==e}checkRanges(e){if(!Array.isArray(e)||Object.prototype.toString.call(e[0])!=="[object Object]")return this.log("markRanges() will only accept an array of objects"),this.opt.noMatch(e),[];const t=[];let r=0;return e.sort((n,a)=>n.start-a.start).forEach(n=>{let{start:a,end:i,valid:s}=this.callNoMatchOnInvalidRanges(n,r);s&&(n.start=a,n.length=i-a,t.push(n),r=i)}),t}callNoMatchOnInvalidRanges(e,t){let r,n,a=!1;return e&&typeof e.start<"u"?(r=parseInt(e.start,10),n=r+parseInt(e.length,10),this.isNumeric(e.start)&&this.isNumeric(e.length)&&n-t>0&&n-r>0?a=!0:(this.log(`Ignoring invalid or overlapping range: ${JSON.stringify(e)}`),this.opt.noMatch(e))):(this.log(`Ignoring invalid range: ${JSON.stringify(e)}`),this.opt.noMatch(e)),{start:r,end:n,valid:a}}checkWhitespaceRanges(e,t,r){let n,a=!0,i=r.length,s=t-i,u=parseInt(e.start,10)-s;return u=u>i?i:u,n=u+parseInt(e.length,10),n>i&&(n=i,this.log(`End range automatically set to the max value of ${i}`)),u<0||n-u<0||u>i||n>i?(a=!1,this.log(`Invalid range: ${JSON.stringify(e)}`),this.opt.noMatch(e)):r.substring(u,n).replace(/\s+/g,"")===""&&(a=!1,this.log("Skipping whitespace only range: "+JSON.stringify(e)),this.opt.noMatch(e)),{start:u,end:n,valid:a}}getTextNodes(e){let t="",r=[];this.iterator.forEachNode(NodeFilter.SHOW_TEXT,n=>{r.push({start:t.length,end:(t+=n.textContent).length,node:n})},n=>this.matchesExclude(n.parentNode)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT,()=>{e({value:t,nodes:r})})}matchesExclude(e){return fe.matches(e,this.opt.exclude.concat(["script","style","title","head","html"]))}wrapRangeInTextNode(e,t,r){const n=this.opt.element?this.opt.element:"mark",a=e.splitText(t),i=a.splitText(r-t);let s=document.createElement(n);return s.setAttribute("data-markjs","true"),this.opt.className&&s.setAttribute("class",this.opt.className),s.textContent=a.textContent,a.parentNode.replaceChild(s,a),i}wrapRangeInMappedTextNode(e,t,r,n,a){e.nodes.every((i,s)=>{const u=e.nodes[s+1];if(typeof u>"u"||u.start>t){if(!n(i.node))return!1;const l=t-i.start,h=(r>i.end?i.end:r)-i.start,d=e.value.substr(0,i.start),v=e.value.substr(h+i.start);if(i.node=this.wrapRangeInTextNode(i.node,l,h),e.value=d+v,e.nodes.forEach((m,b)=>{b>=s&&(e.nodes[b].start>0&&b!==s&&(e.nodes[b].start-=h),e.nodes[b].end-=h)}),r-=h,a(i.node.previousSibling,i.start),r>i.end)t=i.end;else return!1}return!0})}wrapMatches(e,t,r,n,a){const i=t===0?0:t+1;this.getTextNodes(s=>{s.nodes.forEach(u=>{u=u.node;let l;for(;(l=e.exec(u.textContent))!==null&&l[i]!=="";){if(!r(l[i],u))continue;let h=l.index;if(i!==0)for(let d=1;d{let u;for(;(u=e.exec(s.value))!==null&&u[i]!=="";){let l=u.index;if(i!==0)for(let d=1;dr(u[i],d),(d,v)=>{e.lastIndex=v,n(d)})}a()})}wrapRangeFromIndex(e,t,r,n){this.getTextNodes(a=>{const i=a.value.length;e.forEach((s,u)=>{let{start:l,end:h,valid:d}=this.checkWhitespaceRanges(s,i,a.value);d&&this.wrapRangeInMappedTextNode(a,l,h,v=>t(v,s,a.value.substring(l,h),u),v=>{r(v,s)})}),n()})}unwrapMatches(e){const t=e.parentNode;let r=document.createDocumentFragment();for(;e.firstChild;)r.appendChild(e.removeChild(e.firstChild));t.replaceChild(r,e),this.ie?this.normalizeTextNode(t):t.normalize()}normalizeTextNode(e){if(e){if(e.nodeType===3)for(;e.nextSibling&&e.nextSibling.nodeType===3;)e.nodeValue+=e.nextSibling.nodeValue,e.parentNode.removeChild(e.nextSibling);else this.normalizeTextNode(e.firstChild);this.normalizeTextNode(e.nextSibling)}}markRegExp(e,t){this.opt=t,this.log(`Searching with expression "${e}"`);let r=0,n="wrapMatches";const a=i=>{r++,this.opt.each(i)};this.opt.acrossElements&&(n="wrapMatchesAcrossElements"),this[n](e,this.opt.ignoreGroups,(i,s)=>this.opt.filter(s,i,r),a,()=>{r===0&&this.opt.noMatch(e),this.opt.done(r)})}mark(e,t){this.opt=t;let r=0,n="wrapMatches";const{keywords:a,length:i}=this.getSeparatedKeywords(typeof e=="string"?[e]:e),s=this.opt.caseSensitive?"":"i",u=l=>{let h=new RegExp(this.createRegExp(l),`gm${s}`),d=0;this.log(`Searching with expression "${h}"`),this[n](h,1,(v,m)=>this.opt.filter(m,l,r,d),v=>{d++,r++,this.opt.each(v)},()=>{d===0&&this.opt.noMatch(l),a[i-1]===l?this.opt.done(r):u(a[a.indexOf(l)+1])})};this.opt.acrossElements&&(n="wrapMatchesAcrossElements"),i===0?this.opt.done(r):u(a[0])}markRanges(e,t){this.opt=t;let r=0,n=this.checkRanges(e);n&&n.length?(this.log("Starting to mark with the following ranges: "+JSON.stringify(n)),this.wrapRangeFromIndex(n,(a,i,s,u)=>this.opt.filter(a,i,s,u),(a,i)=>{r++,this.opt.each(a,i)},()=>{this.opt.done(r)})):this.opt.done(r)}unmark(e){this.opt=e;let t=this.opt.element?this.opt.element:"*";t+="[data-markjs]",this.opt.className&&(t+=`.${this.opt.className}`),this.log(`Removal selector "${t}"`),this.iterator.forEachNode(NodeFilter.SHOW_ELEMENT,r=>{this.unwrapMatches(r)},r=>{const n=fe.matches(r,t),a=this.matchesExclude(r);return!n||a?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT},this.opt.done)}};function _r(o){const e=new Or(o);return this.mark=(t,r)=>(e.mark(t,r),this),this.markRegExp=(t,r)=>(e.markRegExp(t,r),this),this.markRanges=(t,r)=>(e.markRanges(t,r),this),this.unmark=t=>(e.unmark(t),this),this}var W=function(){return W=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0&&a[a.length-1])&&(l[0]===6||l[0]===2)){t=0;continue}if(l[0]===3&&(!a||l[1]>a[0]&&l[1]=o.length&&(o=void 0),{value:o&&o[r++],done:!o}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}function j(o,e){var t=typeof Symbol=="function"&&o[Symbol.iterator];if(!t)return o;var r=t.call(o),n,a=[],i;try{for(;(e===void 0||e-- >0)&&!(n=r.next()).done;)a.push(n.value)}catch(s){i={error:s}}finally{try{n&&!n.done&&(t=r.return)&&t.call(r)}finally{if(i)throw i.error}}return a}var Lr="ENTRIES",Et="KEYS",St="VALUES",H="",Me=function(){function o(e,t){var r=e._tree,n=Array.from(r.keys());this.set=e,this._type=t,this._path=n.length>0?[{node:r,keys:n}]:[]}return o.prototype.next=function(){var e=this.dive();return this.backtrack(),e},o.prototype.dive=function(){if(this._path.length===0)return{done:!0,value:void 0};var e=ce(this._path),t=e.node,r=e.keys;if(ce(r)===H)return{done:!1,value:this.result()};var n=t.get(ce(r));return this._path.push({node:n,keys:Array.from(n.keys())}),this.dive()},o.prototype.backtrack=function(){if(this._path.length!==0){var e=ce(this._path).keys;e.pop(),!(e.length>0)&&(this._path.pop(),this.backtrack())}},o.prototype.key=function(){return this.set._prefix+this._path.map(function(e){var t=e.keys;return ce(t)}).filter(function(e){return e!==H}).join("")},o.prototype.value=function(){return ce(this._path).node.get(H)},o.prototype.result=function(){switch(this._type){case St:return this.value();case Et:return this.key();default:return[this.key(),this.value()]}},o.prototype[Symbol.iterator]=function(){return this},o}(),ce=function(o){return o[o.length-1]},zr=function(o,e,t){var r=new Map;if(e===void 0)return r;for(var n=e.length+1,a=n+t,i=new Uint8Array(a*n).fill(t+1),s=0;st)continue e}At(o.get(m),e,t,r,n,S,i,s+m)}}}catch(f){u={error:f}}finally{try{v&&!v.done&&(l=d.return)&&l.call(d)}finally{if(u)throw u.error}}},Le=function(){function o(e,t){e===void 0&&(e=new Map),t===void 0&&(t=""),this._size=void 0,this._tree=e,this._prefix=t}return o.prototype.atPrefix=function(e){var t,r;if(!e.startsWith(this._prefix))throw new Error("Mismatched prefix");var n=j(De(this._tree,e.slice(this._prefix.length)),2),a=n[0],i=n[1];if(a===void 0){var s=j(Ue(i),2),u=s[0],l=s[1];try{for(var h=D(u.keys()),d=h.next();!d.done;d=h.next()){var v=d.value;if(v!==H&&v.startsWith(l)){var m=new Map;return m.set(v.slice(l.length),u.get(v)),new o(m,e)}}}catch(b){t={error:b}}finally{try{d&&!d.done&&(r=h.return)&&r.call(h)}finally{if(t)throw t.error}}}return new o(a,e)},o.prototype.clear=function(){this._size=void 0,this._tree.clear()},o.prototype.delete=function(e){return this._size=void 0,Pr(this._tree,e)},o.prototype.entries=function(){return new Me(this,Lr)},o.prototype.forEach=function(e){var t,r;try{for(var n=D(this),a=n.next();!a.done;a=n.next()){var i=j(a.value,2),s=i[0],u=i[1];e(s,u,this)}}catch(l){t={error:l}}finally{try{a&&!a.done&&(r=n.return)&&r.call(n)}finally{if(t)throw t.error}}},o.prototype.fuzzyGet=function(e,t){return zr(this._tree,e,t)},o.prototype.get=function(e){var t=Ke(this._tree,e);return t!==void 0?t.get(H):void 0},o.prototype.has=function(e){var t=Ke(this._tree,e);return t!==void 0&&t.has(H)},o.prototype.keys=function(){return new Me(this,Et)},o.prototype.set=function(e,t){if(typeof e!="string")throw new Error("key must be a string");this._size=void 0;var r=ze(this._tree,e);return r.set(H,t),this},Object.defineProperty(o.prototype,"size",{get:function(){if(this._size)return this._size;this._size=0;for(var e=this.entries();!e.next().done;)this._size+=1;return this._size},enumerable:!1,configurable:!0}),o.prototype.update=function(e,t){if(typeof e!="string")throw new Error("key must be a string");this._size=void 0;var r=ze(this._tree,e);return r.set(H,t(r.get(H))),this},o.prototype.fetch=function(e,t){if(typeof e!="string")throw new Error("key must be a string");this._size=void 0;var r=ze(this._tree,e),n=r.get(H);return n===void 0&&r.set(H,n=t()),n},o.prototype.values=function(){return new Me(this,St)},o.prototype[Symbol.iterator]=function(){return this.entries()},o.from=function(e){var t,r,n=new o;try{for(var a=D(e),i=a.next();!i.done;i=a.next()){var s=j(i.value,2),u=s[0],l=s[1];n.set(u,l)}}catch(h){t={error:h}}finally{try{i&&!i.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}return n},o.fromObject=function(e){return o.from(Object.entries(e))},o}(),De=function(o,e,t){var r,n;if(t===void 0&&(t=[]),e.length===0||o==null)return[o,t];try{for(var a=D(o.keys()),i=a.next();!i.done;i=a.next()){var s=i.value;if(s!==H&&e.startsWith(s))return t.push([o,s]),De(o.get(s),e.slice(s.length),t)}}catch(u){r={error:u}}finally{try{i&&!i.done&&(n=a.return)&&n.call(a)}finally{if(r)throw r.error}}return t.push([o,e]),De(void 0,"",t)},Ke=function(o,e){var t,r;if(e.length===0||o==null)return o;try{for(var n=D(o.keys()),a=n.next();!a.done;a=n.next()){var i=a.value;if(i!==H&&e.startsWith(i))return Ke(o.get(i),e.slice(i.length))}}catch(s){t={error:s}}finally{try{a&&!a.done&&(r=n.return)&&r.call(n)}finally{if(t)throw t.error}}},ze=function(o,e){var t,r,n=e.length;e:for(var a=0;o&&a0)throw new Error("Expected documents to be present. Omit the argument to remove all documents.");this._index=new Le,this._documentCount=0,this._documentIds=new Map,this._idToShortId=new Map,this._fieldLength=new Map,this._avgFieldLength=[],this._storedFields=new Map,this._nextId=0}},o.prototype.discard=function(e){var t=this,r=this._idToShortId.get(e);if(r==null)throw new Error("MiniSearch: cannot discard document with ID ".concat(e,": it is not in the index"));this._idToShortId.delete(e),this._documentIds.delete(r),this._storedFields.delete(r),(this._fieldLength.get(r)||[]).forEach(function(n,a){t.removeFieldLength(r,a,t._documentCount,n)}),this._fieldLength.delete(r),this._documentCount-=1,this._dirtCount+=1,this.maybeAutoVacuum()},o.prototype.maybeAutoVacuum=function(){if(this._options.autoVacuum!==!1){var e=this._options.autoVacuum,t=e.minDirtFactor,r=e.minDirtCount,n=e.batchSize,a=e.batchWait;this.conditionalVacuum({batchSize:n,batchWait:a},{minDirtCount:r,minDirtFactor:t})}},o.prototype.discardAll=function(e){var t,r,n=this._options.autoVacuum;try{this._options.autoVacuum=!1;try{for(var a=D(e),i=a.next();!i.done;i=a.next()){var s=i.value;this.discard(s)}}catch(u){t={error:u}}finally{try{i&&!i.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}}finally{this._options.autoVacuum=n}this.maybeAutoVacuum()},o.prototype.replace=function(e){var t=this._options,r=t.idField,n=t.extractField,a=n(e,r);this.discard(a),this.add(e)},o.prototype.vacuum=function(e){return e===void 0&&(e={}),this.conditionalVacuum(e)},o.prototype.conditionalVacuum=function(e,t){var r=this;return this._currentVacuum?(this._enqueuedVacuumConditions=this._enqueuedVacuumConditions&&t,this._enqueuedVacuum!=null?this._enqueuedVacuum:(this._enqueuedVacuum=this._currentVacuum.then(function(){var n=r._enqueuedVacuumConditions;return r._enqueuedVacuumConditions=Je,r.performVacuuming(e,n)}),this._enqueuedVacuum)):this.vacuumConditionsMet(t)===!1?Promise.resolve():(this._currentVacuum=this.performVacuuming(e),this._currentVacuum)},o.prototype.performVacuuming=function(e,t){return Rr(this,void 0,void 0,function(){var r,n,a,i,s,u,l,h,d,v,m,b,S,g,A,T,F,L,R,V,N,_,C,O,w;return Mr(this,function(c){switch(c.label){case 0:if(r=this._dirtCount,!this.vacuumConditionsMet(t))return[3,10];n=e.batchSize||je.batchSize,a=e.batchWait||je.batchWait,i=1,c.label=1;case 1:c.trys.push([1,7,8,9]),s=D(this._index),u=s.next(),c.label=2;case 2:if(u.done)return[3,6];l=j(u.value,2),h=l[0],d=l[1];try{for(v=(_=void 0,D(d)),m=v.next();!m.done;m=v.next()){b=j(m.value,2),S=b[0],g=b[1];try{for(A=(O=void 0,D(g)),T=A.next();!T.done;T=A.next())F=j(T.value,1),L=F[0],!this._documentIds.has(L)&&(g.size<=1?d.delete(S):g.delete(L))}catch(f){O={error:f}}finally{try{T&&!T.done&&(w=A.return)&&w.call(A)}finally{if(O)throw O.error}}}}catch(f){_={error:f}}finally{try{m&&!m.done&&(C=v.return)&&C.call(v)}finally{if(_)throw _.error}}return this._index.get(h).size===0&&this._index.delete(h),i%n!==0?[3,4]:[4,new Promise(function(f){return setTimeout(f,a)})];case 3:c.sent(),c.label=4;case 4:i+=1,c.label=5;case 5:return u=s.next(),[3,2];case 6:return[3,9];case 7:return R=c.sent(),V={error:R},[3,9];case 8:try{u&&!u.done&&(N=s.return)&&N.call(s)}finally{if(V)throw V.error}return[7];case 9:this._dirtCount-=r,c.label=10;case 10:return[4,null];case 11:return c.sent(),this._currentVacuum=this._enqueuedVacuum,this._enqueuedVacuum=null,[2]}})})},o.prototype.vacuumConditionsMet=function(e){if(e==null)return!0;var t=e.minDirtCount,r=e.minDirtFactor;return t=t||Ve.minDirtCount,r=r||Ve.minDirtFactor,this.dirtCount>=t&&this.dirtFactor>=r},Object.defineProperty(o.prototype,"isVacuuming",{get:function(){return this._currentVacuum!=null},enumerable:!1,configurable:!0}),Object.defineProperty(o.prototype,"dirtCount",{get:function(){return this._dirtCount},enumerable:!1,configurable:!0}),Object.defineProperty(o.prototype,"dirtFactor",{get:function(){return this._dirtCount/(1+this._documentCount+this._dirtCount)},enumerable:!1,configurable:!0}),o.prototype.has=function(e){return this._idToShortId.has(e)},o.prototype.getStoredFields=function(e){var t=this._idToShortId.get(e);if(t!=null)return this._storedFields.get(t)},o.prototype.search=function(e,t){var r,n;t===void 0&&(t={});var a=this.executeQuery(e,t),i=[];try{for(var s=D(a),u=s.next();!u.done;u=s.next()){var l=j(u.value,2),h=l[0],d=l[1],v=d.score,m=d.terms,b=d.match,S=m.length||1,g={id:this._documentIds.get(h),score:v*S,terms:Object.keys(b),queryTerms:m,match:b};Object.assign(g,this._storedFields.get(h)),(t.filter==null||t.filter(g))&&i.push(g)}}catch(A){r={error:A}}finally{try{u&&!u.done&&(n=s.return)&&n.call(s)}finally{if(r)throw r.error}}return e===o.wildcard&&t.boostDocument==null&&this._options.searchOptions.boostDocument==null||i.sort(vt),i},o.prototype.autoSuggest=function(e,t){var r,n,a,i;t===void 0&&(t={}),t=W(W({},this._options.autoSuggestOptions),t);var s=new Map;try{for(var u=D(this.search(e,t)),l=u.next();!l.done;l=u.next()){var h=l.value,d=h.score,v=h.terms,m=v.join(" "),b=s.get(m);b!=null?(b.score+=d,b.count+=1):s.set(m,{score:d,terms:v,count:1})}}catch(R){r={error:R}}finally{try{l&&!l.done&&(n=u.return)&&n.call(u)}finally{if(r)throw r.error}}var S=[];try{for(var g=D(s),A=g.next();!A.done;A=g.next()){var T=j(A.value,2),b=T[0],F=T[1],d=F.score,v=F.terms,L=F.count;S.push({suggestion:b,terms:v,score:d/L})}}catch(R){a={error:R}}finally{try{A&&!A.done&&(i=g.return)&&i.call(g)}finally{if(a)throw a.error}}return S.sort(vt),S},Object.defineProperty(o.prototype,"documentCount",{get:function(){return this._documentCount},enumerable:!1,configurable:!0}),Object.defineProperty(o.prototype,"termCount",{get:function(){return this._index.size},enumerable:!1,configurable:!0}),o.loadJSON=function(e,t){if(t==null)throw new Error("MiniSearch: loadJSON should be given the same options used when serializing the index");return this.loadJS(JSON.parse(e),t)},o.getDefault=function(e){if(Be.hasOwnProperty(e))return Pe(Be,e);throw new Error('MiniSearch: unknown option "'.concat(e,'"'))},o.loadJS=function(e,t){var r,n,a,i,s,u,l=e.index,h=e.documentCount,d=e.nextId,v=e.documentIds,m=e.fieldIds,b=e.fieldLength,S=e.averageFieldLength,g=e.storedFields,A=e.dirtCount,T=e.serializationVersion;if(T!==1&&T!==2)throw new Error("MiniSearch: cannot deserialize an index created with an incompatible version");var F=new o(t);F._documentCount=h,F._nextId=d,F._documentIds=Ce(v),F._idToShortId=new Map,F._fieldIds=m,F._fieldLength=Ce(b),F._avgFieldLength=S,F._storedFields=Ce(g),F._dirtCount=A||0,F._index=new Le;try{for(var L=D(F._documentIds),R=L.next();!R.done;R=L.next()){var V=j(R.value,2),N=V[0],_=V[1];F._idToShortId.set(_,N)}}catch(P){r={error:P}}finally{try{R&&!R.done&&(n=L.return)&&n.call(L)}finally{if(r)throw r.error}}try{for(var C=D(l),O=C.next();!O.done;O=C.next()){var w=j(O.value,2),c=w[0],f=w[1],p=new Map;try{for(var k=(s=void 0,D(Object.keys(f))),I=k.next();!I.done;I=k.next()){var M=I.value,z=f[M];T===1&&(z=z.ds),p.set(parseInt(M,10),Ce(z))}}catch(P){s={error:P}}finally{try{I&&!I.done&&(u=k.return)&&u.call(k)}finally{if(s)throw s.error}}F._index.set(c,p)}}catch(P){a={error:P}}finally{try{O&&!O.done&&(i=C.return)&&i.call(C)}finally{if(a)throw a.error}}return F},o.prototype.executeQuery=function(e,t){var r=this;if(t===void 0&&(t={}),e===o.wildcard)return this.executeWildcardQuery(t);if(typeof e!="string"){var n=W(W(W({},t),e),{queries:void 0}),a=e.queries.map(function(g){return r.executeQuery(g,n)});return this.combineResults(a,n.combineWith)}var i=this._options,s=i.tokenize,u=i.processTerm,l=i.searchOptions,h=W(W({tokenize:s,processTerm:u},l),t),d=h.tokenize,v=h.processTerm,m=d(e).flatMap(function(g){return v(g)}).filter(function(g){return!!g}),b=m.map(jr(h)),S=b.map(function(g){return r.executeQuerySpec(g,h)});return this.combineResults(S,h.combineWith)},o.prototype.executeQuerySpec=function(e,t){var r,n,a,i,s=W(W({},this._options.searchOptions),t),u=(s.fields||this._options.fields).reduce(function(M,z){var P;return W(W({},M),(P={},P[z]=Pe(s.boost,z)||1,P))},{}),l=s.boostDocument,h=s.weights,d=s.maxFuzzy,v=s.bm25,m=W(W({},ht.weights),h),b=m.fuzzy,S=m.prefix,g=this._index.get(e.term),A=this.termResults(e.term,e.term,1,g,u,l,v),T,F;if(e.prefix&&(T=this._index.atPrefix(e.term)),e.fuzzy){var L=e.fuzzy===!0?.2:e.fuzzy,R=L<1?Math.min(d,Math.round(e.term.length*L)):L;R&&(F=this._index.fuzzyGet(e.term,R))}if(T)try{for(var V=D(T),N=V.next();!N.done;N=V.next()){var _=j(N.value,2),C=_[0],O=_[1],w=C.length-e.term.length;if(w){F==null||F.delete(C);var c=S*C.length/(C.length+.3*w);this.termResults(e.term,C,c,O,u,l,v,A)}}}catch(M){r={error:M}}finally{try{N&&!N.done&&(n=V.return)&&n.call(V)}finally{if(r)throw r.error}}if(F)try{for(var f=D(F.keys()),p=f.next();!p.done;p=f.next()){var C=p.value,k=j(F.get(C),2),I=k[0],w=k[1];if(w){var c=b*C.length/(C.length+w);this.termResults(e.term,C,c,I,u,l,v,A)}}}catch(M){a={error:M}}finally{try{p&&!p.done&&(i=f.return)&&i.call(f)}finally{if(a)throw a.error}}return A},o.prototype.executeWildcardQuery=function(e){var t,r,n=new Map,a=W(W({},this._options.searchOptions),e);try{for(var i=D(this._documentIds),s=i.next();!s.done;s=i.next()){var u=j(s.value,2),l=u[0],h=u[1],d=a.boostDocument?a.boostDocument(h,"",this._storedFields.get(l)):1;n.set(l,{score:d,terms:[],match:{}})}}catch(v){t={error:v}}finally{try{s&&!s.done&&(r=i.return)&&r.call(i)}finally{if(t)throw t.error}}return n},o.prototype.combineResults=function(e,t){if(t===void 0&&(t=He),e.length===0)return new Map;var r=t.toLowerCase();return e.reduce($r[r])||new Map},o.prototype.toJSON=function(){var e,t,r,n,a=[];try{for(var i=D(this._index),s=i.next();!s.done;s=i.next()){var u=j(s.value,2),l=u[0],h=u[1],d={};try{for(var v=(r=void 0,D(h)),m=v.next();!m.done;m=v.next()){var b=j(m.value,2),S=b[0],g=b[1];d[S]=Object.fromEntries(g)}}catch(A){r={error:A}}finally{try{m&&!m.done&&(n=v.return)&&n.call(v)}finally{if(r)throw r.error}}a.push([l,d])}}catch(A){e={error:A}}finally{try{s&&!s.done&&(t=i.return)&&t.call(i)}finally{if(e)throw e.error}}return{documentCount:this._documentCount,nextId:this._nextId,documentIds:Object.fromEntries(this._documentIds),fieldIds:this._fieldIds,fieldLength:Object.fromEntries(this._fieldLength),averageFieldLength:this._avgFieldLength,storedFields:Object.fromEntries(this._storedFields),dirtCount:this._dirtCount,index:a,serializationVersion:2}},o.prototype.termResults=function(e,t,r,n,a,i,s,u){var l,h,d,v,m;if(u===void 0&&(u=new Map),n==null)return u;try{for(var b=D(Object.keys(a)),S=b.next();!S.done;S=b.next()){var g=S.value,A=a[g],T=this._fieldIds[g],F=n.get(T);if(F!=null){var L=F.size,R=this._avgFieldLength[T];try{for(var V=(d=void 0,D(F.keys())),N=V.next();!N.done;N=V.next()){var _=N.value;if(!this._documentIds.has(_)){this.removeTerm(T,_,t),L-=1;continue}var C=i?i(this._documentIds.get(_),t,this._storedFields.get(_)):1;if(C){var O=F.get(_),w=this._fieldLength.get(_)[T],c=Kr(O,L,this._documentCount,w,R,s),f=r*A*C*c,p=u.get(_);if(p){p.score+=f,Ur(p.terms,e);var k=Pe(p.match,t);k?k.push(g):p.match[t]=[g]}else u.set(_,{score:f,terms:[e],match:(m={},m[t]=[g],m)})}}}catch(I){d={error:I}}finally{try{N&&!N.done&&(v=V.return)&&v.call(V)}finally{if(d)throw d.error}}}}}catch(I){l={error:I}}finally{try{S&&!S.done&&(h=b.return)&&h.call(b)}finally{if(l)throw l.error}}return u},o.prototype.addTerm=function(e,t,r){var n=this._index.fetch(r,pt),a=n.get(e);if(a==null)a=new Map,a.set(t,1),n.set(e,a);else{var i=a.get(t);a.set(t,(i||0)+1)}},o.prototype.removeTerm=function(e,t,r){if(!this._index.has(r)){this.warnDocumentChanged(t,e,r);return}var n=this._index.fetch(r,pt),a=n.get(e);a==null||a.get(t)==null?this.warnDocumentChanged(t,e,r):a.get(t)<=1?a.size<=1?n.delete(e):a.delete(t):a.set(t,a.get(t)-1),this._index.get(r).size===0&&this._index.delete(r)},o.prototype.warnDocumentChanged=function(e,t,r){var n,a;try{for(var i=D(Object.keys(this._fieldIds)),s=i.next();!s.done;s=i.next()){var u=s.value;if(this._fieldIds[u]===t){this._options.logger("warn","MiniSearch: document with ID ".concat(this._documentIds.get(e),' has changed before removal: term "').concat(r,'" was not present in field "').concat(u,'". Removing a document after it has changed can corrupt the index!'),"version_conflict");return}}}catch(l){n={error:l}}finally{try{s&&!s.done&&(a=i.return)&&a.call(i)}finally{if(n)throw n.error}}},o.prototype.addDocumentId=function(e){var t=this._nextId;return this._idToShortId.set(e,t),this._documentIds.set(t,e),this._documentCount+=1,this._nextId+=1,t},o.prototype.addFields=function(e){for(var t=0;t(Qt("data-v-fcbfb6ff"),o=o(),qt(),o),Qr=["aria-owns"],qr={class:"shell"},Yr=["title"],Zr=Y(()=>E("svg",{class:"search-icon",width:"18",height:"18",viewBox:"0 0 24 24","aria-hidden":"true"},[E("g",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2"},[E("circle",{cx:"11",cy:"11",r:"8"}),E("path",{d:"m21 21l-4.35-4.35"})])],-1)),Xr=[Zr],ea={class:"search-actions before"},ta=["title"],ra=Y(()=>E("svg",{width:"18",height:"18",viewBox:"0 0 24 24","aria-hidden":"true"},[E("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M19 12H5m7 7l-7-7l7-7"})],-1)),aa=[ra],na=["placeholder"],ia={class:"search-actions"},oa=["title"],sa=Y(()=>E("svg",{width:"18",height:"18",viewBox:"0 0 24 24","aria-hidden":"true"},[E("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M3 14h7v7H3zM3 3h7v7H3zm11 1h7m-7 5h7m-7 6h7m-7 5h7"})],-1)),ua=[sa],la=["disabled","title"],ca=Y(()=>E("svg",{width:"18",height:"18",viewBox:"0 0 24 24","aria-hidden":"true"},[E("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M20 5H9l-7 7l7 7h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2Zm-2 4l-6 6m0-6l6 6"})],-1)),fa=[ca],ha=["id","role","aria-labelledby"],da=["aria-selected"],va=["href","aria-label","onMouseenter","onFocusin"],pa={class:"titles"},ma=Y(()=>E("span",{class:"title-icon"},"#",-1)),ya=["innerHTML"],ga=Y(()=>E("svg",{width:"18",height:"18",viewBox:"0 0 24 24"},[E("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"m9 18l6-6l-6-6"})],-1)),ba={class:"title main"},wa=["innerHTML"],xa={key:0,class:"excerpt-wrapper"},Fa={key:0,class:"excerpt",inert:""},Ea=["innerHTML"],Sa=Y(()=>E("div",{class:"excerpt-gradient-bottom"},null,-1)),Aa=Y(()=>E("div",{class:"excerpt-gradient-top"},null,-1)),Ca={key:0,class:"no-results"},Ta={class:"search-keyboard-shortcuts"},Na=["aria-label"],ka=Y(()=>E("svg",{width:"14",height:"14",viewBox:"0 0 24 24"},[E("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M12 19V5m-7 7l7-7l7 7"})],-1)),Ia=[ka],Da=["aria-label"],Oa=Y(()=>E("svg",{width:"14",height:"14",viewBox:"0 0 24 24"},[E("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M12 5v14m7-7l-7 7l-7-7"})],-1)),_a=[Oa],Ra=["aria-label"],Ma=Y(()=>E("svg",{width:"14",height:"14",viewBox:"0 0 24 24"},[E("g",{fill:"none",stroke:"currentcolor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2"},[E("path",{d:"m9 10l-5 5l5 5"}),E("path",{d:"M20 4v7a4 4 0 0 1-4 4H4"})])],-1)),La=[Ma],za=["aria-label"],Pa=_t({__name:"VPLocalSearchBox",emits:["close"],setup(o,{emit:e}){var z,P;const t=e,r=xe(),n=xe(),a=xe(nr),i=rr(),{activate:s}=Dr(r,{immediate:!0,allowOutsideClick:!0,clickOutsideDeactivates:!0,escapeDeactivates:!0}),{localeIndex:u,theme:l}=i,h=tt(async()=>{var y,x,$,K,G,Q,B,J,Z;return it(Vr.loadJSON(($=await((x=(y=a.value)[u.value])==null?void 0:x.call(y)))==null?void 0:$.default,{fields:["title","titles","text"],storeFields:["title","titles"],searchOptions:{fuzzy:.2,prefix:!0,boost:{title:4,text:2,titles:1},...((K=l.value.search)==null?void 0:K.provider)==="local"&&((Q=(G=l.value.search.options)==null?void 0:G.miniSearch)==null?void 0:Q.searchOptions)},...((B=l.value.search)==null?void 0:B.provider)==="local"&&((Z=(J=l.value.search.options)==null?void 0:J.miniSearch)==null?void 0:Z.options)}))}),v=Fe(()=>{var y,x;return((y=l.value.search)==null?void 0:y.provider)==="local"&&((x=l.value.search.options)==null?void 0:x.disableQueryPersistence)===!0}).value?oe(""):Rt("vitepress:local-search-filter",""),m=Mt("vitepress:local-search-detailed-list",((z=l.value.search)==null?void 0:z.provider)==="local"&&((P=l.value.search.options)==null?void 0:P.detailedView)===!0),b=Fe(()=>{var y,x,$;return((y=l.value.search)==null?void 0:y.provider)==="local"&&(((x=l.value.search.options)==null?void 0:x.disableDetailedView)===!0||(($=l.value.search.options)==null?void 0:$.detailedView)===!1)}),S=Fe(()=>{var x,$,K,G,Q,B,J;const y=((x=l.value.search)==null?void 0:x.options)??l.value.algolia;return((Q=(G=(K=($=y==null?void 0:y.locales)==null?void 0:$[u.value])==null?void 0:K.translations)==null?void 0:G.button)==null?void 0:Q.buttonText)||((J=(B=y==null?void 0:y.translations)==null?void 0:B.button)==null?void 0:J.buttonText)||"Search"});Lt(()=>{b.value&&(m.value=!1)});const g=xe([]),A=oe(!1);$e(v,()=>{A.value=!1});const T=tt(async()=>{if(n.value)return it(new _r(n.value))},null),F=new Gr(16);zt(()=>[h.value,v.value,m.value],async([y,x,$],K,G)=>{var be,Ge,Qe,qe;(K==null?void 0:K[0])!==y&&F.clear();let Q=!1;if(G(()=>{Q=!0}),!y)return;g.value=y.search(x).slice(0,16),A.value=!0;const B=$?await Promise.all(g.value.map(q=>L(q.id))):[];if(Q)return;for(const{id:q,mod:ae}of B){const ne=q.slice(0,q.indexOf("#"));let te=F.get(ne);if(te)continue;te=new Map,F.set(ne,te);const X=ae.default??ae;if(X!=null&&X.render||X!=null&&X.setup){const ie=Yt(X);ie.config.warnHandler=()=>{},ie.provide(Zt,i),Object.defineProperties(ie.config.globalProperties,{$frontmatter:{get(){return i.frontmatter.value}},$params:{get(){return i.page.value.params}}});const Ye=document.createElement("div");ie.mount(Ye),Ye.querySelectorAll("h1, h2, h3, h4, h5, h6").forEach(he=>{var et;const we=(et=he.querySelector("a"))==null?void 0:et.getAttribute("href"),Ze=(we==null?void 0:we.startsWith("#"))&&we.slice(1);if(!Ze)return;let Xe="";for(;(he=he.nextElementSibling)&&!/^h[1-6]$/i.test(he.tagName);)Xe+=he.outerHTML;te.set(Ze,Xe)}),ie.unmount()}if(Q)return}const J=new Set;if(g.value=g.value.map(q=>{const[ae,ne]=q.id.split("#"),te=F.get(ae),X=(te==null?void 0:te.get(ne))??"";for(const ie in q.match)J.add(ie);return{...q,text:X}}),await de(),Q)return;await new Promise(q=>{var ae;(ae=T.value)==null||ae.unmark({done:()=>{var ne;(ne=T.value)==null||ne.markRegExp(M(J),{done:q})}})});const Z=((be=r.value)==null?void 0:be.querySelectorAll(".result .excerpt"))??[];for(const q of Z)(Ge=q.querySelector('mark[data-markjs="true"]'))==null||Ge.scrollIntoView({block:"center"});(qe=(Qe=n.value)==null?void 0:Qe.firstElementChild)==null||qe.scrollIntoView({block:"start"})},{debounce:200,immediate:!0});async function L(y){const x=Xt(y.slice(0,y.indexOf("#")));try{if(!x)throw new Error(`Cannot find file for id: ${y}`);return{id:y,mod:await mt(()=>import(x),__vite__mapDeps([]))}}catch($){return console.error($),{id:y,mod:{}}}}const R=oe(),V=Fe(()=>{var y;return((y=v.value)==null?void 0:y.length)<=0});function N(y=!0){var x,$;(x=R.value)==null||x.focus(),y&&(($=R.value)==null||$.select())}_e(()=>{N()});function _(y){y.pointerType==="mouse"&&N()}const C=oe(-1),O=oe(!1);$e(g,y=>{C.value=y.length?0:-1,w()});function w(){de(()=>{const y=document.querySelector(".result.selected");y&&y.scrollIntoView({block:"nearest"})})}Ee("ArrowUp",y=>{y.preventDefault(),C.value--,C.value<0&&(C.value=g.value.length-1),O.value=!0,w()}),Ee("ArrowDown",y=>{y.preventDefault(),C.value++,C.value>=g.value.length&&(C.value=0),O.value=!0,w()});const c=Pt();Ee("Enter",y=>{if(y.isComposing||y.target instanceof HTMLButtonElement&&y.target.type!=="submit")return;const x=g.value[C.value];if(y.target instanceof HTMLInputElement&&!x){y.preventDefault();return}x&&(c.go(x.id),t("close"))}),Ee("Escape",()=>{t("close")});const p=ar({modal:{displayDetails:"Display detailed list",resetButtonTitle:"Reset search",backButtonTitle:"Close search",noResultsText:"No results for",footer:{selectText:"to select",selectKeyAriaLabel:"enter",navigateText:"to navigate",navigateUpKeyAriaLabel:"up arrow",navigateDownKeyAriaLabel:"down arrow",closeText:"to close",closeKeyAriaLabel:"escape"}}});_e(()=>{window.history.pushState(null,"",null)}),Bt("popstate",y=>{y.preventDefault(),t("close")});const k=Vt($t?document.body:null);_e(()=>{de(()=>{k.value=!0,de().then(()=>s())})}),Wt(()=>{k.value=!1});function I(){v.value="",de().then(()=>N(!1))}function M(y){return new RegExp([...y].sort((x,$)=>$.length-x.length).map(x=>`(${er(x)})`).join("|"),"gi")}return(y,x)=>{var $,K,G,Q;return ee(),Kt(Gt,{to:"body"},[E("div",{ref_key:"el",ref:r,role:"button","aria-owns":($=g.value)!=null&&$.length?"localsearch-list":void 0,"aria-expanded":"true","aria-haspopup":"listbox","aria-labelledby":"localsearch-label",class:"VPLocalSearchBox"},[E("div",{class:"backdrop",onClick:x[0]||(x[0]=B=>y.$emit("close"))}),E("div",qr,[E("form",{class:"search-bar",onPointerup:x[4]||(x[4]=B=>_(B)),onSubmit:x[5]||(x[5]=jt(()=>{},["prevent"]))},[E("label",{title:S.value,id:"localsearch-label",for:"localsearch-input"},Xr,8,Yr),E("div",ea,[E("button",{class:"back-button",title:U(p)("modal.backButtonTitle"),onClick:x[1]||(x[1]=B=>y.$emit("close"))},aa,8,ta)]),Jt(E("input",{ref_key:"searchInput",ref:R,"onUpdate:modelValue":x[2]||(x[2]=B=>Ht(v)?v.value=B:null),placeholder:S.value,id:"localsearch-input","aria-labelledby":"localsearch-label",class:"search-input"},null,8,na),[[Ut,U(v)]]),E("div",ia,[b.value?Se("",!0):(ee(),re("button",{key:0,class:rt(["toggle-layout-button",{"detailed-list":U(m)}]),type:"button",title:U(p)("modal.displayDetails"),onClick:x[3]||(x[3]=B=>C.value>-1&&(m.value=!U(m)))},ua,10,oa)),E("button",{class:"clear-button",type:"reset",disabled:V.value,title:U(p)("modal.resetButtonTitle"),onClick:I},fa,8,la)])],32),E("ul",{ref_key:"resultsEl",ref:n,id:(K=g.value)!=null&&K.length?"localsearch-list":void 0,role:(G=g.value)!=null&&G.length?"listbox":void 0,"aria-labelledby":(Q=g.value)!=null&&Q.length?"localsearch-label":void 0,class:"results",onMousemove:x[7]||(x[7]=B=>O.value=!1)},[(ee(!0),re(nt,null,at(g.value,(B,J)=>(ee(),re("li",{key:B.id,role:"option","aria-selected":C.value===J?"true":"false"},[E("a",{href:B.id,class:rt(["result",{selected:C.value===J}]),"aria-label":[...B.titles,B.title].join(" > "),onMouseenter:Z=>!O.value&&(C.value=J),onFocusin:Z=>C.value=J,onClick:x[6]||(x[6]=Z=>y.$emit("close"))},[E("div",null,[E("div",pa,[ma,(ee(!0),re(nt,null,at(B.titles,(Z,be)=>(ee(),re("span",{key:be,class:"title"},[E("span",{class:"text",innerHTML:Z},null,8,ya),ga]))),128)),E("span",ba,[E("span",{class:"text",innerHTML:B.title},null,8,wa)])]),U(m)?(ee(),re("div",xa,[B.text?(ee(),re("div",Fa,[E("div",{class:"vp-doc",innerHTML:B.text},null,8,Ea)])):Se("",!0),Sa,Aa])):Se("",!0)])],42,va)],8,da))),128)),U(v)&&!g.value.length&&A.value?(ee(),re("li",Ca,[ve(pe(U(p)("modal.noResultsText"))+' "',1),E("strong",null,pe(U(v)),1),ve('" ')])):Se("",!0)],40,ha),E("div",Ta,[E("span",null,[E("kbd",{"aria-label":U(p)("modal.footer.navigateUpKeyAriaLabel")},Ia,8,Na),E("kbd",{"aria-label":U(p)("modal.footer.navigateDownKeyAriaLabel")},_a,8,Da),ve(" "+pe(U(p)("modal.footer.navigateText")),1)]),E("span",null,[E("kbd",{"aria-label":U(p)("modal.footer.selectKeyAriaLabel")},La,8,Ra),ve(" "+pe(U(p)("modal.footer.selectText")),1)]),E("span",null,[E("kbd",{"aria-label":U(p)("modal.footer.closeKeyAriaLabel")},"esc",8,za),ve(" "+pe(U(p)("modal.footer.closeText")),1)])])])],8,Qr)])}}}),ja=tr(Pa,[["__scopeId","data-v-fcbfb6ff"]]);export{ja as default}; +function __vite__mapDeps(indexes) { + if (!__vite__mapDeps.viteFileDeps) { + __vite__mapDeps.viteFileDeps = [] + } + return indexes.map((i) => __vite__mapDeps.viteFileDeps[i]) +} diff --git a/assets/chunks/framework.B6c1f-8R.js b/assets/chunks/framework.B6c1f-8R.js new file mode 100644 index 00000000..2cc14a2e --- /dev/null +++ b/assets/chunks/framework.B6c1f-8R.js @@ -0,0 +1,17 @@ +/** +* @vue/shared v3.4.18 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function Pr(e,t){const n=new Set(e.split(","));return t?r=>n.has(r.toLowerCase()):r=>n.has(r)}const ee={},vt=[],xe=()=>{},Ii=()=>!1,qt=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),Nr=e=>e.startsWith("onUpdate:"),ce=Object.assign,Fr=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},Pi=Object.prototype.hasOwnProperty,Y=(e,t)=>Pi.call(e,t),k=Array.isArray,bt=e=>Gt(e)==="[object Map]",eo=e=>Gt(e)==="[object Set]",rs=e=>Gt(e)==="[object Date]",q=e=>typeof e=="function",ne=e=>typeof e=="string",et=e=>typeof e=="symbol",Z=e=>e!==null&&typeof e=="object",to=e=>(Z(e)||q(e))&&q(e.then)&&q(e.catch),no=Object.prototype.toString,Gt=e=>no.call(e),Ni=e=>Gt(e).slice(8,-1),ro=e=>Gt(e)==="[object Object]",$r=e=>ne(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,wt=Pr(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Pn=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},Fi=/-(\w)/g,He=Pn(e=>e.replace(Fi,(t,n)=>n?n.toUpperCase():"")),$i=/\B([A-Z])/g,pt=Pn(e=>e.replace($i,"-$1").toLowerCase()),Nn=Pn(e=>e.charAt(0).toUpperCase()+e.slice(1)),yn=Pn(e=>e?`on${Nn(e)}`:""),tt=(e,t)=>!Object.is(e,t),_n=(e,t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,value:n})},yr=e=>{const t=parseFloat(e);return isNaN(t)?e:t},Hi=e=>{const t=ne(e)?Number(e):NaN;return isNaN(t)?e:t};let ss;const so=()=>ss||(ss=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Fn(e){if(k(e)){const t={};for(let n=0;n{if(n){const r=n.split(Vi);r.length>1&&(t[r[0].trim()]=r[1].trim())}}),t}function $n(e){let t="";if(ne(e))t=e;else if(k(e))for(let n=0;nne(e)?e:e==null?"":k(e)||Z(e)&&(e.toString===no||!q(e.toString))?JSON.stringify(e,io,2):String(e),io=(e,t)=>t&&t.__v_isRef?io(e,t.value):bt(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[r,s],o)=>(n[nr(r,o)+" =>"]=s,n),{})}:eo(t)?{[`Set(${t.size})`]:[...t.values()].map(n=>nr(n))}:et(t)?nr(t):Z(t)&&!k(t)&&!ro(t)?String(t):t,nr=(e,t="")=>{var n;return et(e)?`Symbol(${(n=e.description)!=null?n:t})`:e};/** +* @vue/reactivity v3.4.18 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let ve;class lo{constructor(t=!1){this.detached=t,this._active=!0,this.effects=[],this.cleanups=[],this.parent=ve,!t&&ve&&(this.index=(ve.scopes||(ve.scopes=[])).push(this)-1)}get active(){return this._active}run(t){if(this._active){const n=ve;try{return ve=this,t()}finally{ve=n}}}on(){ve=this}off(){ve=this.parent}stop(t){if(this._active){let n,r;for(n=0,r=this.effects.length;n=4))break}this._dirtyLevel===1&&(this._dirtyLevel=0),mt()}return this._dirtyLevel>=4}set dirty(t){this._dirtyLevel=t?4:0}run(){if(this._dirtyLevel=0,!this.active)return this.fn();let t=Je,n=ft;try{return Je=!0,ft=this,this._runnings++,os(this),this.fn()}finally{is(this),this._runnings--,ft=n,Je=t}}stop(){var t;this.active&&(os(this),is(this),(t=this.onStop)==null||t.call(this),this.active=!1)}}function Gi(e){return e.value}function os(e){e._trackId++,e._depsLength=0}function is(e){if(e.deps.length>e._depsLength){for(let t=e._depsLength;t{const n=new Map;return n.cleanup=e,n.computed=t,n},Cn=new WeakMap,dt=Symbol(""),br=Symbol("");function ye(e,t,n){if(Je&&ft){let r=Cn.get(e);r||Cn.set(e,r=new Map);let s=r.get(n);s||r.set(n,s=po(()=>r.delete(n))),fo(ft,s)}}function ke(e,t,n,r,s,o){const i=Cn.get(e);if(!i)return;let l=[];if(t==="clear")l=[...i.values()];else if(n==="length"&&k(e)){const c=Number(r);i.forEach((a,f)=>{(f==="length"||!et(f)&&f>=c)&&l.push(a)})}else switch(n!==void 0&&l.push(i.get(n)),t){case"add":k(e)?$r(n)&&l.push(i.get("length")):(l.push(i.get(dt)),bt(e)&&l.push(i.get(br)));break;case"delete":k(e)||(l.push(i.get(dt)),bt(e)&&l.push(i.get(br)));break;case"set":bt(e)&&l.push(i.get(dt));break}jr();for(const c of l)c&&ho(c,4);Vr()}function zi(e,t){var n;return(n=Cn.get(e))==null?void 0:n.get(t)}const Xi=Pr("__proto__,__v_isRef,__isVue"),go=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(et)),ls=Yi();function Yi(){const e={};return["includes","indexOf","lastIndexOf"].forEach(t=>{e[t]=function(...n){const r=J(this);for(let o=0,i=this.length;o{e[t]=function(...n){gt(),jr();const r=J(this)[t].apply(this,n);return Vr(),mt(),r}}),e}function Ji(e){const t=J(this);return ye(t,"has",e),t.hasOwnProperty(e)}class mo{constructor(t=!1,n=!1){this._isReadonly=t,this._shallow=n}get(t,n,r){const s=this._isReadonly,o=this._shallow;if(n==="__v_isReactive")return!s;if(n==="__v_isReadonly")return s;if(n==="__v_isShallow")return o;if(n==="__v_raw")return r===(s?o?Eo:wo:o?bo:vo).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(r)?t:void 0;const i=k(t);if(!s){if(i&&Y(ls,n))return Reflect.get(ls,n,r);if(n==="hasOwnProperty")return Ji}const l=Reflect.get(t,n,r);return(et(n)?go.has(n):Xi(n))||(s||ye(t,"get",n),o)?l:de(l)?i&&$r(n)?l:l.value:Z(l)?s?zt(l):Vn(l):l}}class yo extends mo{constructor(t=!1){super(!1,t)}set(t,n,r,s){let o=t[n];if(!this._shallow){const c=At(o);if(!xn(r)&&!At(r)&&(o=J(o),r=J(r)),!k(t)&&de(o)&&!de(r))return c?!1:(o.value=r,!0)}const i=k(t)&&$r(n)?Number(n)e,Hn=e=>Reflect.getPrototypeOf(e);function nn(e,t,n=!1,r=!1){e=e.__v_raw;const s=J(e),o=J(t);n||(tt(t,o)&&ye(s,"get",t),ye(s,"get",o));const{has:i}=Hn(s),l=r?Dr:n?kr:kt;if(i.call(s,t))return l(e.get(t));if(i.call(s,o))return l(e.get(o));e!==s&&e.get(t)}function rn(e,t=!1){const n=this.__v_raw,r=J(n),s=J(e);return t||(tt(e,s)&&ye(r,"has",e),ye(r,"has",s)),e===s?n.has(e):n.has(e)||n.has(s)}function sn(e,t=!1){return e=e.__v_raw,!t&&ye(J(e),"iterate",dt),Reflect.get(e,"size",e)}function cs(e){e=J(e);const t=J(this);return Hn(t).has.call(t,e)||(t.add(e),ke(t,"add",e,e)),this}function as(e,t){t=J(t);const n=J(this),{has:r,get:s}=Hn(n);let o=r.call(n,e);o||(e=J(e),o=r.call(n,e));const i=s.call(n,e);return n.set(e,t),o?tt(t,i)&&ke(n,"set",e,t):ke(n,"add",e,t),this}function us(e){const t=J(this),{has:n,get:r}=Hn(t);let s=n.call(t,e);s||(e=J(e),s=n.call(t,e)),r&&r.call(t,e);const o=t.delete(e);return s&&ke(t,"delete",e,void 0),o}function fs(){const e=J(this),t=e.size!==0,n=e.clear();return t&&ke(e,"clear",void 0,void 0),n}function on(e,t){return function(r,s){const o=this,i=o.__v_raw,l=J(i),c=t?Dr:e?kr:kt;return!e&&ye(l,"iterate",dt),i.forEach((a,f)=>r.call(s,c(a),c(f),o))}}function ln(e,t,n){return function(...r){const s=this.__v_raw,o=J(s),i=bt(o),l=e==="entries"||e===Symbol.iterator&&i,c=e==="keys"&&i,a=s[e](...r),f=n?Dr:t?kr:kt;return!t&&ye(o,"iterate",c?br:dt),{next(){const{value:h,done:p}=a.next();return p?{value:h,done:p}:{value:l?[f(h[0]),f(h[1])]:f(h),done:p}},[Symbol.iterator](){return this}}}}function Be(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function nl(){const e={get(o){return nn(this,o)},get size(){return sn(this)},has:rn,add:cs,set:as,delete:us,clear:fs,forEach:on(!1,!1)},t={get(o){return nn(this,o,!1,!0)},get size(){return sn(this)},has:rn,add:cs,set:as,delete:us,clear:fs,forEach:on(!1,!0)},n={get(o){return nn(this,o,!0)},get size(){return sn(this,!0)},has(o){return rn.call(this,o,!0)},add:Be("add"),set:Be("set"),delete:Be("delete"),clear:Be("clear"),forEach:on(!0,!1)},r={get(o){return nn(this,o,!0,!0)},get size(){return sn(this,!0)},has(o){return rn.call(this,o,!0)},add:Be("add"),set:Be("set"),delete:Be("delete"),clear:Be("clear"),forEach:on(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(o=>{e[o]=ln(o,!1,!1),n[o]=ln(o,!0,!1),t[o]=ln(o,!1,!0),r[o]=ln(o,!0,!0)}),[e,n,t,r]}const[rl,sl,ol,il]=nl();function jn(e,t){const n=t?e?il:ol:e?sl:rl;return(r,s,o)=>s==="__v_isReactive"?!e:s==="__v_isReadonly"?e:s==="__v_raw"?r:Reflect.get(Y(n,s)&&s in r?n:r,s,o)}const ll={get:jn(!1,!1)},cl={get:jn(!1,!0)},al={get:jn(!0,!1)},ul={get:jn(!0,!0)},vo=new WeakMap,bo=new WeakMap,wo=new WeakMap,Eo=new WeakMap;function fl(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function dl(e){return e.__v_skip||!Object.isExtensible(e)?0:fl(Ni(e))}function Vn(e){return At(e)?e:Dn(e,!1,Qi,ll,vo)}function hl(e){return Dn(e,!1,el,cl,bo)}function zt(e){return Dn(e,!0,Zi,al,wo)}function lu(e){return Dn(e,!0,tl,ul,Eo)}function Dn(e,t,n,r,s){if(!Z(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const o=s.get(e);if(o)return o;const i=dl(e);if(i===0)return e;const l=new Proxy(e,i===2?r:n);return s.set(e,l),l}function Et(e){return At(e)?Et(e.__v_raw):!!(e&&e.__v_isReactive)}function At(e){return!!(e&&e.__v_isReadonly)}function xn(e){return!!(e&&e.__v_isShallow)}function Co(e){return Et(e)||At(e)}function J(e){const t=e&&e.__v_raw;return t?J(t):e}function Pt(e){return Object.isExtensible(e)&&wn(e,"__v_skip",!0),e}const kt=e=>Z(e)?Vn(e):e,kr=e=>Z(e)?zt(e):e;class xo{constructor(t,n,r,s){this._setter=n,this.dep=void 0,this.__v_isRef=!0,this.__v_isReadonly=!1,this.effect=new Hr(()=>t(this._value),()=>Nt(this,this.effect._dirtyLevel===2?2:3)),this.effect.computed=this,this.effect.active=this._cacheable=!s,this.__v_isReadonly=r}get value(){const t=J(this);return(!t._cacheable||t.effect.dirty)&&tt(t._value,t._value=t.effect.run())&&Nt(t,4),Ur(t),t.effect._dirtyLevel>=2&&Nt(t,2),t._value}set value(t){this._setter(t)}get _dirty(){return this.effect.dirty}set _dirty(t){this.effect.dirty=t}}function pl(e,t,n=!1){let r,s;const o=q(e);return o?(r=e,s=xe):(r=e.get,s=e.set),new xo(r,s,o||!s,n)}function Ur(e){var t;Je&&ft&&(e=J(e),fo(ft,(t=e.dep)!=null?t:e.dep=po(()=>e.dep=void 0,e instanceof xo?e:void 0)))}function Nt(e,t=4,n){e=J(e);const r=e.dep;r&&ho(r,t)}function de(e){return!!(e&&e.__v_isRef===!0)}function oe(e){return To(e,!1)}function kn(e){return To(e,!0)}function To(e,t){return de(e)?e:new gl(e,t)}class gl{constructor(t,n){this.__v_isShallow=n,this.dep=void 0,this.__v_isRef=!0,this._rawValue=n?t:J(t),this._value=n?t:kt(t)}get value(){return Ur(this),this._value}set value(t){const n=this.__v_isShallow||xn(t)||At(t);t=n?t:J(t),tt(t,this._rawValue)&&(this._rawValue=t,this._value=n?t:kt(t),Nt(this,4))}}function So(e){return de(e)?e.value:e}const ml={get:(e,t,n)=>So(Reflect.get(e,t,n)),set:(e,t,n,r)=>{const s=e[t];return de(s)&&!de(n)?(s.value=n,!0):Reflect.set(e,t,n,r)}};function Ao(e){return Et(e)?e:new Proxy(e,ml)}class yl{constructor(t){this.dep=void 0,this.__v_isRef=!0;const{get:n,set:r}=t(()=>Ur(this),()=>Nt(this));this._get=n,this._set=r}get value(){return this._get()}set value(t){this._set(t)}}function Ro(e){return new yl(e)}class _l{constructor(t,n,r){this._object=t,this._key=n,this._defaultValue=r,this.__v_isRef=!0}get value(){const t=this._object[this._key];return t===void 0?this._defaultValue:t}set value(t){this._object[this._key]=t}get dep(){return zi(J(this._object),this._key)}}class vl{constructor(t){this._getter=t,this.__v_isRef=!0,this.__v_isReadonly=!0}get value(){return this._getter()}}function bl(e,t,n){return de(e)?e:q(e)?new vl(e):Z(e)&&arguments.length>1?wl(e,t,n):oe(e)}function wl(e,t,n){const r=e[t];return de(r)?r:new _l(e,t,n)}/** +* @vue/runtime-core v3.4.18 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function Qe(e,t,n,r){let s;try{s=r?e(...r):e()}catch(o){Xt(o,t,n)}return s}function Te(e,t,n,r){if(q(e)){const o=Qe(e,t,n,r);return o&&to(o)&&o.catch(i=>{Xt(i,t,n)}),o}const s=[];for(let o=0;o>>1,s=he[r],o=Bt(s);oFe&&he.splice(t,1)}function Tl(e){k(e)?Ct.push(...e):(!Ge||!Ge.includes(e,e.allowRecurse?lt+1:lt))&&Ct.push(e),Lo()}function ds(e,t,n=Ut?Fe+1:0){for(;nBt(n)-Bt(r));if(Ct.length=0,Ge){Ge.push(...t);return}for(Ge=t,lt=0;lte.id==null?1/0:e.id,Sl=(e,t)=>{const n=Bt(e)-Bt(t);if(n===0){if(e.pre&&!t.pre)return-1;if(t.pre&&!e.pre)return 1}return n};function Mo(e){wr=!1,Ut=!0,he.sort(Sl);try{for(Fe=0;Fene(y)?y.trim():y)),h&&(s=n.map(yr))}let l,c=r[l=yn(t)]||r[l=yn(He(t))];!c&&o&&(c=r[l=yn(pt(t))]),c&&Te(c,e,6,s);const a=r[l+"Once"];if(a){if(!e.emitted)e.emitted={};else if(e.emitted[l])return;e.emitted[l]=!0,Te(a,e,6,s)}}function Io(e,t,n=!1){const r=t.emitsCache,s=r.get(e);if(s!==void 0)return s;const o=e.emits;let i={},l=!1;if(!q(e)){const c=a=>{const f=Io(a,t,!0);f&&(l=!0,ce(i,f))};!n&&t.mixins.length&&t.mixins.forEach(c),e.extends&&c(e.extends),e.mixins&&e.mixins.forEach(c)}return!o&&!l?(Z(e)&&r.set(e,null),null):(k(o)?o.forEach(c=>i[c]=null):ce(i,o),Z(e)&&r.set(e,i),i)}function Kn(e,t){return!e||!qt(t)?!1:(t=t.slice(2).replace(/Once$/,""),Y(e,t[0].toLowerCase()+t.slice(1))||Y(e,pt(t))||Y(e,t))}let le=null,Wn=null;function Sn(e){const t=le;return le=e,Wn=e&&e.type.__scopeId||null,t}function cu(e){Wn=e}function au(){Wn=null}function Rl(e,t=le,n){if(!t||e._n)return e;const r=(...s)=>{r._d&&Ss(-1);const o=Sn(t);let i;try{i=e(...s)}finally{Sn(o),r._d&&Ss(1)}return i};return r._n=!0,r._c=!0,r._d=!0,r}function rr(e){const{type:t,vnode:n,proxy:r,withProxy:s,props:o,propsOptions:[i],slots:l,attrs:c,emit:a,render:f,renderCache:h,data:p,setupState:y,ctx:v,inheritAttrs:T}=e;let F,U;const B=Sn(e);try{if(n.shapeFlag&4){const _=s||r,P=_;F=Re(f.call(P,_,h,o,y,p,v)),U=c}else{const _=t;F=Re(_.length>1?_(o,{attrs:c,slots:l,emit:a}):_(o,null)),U=t.props?c:Ol(c)}}catch(_){Vt.length=0,Xt(_,e,1),F=se(be)}let g=F;if(U&&T!==!1){const _=Object.keys(U),{shapeFlag:P}=g;_.length&&P&7&&(i&&_.some(Nr)&&(U=Ll(U,i)),g=nt(g,U))}return n.dirs&&(g=nt(g),g.dirs=g.dirs?g.dirs.concat(n.dirs):n.dirs),n.transition&&(g.transition=n.transition),F=g,Sn(B),F}const Ol=e=>{let t;for(const n in e)(n==="class"||n==="style"||qt(n))&&((t||(t={}))[n]=e[n]);return t},Ll=(e,t)=>{const n={};for(const r in e)(!Nr(r)||!(r.slice(9)in t))&&(n[r]=e[r]);return n};function Ml(e,t,n){const{props:r,children:s,component:o}=e,{props:i,children:l,patchFlag:c}=t,a=o.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&c>=0){if(c&1024)return!0;if(c&16)return r?hs(r,i,a):!!i;if(c&8){const f=t.dynamicProps;for(let h=0;he.__isSuspense;function Fo(e,t){t&&t.pendingBranch?k(e)?t.effects.push(...e):t.effects.push(e):Tl(e)}const Nl=Symbol.for("v-scx"),Fl=()=>Tt(Nl);function qn(e,t){return Gn(e,null,t)}function du(e,t){return Gn(e,null,{flush:"post"})}const cn={};function $e(e,t,n){return Gn(e,t,n)}function Gn(e,t,{immediate:n,deep:r,flush:s,once:o,onTrack:i,onTrigger:l}=ee){if(t&&o){const L=t;t=(...$)=>{L(...$),P()}}const c=ue,a=L=>r===!0?L:ut(L,r===!1?1:void 0);let f,h=!1,p=!1;if(de(e)?(f=()=>e.value,h=xn(e)):Et(e)?(f=()=>a(e),h=!0):k(e)?(p=!0,h=e.some(L=>Et(L)||xn(L)),f=()=>e.map(L=>{if(de(L))return L.value;if(Et(L))return a(L);if(q(L))return Qe(L,c,2)})):q(e)?t?f=()=>Qe(e,c,2):f=()=>(y&&y(),Te(e,c,3,[v])):f=xe,t&&r){const L=f;f=()=>ut(L())}let y,v=L=>{y=g.onStop=()=>{Qe(L,c,4),y=g.onStop=void 0}},T;if(Zt)if(v=xe,t?n&&Te(t,c,3,[f(),p?[]:void 0,v]):f(),s==="sync"){const L=Fl();T=L.__watcherHandles||(L.__watcherHandles=[])}else return xe;let F=p?new Array(e.length).fill(cn):cn;const U=()=>{if(!(!g.active||!g.dirty))if(t){const L=g.run();(r||h||(p?L.some(($,R)=>tt($,F[R])):tt(L,F)))&&(y&&y(),Te(t,c,3,[L,F===cn?void 0:p&&F[0]===cn?[]:F,v]),F=L)}else g.run()};U.allowRecurse=!!t;let B;s==="sync"?B=U:s==="post"?B=()=>ge(U,c&&c.suspense):(U.pre=!0,c&&(U.id=c.uid),B=()=>Bn(U));const g=new Hr(f,xe,B),_=co(),P=()=>{g.stop(),_&&Fr(_.effects,g)};return t?n?U():F=g.run():s==="post"?ge(g.run.bind(g),c&&c.suspense):g.run(),T&&T.push(P),P}function $l(e,t,n){const r=this.proxy,s=ne(e)?e.includes(".")?$o(r,e):()=>r[e]:e.bind(r,r);let o;q(t)?o=t:(o=t.handler,n=t);const i=Qt(this),l=Gn(s,o.bind(r),n);return i(),l}function $o(e,t){const n=t.split(".");return()=>{let r=e;for(let s=0;s0){if(n>=t)return e;n++}if(r=r||new Set,r.has(e))return e;if(r.add(e),de(e))ut(e.value,t,n,r);else if(k(e))for(let s=0;s{ut(s,t,n,r)});else if(ro(e))for(const s in e)ut(e[s],t,n,r);return e}function hu(e,t){if(le===null)return e;const n=Jn(le)||le.proxy,r=e.dirs||(e.dirs=[]);for(let s=0;s{e.isMounted=!0}),Uo(()=>{e.isUnmounting=!0}),e}const we=[Function,Array],Ho={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:we,onEnter:we,onAfterEnter:we,onEnterCancelled:we,onBeforeLeave:we,onLeave:we,onAfterLeave:we,onLeaveCancelled:we,onBeforeAppear:we,onAppear:we,onAfterAppear:we,onAppearCancelled:we},jl={name:"BaseTransition",props:Ho,setup(e,{slots:t}){const n=Jt(),r=Hl();let s;return()=>{const o=t.default&&Vo(t.default(),!0);if(!o||!o.length)return;let i=o[0];if(o.length>1){for(const T of o)if(T.type!==be){i=T;break}}const l=J(e),{mode:c}=l;if(r.isLeaving)return sr(i);const a=gs(i);if(!a)return sr(i);const f=Er(a,l,r,n);Cr(a,f);const h=n.subTree,p=h&&gs(h);let y=!1;const{getTransitionKey:v}=a.type;if(v){const T=v();s===void 0?s=T:T!==s&&(s=T,y=!0)}if(p&&p.type!==be&&(!ct(a,p)||y)){const T=Er(p,l,r,n);if(Cr(p,T),c==="out-in")return r.isLeaving=!0,T.afterLeave=()=>{r.isLeaving=!1,n.update.active!==!1&&(n.effect.dirty=!0,n.update())},sr(i);c==="in-out"&&a.type!==be&&(T.delayLeave=(F,U,B)=>{const g=jo(r,p);g[String(p.key)]=p,F[ze]=()=>{U(),F[ze]=void 0,delete f.delayedLeave},f.delayedLeave=B})}return i}}},Vl=jl;function jo(e,t){const{leavingVNodes:n}=e;let r=n.get(t.type);return r||(r=Object.create(null),n.set(t.type,r)),r}function Er(e,t,n,r){const{appear:s,mode:o,persisted:i=!1,onBeforeEnter:l,onEnter:c,onAfterEnter:a,onEnterCancelled:f,onBeforeLeave:h,onLeave:p,onAfterLeave:y,onLeaveCancelled:v,onBeforeAppear:T,onAppear:F,onAfterAppear:U,onAppearCancelled:B}=t,g=String(e.key),_=jo(n,e),P=(R,S)=>{R&&Te(R,r,9,S)},L=(R,S)=>{const A=S[1];P(R,S),k(R)?R.every(K=>K.length<=1)&&A():R.length<=1&&A()},$={mode:o,persisted:i,beforeEnter(R){let S=l;if(!n.isMounted)if(s)S=T||l;else return;R[ze]&&R[ze](!0);const A=_[g];A&&ct(e,A)&&A.el[ze]&&A.el[ze](),P(S,[R])},enter(R){let S=c,A=a,K=f;if(!n.isMounted)if(s)S=F||c,A=U||a,K=B||f;else return;let I=!1;const G=R[an]=ie=>{I||(I=!0,ie?P(K,[R]):P(A,[R]),$.delayedLeave&&$.delayedLeave(),R[an]=void 0)};S?L(S,[R,G]):G()},leave(R,S){const A=String(e.key);if(R[an]&&R[an](!0),n.isUnmounting)return S();P(h,[R]);let K=!1;const I=R[ze]=G=>{K||(K=!0,S(),G?P(v,[R]):P(y,[R]),R[ze]=void 0,_[A]===e&&delete _[A])};_[A]=e,p?L(p,[R,I]):I()},clone(R){return Er(R,t,n,r)}};return $}function sr(e){if(Yt(e))return e=nt(e),e.children=null,e}function gs(e){return Yt(e)?e.children?e.children[0]:void 0:e}function Cr(e,t){e.shapeFlag&6&&e.component?Cr(e.component.subTree,t):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function Vo(e,t=!1,n){let r=[],s=0;for(let o=0;o1)for(let o=0;o!!e.type.__asyncLoader;/*! #__NO_SIDE_EFFECTS__ */function pu(e){q(e)&&(e={loader:e});const{loader:t,loadingComponent:n,errorComponent:r,delay:s=200,timeout:o,suspensible:i=!0,onError:l}=e;let c=null,a,f=0;const h=()=>(f++,c=null,p()),p=()=>{let y;return c||(y=c=t().catch(v=>{if(v=v instanceof Error?v:new Error(String(v)),l)return new Promise((T,F)=>{l(v,()=>T(h()),()=>F(v),f+1)});throw v}).then(v=>y!==c&&c?c:(v&&(v.__esModule||v[Symbol.toStringTag]==="Module")&&(v=v.default),a=v,v)))};return Wr({name:"AsyncComponentWrapper",__asyncLoader:p,get __asyncResolved(){return a},setup(){const y=ue;if(a)return()=>or(a,y);const v=B=>{c=null,Xt(B,y,13,!r)};if(i&&y.suspense||Zt)return p().then(B=>()=>or(B,y)).catch(B=>(v(B),()=>r?se(r,{error:B}):null));const T=oe(!1),F=oe(),U=oe(!!s);return s&&setTimeout(()=>{U.value=!1},s),o!=null&&setTimeout(()=>{if(!T.value&&!F.value){const B=new Error(`Async component timed out after ${o}ms.`);v(B),F.value=B}},o),p().then(()=>{T.value=!0,y.parent&&Yt(y.parent.vnode)&&(y.parent.effect.dirty=!0,Bn(y.parent.update))}).catch(B=>{v(B),F.value=B}),()=>{if(T.value&&a)return or(a,y);if(F.value&&r)return se(r,{error:F.value});if(n&&!U.value)return se(n)}}})}function or(e,t){const{ref:n,props:r,children:s,ce:o}=t.vnode,i=se(e,r,s);return i.ref=n,i.ce=o,delete t.vnode.ce,i}const Yt=e=>e.type.__isKeepAlive;function Dl(e,t){Do(e,"a",t)}function kl(e,t){Do(e,"da",t)}function Do(e,t,n=ue){const r=e.__wdc||(e.__wdc=()=>{let s=n;for(;s;){if(s.isDeactivated)return;s=s.parent}return e()});if(zn(t,r,n),n){let s=n.parent;for(;s&&s.parent;)Yt(s.parent.vnode)&&Ul(r,t,n,s),s=s.parent}}function Ul(e,t,n,r){const s=zn(t,e,r,!0);Xn(()=>{Fr(r[t],s)},n)}function zn(e,t,n=ue,r=!1){if(n){const s=n[e]||(n[e]=[]),o=t.__weh||(t.__weh=(...i)=>{if(n.isUnmounted)return;gt();const l=Qt(n),c=Te(t,n,e,i);return l(),mt(),c});return r?s.unshift(o):s.push(o),o}}const Ue=e=>(t,n=ue)=>(!Zt||e==="sp")&&zn(e,(...r)=>t(...r),n),Bl=Ue("bm"),Ot=Ue("m"),Kl=Ue("bu"),ko=Ue("u"),Uo=Ue("bum"),Xn=Ue("um"),Wl=Ue("sp"),ql=Ue("rtg"),Gl=Ue("rtc");function zl(e,t=ue){zn("ec",e,t)}function gu(e,t,n,r){let s;const o=n&&n[r];if(k(e)||ne(e)){s=new Array(e.length);for(let i=0,l=e.length;it(i,l,void 0,o&&o[l]));else{const i=Object.keys(e);s=new Array(i.length);for(let l=0,c=i.length;l{const o=r.fn(...s);return o&&(o.key=r.key),o}:r.fn)}return e}function yu(e,t,n={},r,s){if(le.isCE||le.parent&&xt(le.parent)&&le.parent.isCE)return t!=="default"&&(n.name=t),se("slot",n,r&&r());let o=e[t];o&&o._c&&(o._d=!1),ti();const i=o&&Bo(o(n)),l=ri(me,{key:n.key||i&&i.key||`_${t}`},i||(r?r():[]),i&&e._===1?64:-2);return!s&&l.scopeId&&(l.slotScopeIds=[l.scopeId+"-s"]),o&&o._c&&(o._d=!0),l}function Bo(e){return e.some(t=>On(t)?!(t.type===be||t.type===me&&!Bo(t.children)):!0)?e:null}function _u(e,t){const n={};for(const r in e)n[t&&/[A-Z]/.test(r)?`on:${r}`:yn(r)]=e[r];return n}const xr=e=>e?li(e)?Jn(e)||e.proxy:xr(e.parent):null,Ft=ce(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>xr(e.parent),$root:e=>xr(e.root),$emit:e=>e.emit,$options:e=>qr(e),$forceUpdate:e=>e.f||(e.f=()=>{e.effect.dirty=!0,Bn(e.update)}),$nextTick:e=>e.n||(e.n=Un.bind(e.proxy)),$watch:e=>$l.bind(e)}),ir=(e,t)=>e!==ee&&!e.__isScriptSetup&&Y(e,t),Xl={get({_:e},t){const{ctx:n,setupState:r,data:s,props:o,accessCache:i,type:l,appContext:c}=e;let a;if(t[0]!=="$"){const y=i[t];if(y!==void 0)switch(y){case 1:return r[t];case 2:return s[t];case 4:return n[t];case 3:return o[t]}else{if(ir(r,t))return i[t]=1,r[t];if(s!==ee&&Y(s,t))return i[t]=2,s[t];if((a=e.propsOptions[0])&&Y(a,t))return i[t]=3,o[t];if(n!==ee&&Y(n,t))return i[t]=4,n[t];Tr&&(i[t]=0)}}const f=Ft[t];let h,p;if(f)return t==="$attrs"&&ye(e,"get",t),f(e);if((h=l.__cssModules)&&(h=h[t]))return h;if(n!==ee&&Y(n,t))return i[t]=4,n[t];if(p=c.config.globalProperties,Y(p,t))return p[t]},set({_:e},t,n){const{data:r,setupState:s,ctx:o}=e;return ir(s,t)?(s[t]=n,!0):r!==ee&&Y(r,t)?(r[t]=n,!0):Y(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(o[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:r,appContext:s,propsOptions:o}},i){let l;return!!n[i]||e!==ee&&Y(e,i)||ir(t,i)||(l=o[0])&&Y(l,i)||Y(r,i)||Y(Ft,i)||Y(s.config.globalProperties,i)},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:Y(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};function vu(){return Yl().slots}function Yl(){const e=Jt();return e.setupContext||(e.setupContext=ai(e))}function ms(e){return k(e)?e.reduce((t,n)=>(t[n]=null,t),{}):e}let Tr=!0;function Jl(e){const t=qr(e),n=e.proxy,r=e.ctx;Tr=!1,t.beforeCreate&&ys(t.beforeCreate,e,"bc");const{data:s,computed:o,methods:i,watch:l,provide:c,inject:a,created:f,beforeMount:h,mounted:p,beforeUpdate:y,updated:v,activated:T,deactivated:F,beforeDestroy:U,beforeUnmount:B,destroyed:g,unmounted:_,render:P,renderTracked:L,renderTriggered:$,errorCaptured:R,serverPrefetch:S,expose:A,inheritAttrs:K,components:I,directives:G,filters:ie}=t;if(a&&Ql(a,r,null),i)for(const X in i){const j=i[X];q(j)&&(r[X]=j.bind(n))}if(s){const X=s.call(n,n);Z(X)&&(e.data=Vn(X))}if(Tr=!0,o)for(const X in o){const j=o[X],je=q(j)?j.bind(n,n):q(j.get)?j.get.bind(n,n):xe,en=!q(j)&&q(j.set)?j.set.bind(n):xe,rt=re({get:je,set:en});Object.defineProperty(r,X,{enumerable:!0,configurable:!0,get:()=>rt.value,set:Ie=>rt.value=Ie})}if(l)for(const X in l)Ko(l[X],r,n,X);if(c){const X=q(c)?c.call(n):c;Reflect.ownKeys(X).forEach(j=>{sc(j,X[j])})}f&&ys(f,e,"c");function V(X,j){k(j)?j.forEach(je=>X(je.bind(n))):j&&X(j.bind(n))}if(V(Bl,h),V(Ot,p),V(Kl,y),V(ko,v),V(Dl,T),V(kl,F),V(zl,R),V(Gl,L),V(ql,$),V(Uo,B),V(Xn,_),V(Wl,S),k(A))if(A.length){const X=e.exposed||(e.exposed={});A.forEach(j=>{Object.defineProperty(X,j,{get:()=>n[j],set:je=>n[j]=je})})}else e.exposed||(e.exposed={});P&&e.render===xe&&(e.render=P),K!=null&&(e.inheritAttrs=K),I&&(e.components=I),G&&(e.directives=G)}function Ql(e,t,n=xe){k(e)&&(e=Sr(e));for(const r in e){const s=e[r];let o;Z(s)?"default"in s?o=Tt(s.from||r,s.default,!0):o=Tt(s.from||r):o=Tt(s),de(o)?Object.defineProperty(t,r,{enumerable:!0,configurable:!0,get:()=>o.value,set:i=>o.value=i}):t[r]=o}}function ys(e,t,n){Te(k(e)?e.map(r=>r.bind(t.proxy)):e.bind(t.proxy),t,n)}function Ko(e,t,n,r){const s=r.includes(".")?$o(n,r):()=>n[r];if(ne(e)){const o=t[e];q(o)&&$e(s,o)}else if(q(e))$e(s,e.bind(n));else if(Z(e))if(k(e))e.forEach(o=>Ko(o,t,n,r));else{const o=q(e.handler)?e.handler.bind(n):t[e.handler];q(o)&&$e(s,o,e)}}function qr(e){const t=e.type,{mixins:n,extends:r}=t,{mixins:s,optionsCache:o,config:{optionMergeStrategies:i}}=e.appContext,l=o.get(t);let c;return l?c=l:!s.length&&!n&&!r?c=t:(c={},s.length&&s.forEach(a=>An(c,a,i,!0)),An(c,t,i)),Z(t)&&o.set(t,c),c}function An(e,t,n,r=!1){const{mixins:s,extends:o}=t;o&&An(e,o,n,!0),s&&s.forEach(i=>An(e,i,n,!0));for(const i in t)if(!(r&&i==="expose")){const l=Zl[i]||n&&n[i];e[i]=l?l(e[i],t[i]):t[i]}return e}const Zl={data:_s,props:vs,emits:vs,methods:It,computed:It,beforeCreate:pe,created:pe,beforeMount:pe,mounted:pe,beforeUpdate:pe,updated:pe,beforeDestroy:pe,beforeUnmount:pe,destroyed:pe,unmounted:pe,activated:pe,deactivated:pe,errorCaptured:pe,serverPrefetch:pe,components:It,directives:It,watch:tc,provide:_s,inject:ec};function _s(e,t){return t?e?function(){return ce(q(e)?e.call(this,this):e,q(t)?t.call(this,this):t)}:t:e}function ec(e,t){return It(Sr(e),Sr(t))}function Sr(e){if(k(e)){const t={};for(let n=0;n1)return n&&q(t)?t.call(r&&r.proxy):t}}function oc(e,t,n,r=!1){const s={},o={};wn(o,Yn,1),e.propsDefaults=Object.create(null),qo(e,t,s,o);for(const i in e.propsOptions[0])i in s||(s[i]=void 0);n?e.props=r?s:hl(s):e.type.props?e.props=s:e.props=o,e.attrs=o}function ic(e,t,n,r){const{props:s,attrs:o,vnode:{patchFlag:i}}=e,l=J(s),[c]=e.propsOptions;let a=!1;if((r||i>0)&&!(i&16)){if(i&8){const f=e.vnode.dynamicProps;for(let h=0;h{c=!0;const[p,y]=Go(h,t,!0);ce(i,p),y&&l.push(...y)};!n&&t.mixins.length&&t.mixins.forEach(f),e.extends&&f(e.extends),e.mixins&&e.mixins.forEach(f)}if(!o&&!c)return Z(e)&&r.set(e,vt),vt;if(k(o))for(let f=0;f-1,y[1]=T<0||v-1||Y(y,"default"))&&l.push(h)}}}const a=[i,l];return Z(e)&&r.set(e,a),a}function bs(e){return e[0]!=="$"&&!wt(e)}function ws(e){const t=e&&e.toString().match(/^\s*(function|class) (\w+)/);return t?t[2]:e===null?"null":""}function Es(e,t){return ws(e)===ws(t)}function Cs(e,t){return k(t)?t.findIndex(n=>Es(n,e)):q(t)&&Es(t,e)?0:-1}const zo=e=>e[0]==="_"||e==="$stable",Gr=e=>k(e)?e.map(Re):[Re(e)],lc=(e,t,n)=>{if(t._n)return t;const r=Rl((...s)=>Gr(t(...s)),n);return r._c=!1,r},Xo=(e,t,n)=>{const r=e._ctx;for(const s in e){if(zo(s))continue;const o=e[s];if(q(o))t[s]=lc(s,o,r);else if(o!=null){const i=Gr(o);t[s]=()=>i}}},Yo=(e,t)=>{const n=Gr(t);e.slots.default=()=>n},cc=(e,t)=>{if(e.vnode.shapeFlag&32){const n=t._;n?(e.slots=J(t),wn(t,"_",n)):Xo(t,e.slots={})}else e.slots={},t&&Yo(e,t);wn(e.slots,Yn,1)},ac=(e,t,n)=>{const{vnode:r,slots:s}=e;let o=!0,i=ee;if(r.shapeFlag&32){const l=t._;l?n&&l===1?o=!1:(ce(s,t),!n&&l===1&&delete s._):(o=!t.$stable,Xo(t,s)),i=t}else t&&(Yo(e,t),i={default:1});if(o)for(const l in s)!zo(l)&&i[l]==null&&delete s[l]};function Rn(e,t,n,r,s=!1){if(k(e)){e.forEach((p,y)=>Rn(p,t&&(k(t)?t[y]:t),n,r,s));return}if(xt(r)&&!s)return;const o=r.shapeFlag&4?Jn(r.component)||r.component.proxy:r.el,i=s?null:o,{i:l,r:c}=e,a=t&&t.r,f=l.refs===ee?l.refs={}:l.refs,h=l.setupState;if(a!=null&&a!==c&&(ne(a)?(f[a]=null,Y(h,a)&&(h[a]=null)):de(a)&&(a.value=null)),q(c))Qe(c,l,12,[i,f]);else{const p=ne(c),y=de(c);if(p||y){const v=()=>{if(e.f){const T=p?Y(h,c)?h[c]:f[c]:c.value;s?k(T)&&Fr(T,o):k(T)?T.includes(o)||T.push(o):p?(f[c]=[o],Y(h,c)&&(h[c]=f[c])):(c.value=[o],e.k&&(f[e.k]=c.value))}else p?(f[c]=i,Y(h,c)&&(h[c]=i)):y&&(c.value=i,e.k&&(f[e.k]=i))};i?(v.id=-1,ge(v,n)):v()}}}let Ke=!1;const uc=e=>e.namespaceURI.includes("svg")&&e.tagName!=="foreignObject",fc=e=>e.namespaceURI.includes("MathML"),un=e=>{if(uc(e))return"svg";if(fc(e))return"mathml"},fn=e=>e.nodeType===8;function dc(e){const{mt:t,p:n,o:{patchProp:r,createText:s,nextSibling:o,parentNode:i,remove:l,insert:c,createComment:a}}=e,f=(g,_)=>{if(!_.hasChildNodes()){n(null,g,_),Tn(),_._vnode=g;return}Ke=!1,h(_.firstChild,g,null,null,null),Tn(),_._vnode=g,Ke&&console.error("Hydration completed but contains mismatches.")},h=(g,_,P,L,$,R=!1)=>{const S=fn(g)&&g.data==="[",A=()=>T(g,_,P,L,$,S),{type:K,ref:I,shapeFlag:G,patchFlag:ie}=_;let fe=g.nodeType;_.el=g,ie===-2&&(R=!1,_.dynamicChildren=null);let V=null;switch(K){case Rt:fe!==3?_.children===""?(c(_.el=s(""),i(g),g),V=g):V=A():(g.data!==_.children&&(Ke=!0,g.data=_.children),V=o(g));break;case be:B(g)?(V=o(g),U(_.el=g.content.firstChild,g,P)):fe!==8||S?V=A():V=o(g);break;case jt:if(S&&(g=o(g),fe=g.nodeType),fe===1||fe===3){V=g;const X=!_.children.length;for(let j=0;j<_.staticCount;j++)X&&(_.children+=V.nodeType===1?V.outerHTML:V.data),j===_.staticCount-1&&(_.anchor=V),V=o(V);return S?o(V):V}else A();break;case me:S?V=v(g,_,P,L,$,R):V=A();break;default:if(G&1)(fe!==1||_.type.toLowerCase()!==g.tagName.toLowerCase())&&!B(g)?V=A():V=p(g,_,P,L,$,R);else if(G&6){_.slotScopeIds=$;const X=i(g);if(S?V=F(g):fn(g)&&g.data==="teleport start"?V=F(g,g.data,"teleport end"):V=o(g),t(_,X,null,P,L,un(X),R),xt(_)){let j;S?(j=se(me),j.anchor=V?V.previousSibling:X.lastChild):j=g.nodeType===3?ii(""):se("div"),j.el=g,_.component.subTree=j}}else G&64?fe!==8?V=A():V=_.type.hydrate(g,_,P,L,$,R,e,y):G&128&&(V=_.type.hydrate(g,_,P,L,un(i(g)),$,R,e,h))}return I!=null&&Rn(I,null,L,_),V},p=(g,_,P,L,$,R)=>{R=R||!!_.dynamicChildren;const{type:S,props:A,patchFlag:K,shapeFlag:I,dirs:G,transition:ie}=_,fe=S==="input"||S==="option";if(fe||K!==-1){G&&Ne(_,null,P,"created");let V=!1;if(B(g)){V=Qo(L,ie)&&P&&P.vnode.props&&P.vnode.props.appear;const j=g.content.firstChild;V&&ie.beforeEnter(j),U(j,g,P),_.el=g=j}if(I&16&&!(A&&(A.innerHTML||A.textContent))){let j=y(g.firstChild,_,g,P,L,$,R);for(;j;){Ke=!0;const je=j;j=j.nextSibling,l(je)}}else I&8&&g.textContent!==_.children&&(Ke=!0,g.textContent=_.children);if(A)if(fe||!R||K&48)for(const j in A)(fe&&(j.endsWith("value")||j==="indeterminate")||qt(j)&&!wt(j)||j[0]===".")&&r(g,j,null,A[j],void 0,void 0,P);else A.onClick&&r(g,"onClick",null,A.onClick,void 0,void 0,P);let X;(X=A&&A.onVnodeBeforeMount)&&Ee(X,P,_),G&&Ne(_,null,P,"beforeMount"),((X=A&&A.onVnodeMounted)||G||V)&&Fo(()=>{X&&Ee(X,P,_),V&&ie.enter(g),G&&Ne(_,null,P,"mounted")},L)}return g.nextSibling},y=(g,_,P,L,$,R,S)=>{S=S||!!_.dynamicChildren;const A=_.children,K=A.length;for(let I=0;I{const{slotScopeIds:S}=_;S&&($=$?$.concat(S):S);const A=i(g),K=y(o(g),_,A,P,L,$,R);return K&&fn(K)&&K.data==="]"?o(_.anchor=K):(Ke=!0,c(_.anchor=a("]"),A,K),K)},T=(g,_,P,L,$,R)=>{if(Ke=!0,_.el=null,R){const K=F(g);for(;;){const I=o(g);if(I&&I!==K)l(I);else break}}const S=o(g),A=i(g);return l(g),n(null,_,A,S,P,L,un(A),$),S},F=(g,_="[",P="]")=>{let L=0;for(;g;)if(g=o(g),g&&fn(g)&&(g.data===_&&L++,g.data===P)){if(L===0)return o(g);L--}return g},U=(g,_,P)=>{const L=_.parentNode;L&&L.replaceChild(g,_);let $=P;for(;$;)$.vnode.el===_&&($.vnode.el=$.subTree.el=g),$=$.parent},B=g=>g.nodeType===1&&g.tagName.toLowerCase()==="template";return[f,h]}const ge=Fo;function hc(e){return Jo(e)}function pc(e){return Jo(e,dc)}function Jo(e,t){const n=so();n.__VUE__=!0;const{insert:r,remove:s,patchProp:o,createElement:i,createText:l,createComment:c,setText:a,setElementText:f,parentNode:h,nextSibling:p,setScopeId:y=xe,insertStaticContent:v}=e,T=(u,d,m,b=null,w=null,x=null,M=void 0,C=null,O=!!d.dynamicChildren)=>{if(u===d)return;u&&!ct(u,d)&&(b=tn(u),Ie(u,w,x,!0),u=null),d.patchFlag===-2&&(O=!1,d.dynamicChildren=null);const{type:E,ref:N,shapeFlag:D}=d;switch(E){case Rt:F(u,d,m,b);break;case be:U(u,d,m,b);break;case jt:u==null&&B(d,m,b,M);break;case me:I(u,d,m,b,w,x,M,C,O);break;default:D&1?P(u,d,m,b,w,x,M,C,O):D&6?G(u,d,m,b,w,x,M,C,O):(D&64||D&128)&&E.process(u,d,m,b,w,x,M,C,O,yt)}N!=null&&w&&Rn(N,u&&u.ref,x,d||u,!d)},F=(u,d,m,b)=>{if(u==null)r(d.el=l(d.children),m,b);else{const w=d.el=u.el;d.children!==u.children&&a(w,d.children)}},U=(u,d,m,b)=>{u==null?r(d.el=c(d.children||""),m,b):d.el=u.el},B=(u,d,m,b)=>{[u.el,u.anchor]=v(u.children,d,m,b,u.el,u.anchor)},g=({el:u,anchor:d},m,b)=>{let w;for(;u&&u!==d;)w=p(u),r(u,m,b),u=w;r(d,m,b)},_=({el:u,anchor:d})=>{let m;for(;u&&u!==d;)m=p(u),s(u),u=m;s(d)},P=(u,d,m,b,w,x,M,C,O)=>{d.type==="svg"?M="svg":d.type==="math"&&(M="mathml"),u==null?L(d,m,b,w,x,M,C,O):S(u,d,w,x,M,C,O)},L=(u,d,m,b,w,x,M,C)=>{let O,E;const{props:N,shapeFlag:D,transition:H,dirs:W}=u;if(O=u.el=i(u.type,x,N&&N.is,N),D&8?f(O,u.children):D&16&&R(u.children,O,null,b,w,lr(u,x),M,C),W&&Ne(u,null,b,"created"),$(O,u,u.scopeId,M,b),N){for(const Q in N)Q!=="value"&&!wt(Q)&&o(O,Q,null,N[Q],x,u.children,b,w,Ve);"value"in N&&o(O,"value",null,N.value,x),(E=N.onVnodeBeforeMount)&&Ee(E,b,u)}W&&Ne(u,null,b,"beforeMount");const z=Qo(w,H);z&&H.beforeEnter(O),r(O,d,m),((E=N&&N.onVnodeMounted)||z||W)&&ge(()=>{E&&Ee(E,b,u),z&&H.enter(O),W&&Ne(u,null,b,"mounted")},w)},$=(u,d,m,b,w)=>{if(m&&y(u,m),b)for(let x=0;x{for(let E=O;E{const C=d.el=u.el;let{patchFlag:O,dynamicChildren:E,dirs:N}=d;O|=u.patchFlag&16;const D=u.props||ee,H=d.props||ee;let W;if(m&&st(m,!1),(W=H.onVnodeBeforeUpdate)&&Ee(W,m,d,u),N&&Ne(d,u,m,"beforeUpdate"),m&&st(m,!0),E?A(u.dynamicChildren,E,C,m,b,lr(d,w),x):M||j(u,d,C,null,m,b,lr(d,w),x,!1),O>0){if(O&16)K(C,d,D,H,m,b,w);else if(O&2&&D.class!==H.class&&o(C,"class",null,H.class,w),O&4&&o(C,"style",D.style,H.style,w),O&8){const z=d.dynamicProps;for(let Q=0;Q{W&&Ee(W,m,d,u),N&&Ne(d,u,m,"updated")},b)},A=(u,d,m,b,w,x,M)=>{for(let C=0;C{if(m!==b){if(m!==ee)for(const C in m)!wt(C)&&!(C in b)&&o(u,C,m[C],null,M,d.children,w,x,Ve);for(const C in b){if(wt(C))continue;const O=b[C],E=m[C];O!==E&&C!=="value"&&o(u,C,E,O,M,d.children,w,x,Ve)}"value"in b&&o(u,"value",m.value,b.value,M)}},I=(u,d,m,b,w,x,M,C,O)=>{const E=d.el=u?u.el:l(""),N=d.anchor=u?u.anchor:l("");let{patchFlag:D,dynamicChildren:H,slotScopeIds:W}=d;W&&(C=C?C.concat(W):W),u==null?(r(E,m,b),r(N,m,b),R(d.children||[],m,N,w,x,M,C,O)):D>0&&D&64&&H&&u.dynamicChildren?(A(u.dynamicChildren,H,m,w,x,M,C),(d.key!=null||w&&d===w.subTree)&&zr(u,d,!0)):j(u,d,m,N,w,x,M,C,O)},G=(u,d,m,b,w,x,M,C,O)=>{d.slotScopeIds=C,u==null?d.shapeFlag&512?w.ctx.activate(d,m,b,M,O):ie(d,m,b,w,x,M,O):fe(u,d,O)},ie=(u,d,m,b,w,x,M)=>{const C=u.component=Tc(u,b,w);if(Yt(u)&&(C.ctx.renderer=yt),Sc(C),C.asyncDep){if(w&&w.registerDep(C,V),!u.el){const O=C.subTree=se(be);U(null,O,d,m)}}else V(C,u,d,m,w,x,M)},fe=(u,d,m)=>{const b=d.component=u.component;if(Ml(u,d,m))if(b.asyncDep&&!b.asyncResolved){X(b,d,m);return}else b.next=d,xl(b.update),b.effect.dirty=!0,b.update();else d.el=u.el,b.vnode=d},V=(u,d,m,b,w,x,M)=>{const C=()=>{if(u.isMounted){let{next:N,bu:D,u:H,parent:W,vnode:z}=u;{const _t=Zo(u);if(_t){N&&(N.el=z.el,X(u,N,M)),_t.asyncDep.then(()=>{u.isUnmounted||C()});return}}let Q=N,te;st(u,!1),N?(N.el=z.el,X(u,N,M)):N=z,D&&_n(D),(te=N.props&&N.props.onVnodeBeforeUpdate)&&Ee(te,W,N,z),st(u,!0);const ae=rr(u),Ae=u.subTree;u.subTree=ae,T(Ae,ae,h(Ae.el),tn(Ae),u,w,x),N.el=ae.el,Q===null&&Il(u,ae.el),H&&ge(H,w),(te=N.props&&N.props.onVnodeUpdated)&&ge(()=>Ee(te,W,N,z),w)}else{let N;const{el:D,props:H}=d,{bm:W,m:z,parent:Q}=u,te=xt(d);if(st(u,!1),W&&_n(W),!te&&(N=H&&H.onVnodeBeforeMount)&&Ee(N,Q,d),st(u,!0),D&&tr){const ae=()=>{u.subTree=rr(u),tr(D,u.subTree,u,w,null)};te?d.type.__asyncLoader().then(()=>!u.isUnmounted&&ae()):ae()}else{const ae=u.subTree=rr(u);T(null,ae,m,b,u,w,x),d.el=ae.el}if(z&&ge(z,w),!te&&(N=H&&H.onVnodeMounted)){const ae=d;ge(()=>Ee(N,Q,ae),w)}(d.shapeFlag&256||Q&&xt(Q.vnode)&&Q.vnode.shapeFlag&256)&&u.a&&ge(u.a,w),u.isMounted=!0,d=m=b=null}},O=u.effect=new Hr(C,xe,()=>Bn(E),u.scope),E=u.update=()=>{O.dirty&&O.run()};E.id=u.uid,st(u,!0),E()},X=(u,d,m)=>{d.component=u;const b=u.vnode.props;u.vnode=d,u.next=null,ic(u,d.props,b,m),ac(u,d.children,m),gt(),ds(u),mt()},j=(u,d,m,b,w,x,M,C,O=!1)=>{const E=u&&u.children,N=u?u.shapeFlag:0,D=d.children,{patchFlag:H,shapeFlag:W}=d;if(H>0){if(H&128){en(E,D,m,b,w,x,M,C,O);return}else if(H&256){je(E,D,m,b,w,x,M,C,O);return}}W&8?(N&16&&Ve(E,w,x),D!==E&&f(m,D)):N&16?W&16?en(E,D,m,b,w,x,M,C,O):Ve(E,w,x,!0):(N&8&&f(m,""),W&16&&R(D,m,b,w,x,M,C,O))},je=(u,d,m,b,w,x,M,C,O)=>{u=u||vt,d=d||vt;const E=u.length,N=d.length,D=Math.min(E,N);let H;for(H=0;HN?Ve(u,w,x,!0,!1,D):R(d,m,b,w,x,M,C,O,D)},en=(u,d,m,b,w,x,M,C,O)=>{let E=0;const N=d.length;let D=u.length-1,H=N-1;for(;E<=D&&E<=H;){const W=u[E],z=d[E]=O?Xe(d[E]):Re(d[E]);if(ct(W,z))T(W,z,m,null,w,x,M,C,O);else break;E++}for(;E<=D&&E<=H;){const W=u[D],z=d[H]=O?Xe(d[H]):Re(d[H]);if(ct(W,z))T(W,z,m,null,w,x,M,C,O);else break;D--,H--}if(E>D){if(E<=H){const W=H+1,z=WH)for(;E<=D;)Ie(u[E],w,x,!0),E++;else{const W=E,z=E,Q=new Map;for(E=z;E<=H;E++){const _e=d[E]=O?Xe(d[E]):Re(d[E]);_e.key!=null&&Q.set(_e.key,E)}let te,ae=0;const Ae=H-z+1;let _t=!1,es=0;const Lt=new Array(Ae);for(E=0;E=Ae){Ie(_e,w,x,!0);continue}let Pe;if(_e.key!=null)Pe=Q.get(_e.key);else for(te=z;te<=H;te++)if(Lt[te-z]===0&&ct(_e,d[te])){Pe=te;break}Pe===void 0?Ie(_e,w,x,!0):(Lt[Pe-z]=E+1,Pe>=es?es=Pe:_t=!0,T(_e,d[Pe],m,null,w,x,M,C,O),ae++)}const ts=_t?gc(Lt):vt;for(te=ts.length-1,E=Ae-1;E>=0;E--){const _e=z+E,Pe=d[_e],ns=_e+1{const{el:x,type:M,transition:C,children:O,shapeFlag:E}=u;if(E&6){rt(u.component.subTree,d,m,b);return}if(E&128){u.suspense.move(d,m,b);return}if(E&64){M.move(u,d,m,yt);return}if(M===me){r(x,d,m);for(let D=0;DC.enter(x),w);else{const{leave:D,delayLeave:H,afterLeave:W}=C,z=()=>r(x,d,m),Q=()=>{D(x,()=>{z(),W&&W()})};H?H(x,z,Q):Q()}else r(x,d,m)},Ie=(u,d,m,b=!1,w=!1)=>{const{type:x,props:M,ref:C,children:O,dynamicChildren:E,shapeFlag:N,patchFlag:D,dirs:H}=u;if(C!=null&&Rn(C,null,m,u,!0),N&256){d.ctx.deactivate(u);return}const W=N&1&&H,z=!xt(u);let Q;if(z&&(Q=M&&M.onVnodeBeforeUnmount)&&Ee(Q,d,u),N&6)Mi(u.component,m,b);else{if(N&128){u.suspense.unmount(m,b);return}W&&Ne(u,null,d,"beforeUnmount"),N&64?u.type.remove(u,d,m,w,yt,b):E&&(x!==me||D>0&&D&64)?Ve(E,d,m,!1,!0):(x===me&&D&384||!w&&N&16)&&Ve(O,d,m),b&&Qr(u)}(z&&(Q=M&&M.onVnodeUnmounted)||W)&&ge(()=>{Q&&Ee(Q,d,u),W&&Ne(u,null,d,"unmounted")},m)},Qr=u=>{const{type:d,el:m,anchor:b,transition:w}=u;if(d===me){Li(m,b);return}if(d===jt){_(u);return}const x=()=>{s(m),w&&!w.persisted&&w.afterLeave&&w.afterLeave()};if(u.shapeFlag&1&&w&&!w.persisted){const{leave:M,delayLeave:C}=w,O=()=>M(m,x);C?C(u.el,x,O):O()}else x()},Li=(u,d)=>{let m;for(;u!==d;)m=p(u),s(u),u=m;s(d)},Mi=(u,d,m)=>{const{bum:b,scope:w,update:x,subTree:M,um:C}=u;b&&_n(b),w.stop(),x&&(x.active=!1,Ie(M,u,d,m)),C&&ge(C,d),ge(()=>{u.isUnmounted=!0},d),d&&d.pendingBranch&&!d.isUnmounted&&u.asyncDep&&!u.asyncResolved&&u.suspenseId===d.pendingId&&(d.deps--,d.deps===0&&d.resolve())},Ve=(u,d,m,b=!1,w=!1,x=0)=>{for(let M=x;Mu.shapeFlag&6?tn(u.component.subTree):u.shapeFlag&128?u.suspense.next():p(u.anchor||u.el);let Zn=!1;const Zr=(u,d,m)=>{u==null?d._vnode&&Ie(d._vnode,null,null,!0):T(d._vnode||null,u,d,null,null,null,m),Zn||(Zn=!0,ds(),Tn(),Zn=!1),d._vnode=u},yt={p:T,um:Ie,m:rt,r:Qr,mt:ie,mc:R,pc:j,pbc:A,n:tn,o:e};let er,tr;return t&&([er,tr]=t(yt)),{render:Zr,hydrate:er,createApp:rc(Zr,er)}}function lr({type:e,props:t},n){return n==="svg"&&e==="foreignObject"||n==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:n}function st({effect:e,update:t},n){e.allowRecurse=t.allowRecurse=n}function Qo(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function zr(e,t,n=!1){const r=e.children,s=t.children;if(k(r)&&k(s))for(let o=0;o>1,e[n[l]]0&&(t[r]=n[o-1]),n[o]=r)}}for(o=n.length,i=n[o-1];o-- >0;)n[o]=i,i=t[i];return n}function Zo(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:Zo(t)}const mc=e=>e.__isTeleport,Ht=e=>e&&(e.disabled||e.disabled===""),xs=e=>typeof SVGElement<"u"&&e instanceof SVGElement,Ts=e=>typeof MathMLElement=="function"&&e instanceof MathMLElement,Rr=(e,t)=>{const n=e&&e.to;return ne(n)?t?t(n):null:n},yc={name:"Teleport",__isTeleport:!0,process(e,t,n,r,s,o,i,l,c,a){const{mc:f,pc:h,pbc:p,o:{insert:y,querySelector:v,createText:T,createComment:F}}=a,U=Ht(t.props);let{shapeFlag:B,children:g,dynamicChildren:_}=t;if(e==null){const P=t.el=T(""),L=t.anchor=T("");y(P,n,r),y(L,n,r);const $=t.target=Rr(t.props,v),R=t.targetAnchor=T("");$&&(y(R,$),i==="svg"||xs($)?i="svg":(i==="mathml"||Ts($))&&(i="mathml"));const S=(A,K)=>{B&16&&f(g,A,K,s,o,i,l,c)};U?S(n,L):$&&S($,R)}else{t.el=e.el;const P=t.anchor=e.anchor,L=t.target=e.target,$=t.targetAnchor=e.targetAnchor,R=Ht(e.props),S=R?n:L,A=R?P:$;if(i==="svg"||xs(L)?i="svg":(i==="mathml"||Ts(L))&&(i="mathml"),_?(p(e.dynamicChildren,_,S,s,o,i,l),zr(e,t,!0)):c||h(e,t,S,A,s,o,i,l,!1),U)R?t.props&&e.props&&t.props.to!==e.props.to&&(t.props.to=e.props.to):dn(t,n,P,a,1);else if((t.props&&t.props.to)!==(e.props&&e.props.to)){const K=t.target=Rr(t.props,v);K&&dn(t,K,null,a,0)}else R&&dn(t,L,$,a,1)}ei(t)},remove(e,t,n,r,{um:s,o:{remove:o}},i){const{shapeFlag:l,children:c,anchor:a,targetAnchor:f,target:h,props:p}=e;if(h&&o(f),i&&o(a),l&16){const y=i||!Ht(p);for(let v=0;v0?Oe||vt:null,vc(),Kt>0&&Oe&&Oe.push(e),e}function wu(e,t,n,r,s,o){return ni(oi(e,t,n,r,s,o,!0))}function ri(e,t,n,r,s){return ni(se(e,t,n,r,s,!0))}function On(e){return e?e.__v_isVNode===!0:!1}function ct(e,t){return e.type===t.type&&e.key===t.key}const Yn="__vInternal",si=({key:e})=>e??null,vn=({ref:e,ref_key:t,ref_for:n})=>(typeof e=="number"&&(e=""+e),e!=null?ne(e)||de(e)||q(e)?{i:le,r:e,k:t,f:!!n}:e:null);function oi(e,t=null,n=null,r=0,s=null,o=e===me?0:1,i=!1,l=!1){const c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&si(t),ref:t&&vn(t),scopeId:Wn,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetAnchor:null,staticCount:0,shapeFlag:o,patchFlag:r,dynamicProps:s,dynamicChildren:null,appContext:null,ctx:le};return l?(Xr(c,n),o&128&&e.normalize(c)):n&&(c.shapeFlag|=ne(n)?8:16),Kt>0&&!i&&Oe&&(c.patchFlag>0||o&6)&&c.patchFlag!==32&&Oe.push(c),c}const se=bc;function bc(e,t=null,n=null,r=0,s=null,o=!1){if((!e||e===Po)&&(e=be),On(e)){const l=nt(e,t,!0);return n&&Xr(l,n),Kt>0&&!o&&Oe&&(l.shapeFlag&6?Oe[Oe.indexOf(e)]=l:Oe.push(l)),l.patchFlag|=-2,l}if(Lc(e)&&(e=e.__vccOpts),t){t=wc(t);let{class:l,style:c}=t;l&&!ne(l)&&(t.class=$n(l)),Z(c)&&(Co(c)&&!k(c)&&(c=ce({},c)),t.style=Fn(c))}const i=ne(e)?1:Pl(e)?128:mc(e)?64:Z(e)?4:q(e)?2:0;return oi(e,t,n,r,s,i,o,!0)}function wc(e){return e?Co(e)||Yn in e?ce({},e):e:null}function nt(e,t,n=!1){const{props:r,ref:s,patchFlag:o,children:i}=e,l=t?Ec(r||{},t):r;return{__v_isVNode:!0,__v_skip:!0,type:e.type,props:l,key:l&&si(l),ref:t&&t.ref?n&&s?k(s)?s.concat(vn(t)):[s,vn(t)]:vn(t):s,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:i,target:e.target,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==me?o===-1?16:o|16:o,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:e.transition,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&nt(e.ssContent),ssFallback:e.ssFallback&&nt(e.ssFallback),el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce}}function ii(e=" ",t=0){return se(Rt,null,e,t)}function Eu(e,t){const n=se(jt,null,e);return n.staticCount=t,n}function Cu(e="",t=!1){return t?(ti(),ri(be,null,e)):se(be,null,e)}function Re(e){return e==null||typeof e=="boolean"?se(be):k(e)?se(me,null,e.slice()):typeof e=="object"?Xe(e):se(Rt,null,String(e))}function Xe(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:nt(e)}function Xr(e,t){let n=0;const{shapeFlag:r}=e;if(t==null)t=null;else if(k(t))n=16;else if(typeof t=="object")if(r&65){const s=t.default;s&&(s._c&&(s._d=!1),Xr(e,s()),s._c&&(s._d=!0));return}else{n=32;const s=t._;!s&&!(Yn in t)?t._ctx=le:s===3&&le&&(le.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else q(t)?(t={default:t,_ctx:le},n=32):(t=String(t),r&64?(n=16,t=[ii(t)]):n=8);e.children=t,e.shapeFlag|=n}function Ec(...e){const t={};for(let n=0;nue||le;let Ln,Or;{const e=so(),t=(n,r)=>{let s;return(s=e[n])||(s=e[n]=[]),s.push(r),o=>{s.length>1?s.forEach(i=>i(o)):s[0](o)}};Ln=t("__VUE_INSTANCE_SETTERS__",n=>ue=n),Or=t("__VUE_SSR_SETTERS__",n=>Zt=n)}const Qt=e=>{const t=ue;return Ln(e),e.scope.on(),()=>{e.scope.off(),Ln(t)}},As=()=>{ue&&ue.scope.off(),Ln(null)};function li(e){return e.vnode.shapeFlag&4}let Zt=!1;function Sc(e,t=!1){t&&Or(t);const{props:n,children:r}=e.vnode,s=li(e);oc(e,n,s,t),cc(e,r);const o=s?Ac(e,t):void 0;return t&&Or(!1),o}function Ac(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=Pt(new Proxy(e.ctx,Xl));const{setup:r}=n;if(r){const s=e.setupContext=r.length>1?ai(e):null,o=Qt(e);gt();const i=Qe(r,e,0,[e.props,s]);if(mt(),o(),to(i)){if(i.then(As,As),t)return i.then(l=>{Rs(e,l,t)}).catch(l=>{Xt(l,e,0)});e.asyncDep=i}else Rs(e,i,t)}else ci(e,t)}function Rs(e,t,n){q(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:Z(t)&&(e.setupState=Ao(t)),ci(e,n)}let Os;function ci(e,t,n){const r=e.type;if(!e.render){if(!t&&Os&&!r.render){const s=r.template||qr(e).template;if(s){const{isCustomElement:o,compilerOptions:i}=e.appContext.config,{delimiters:l,compilerOptions:c}=r,a=ce(ce({isCustomElement:o,delimiters:l},i),c);r.render=Os(s,a)}}e.render=r.render||xe}{const s=Qt(e);gt();try{Jl(e)}finally{mt(),s()}}}function Rc(e){return e.attrsProxy||(e.attrsProxy=new Proxy(e.attrs,{get(t,n){return ye(e,"get","$attrs"),t[n]}}))}function ai(e){const t=n=>{e.exposed=n||{}};return{get attrs(){return Rc(e)},slots:e.slots,emit:e.emit,expose:t}}function Jn(e){if(e.exposed)return e.exposeProxy||(e.exposeProxy=new Proxy(Ao(Pt(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in Ft)return Ft[n](e)},has(t,n){return n in t||n in Ft}}))}function Oc(e,t=!0){return q(e)?e.displayName||e.name:e.name||t&&e.__name}function Lc(e){return q(e)&&"__vccOpts"in e}const re=(e,t)=>pl(e,t,Zt);function Lr(e,t,n){const r=arguments.length;return r===2?Z(t)&&!k(t)?On(t)?se(e,null,[t]):se(e,t):se(e,null,t):(r>3?n=Array.prototype.slice.call(arguments,2):r===3&&On(n)&&(n=[n]),se(e,t,n))}const Mc="3.4.18";/** +* @vue/runtime-dom v3.4.18 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/const Ic="http://www.w3.org/2000/svg",Pc="http://www.w3.org/1998/Math/MathML",Ye=typeof document<"u"?document:null,Ls=Ye&&Ye.createElement("template"),Nc={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,r)=>{const s=t==="svg"?Ye.createElementNS(Ic,e):t==="mathml"?Ye.createElementNS(Pc,e):Ye.createElement(e,n?{is:n}:void 0);return e==="select"&&r&&r.multiple!=null&&s.setAttribute("multiple",r.multiple),s},createText:e=>Ye.createTextNode(e),createComment:e=>Ye.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Ye.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,r,s,o){const i=n?n.previousSibling:t.lastChild;if(s&&(s===o||s.nextSibling))for(;t.insertBefore(s.cloneNode(!0),n),!(s===o||!(s=s.nextSibling)););else{Ls.innerHTML=r==="svg"?`${e}`:r==="mathml"?`${e}`:e;const l=Ls.content;if(r==="svg"||r==="mathml"){const c=l.firstChild;for(;c.firstChild;)l.appendChild(c.firstChild);l.removeChild(c)}t.insertBefore(l,n)}return[i?i.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},We="transition",Mt="animation",Wt=Symbol("_vtc"),ui=(e,{slots:t})=>Lr(Vl,Fc(e),t);ui.displayName="Transition";const fi={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String};ui.props=ce({},Ho,fi);const ot=(e,t=[])=>{k(e)?e.forEach(n=>n(...t)):e&&e(...t)},Ms=e=>e?k(e)?e.some(t=>t.length>1):e.length>1:!1;function Fc(e){const t={};for(const I in e)I in fi||(t[I]=e[I]);if(e.css===!1)return t;const{name:n="v",type:r,duration:s,enterFromClass:o=`${n}-enter-from`,enterActiveClass:i=`${n}-enter-active`,enterToClass:l=`${n}-enter-to`,appearFromClass:c=o,appearActiveClass:a=i,appearToClass:f=l,leaveFromClass:h=`${n}-leave-from`,leaveActiveClass:p=`${n}-leave-active`,leaveToClass:y=`${n}-leave-to`}=e,v=$c(s),T=v&&v[0],F=v&&v[1],{onBeforeEnter:U,onEnter:B,onEnterCancelled:g,onLeave:_,onLeaveCancelled:P,onBeforeAppear:L=U,onAppear:$=B,onAppearCancelled:R=g}=t,S=(I,G,ie)=>{it(I,G?f:l),it(I,G?a:i),ie&&ie()},A=(I,G)=>{I._isLeaving=!1,it(I,h),it(I,y),it(I,p),G&&G()},K=I=>(G,ie)=>{const fe=I?$:B,V=()=>S(G,I,ie);ot(fe,[G,V]),Is(()=>{it(G,I?c:o),qe(G,I?f:l),Ms(fe)||Ps(G,r,T,V)})};return ce(t,{onBeforeEnter(I){ot(U,[I]),qe(I,o),qe(I,i)},onBeforeAppear(I){ot(L,[I]),qe(I,c),qe(I,a)},onEnter:K(!1),onAppear:K(!0),onLeave(I,G){I._isLeaving=!0;const ie=()=>A(I,G);qe(I,h),Vc(),qe(I,p),Is(()=>{I._isLeaving&&(it(I,h),qe(I,y),Ms(_)||Ps(I,r,F,ie))}),ot(_,[I,ie])},onEnterCancelled(I){S(I,!1),ot(g,[I])},onAppearCancelled(I){S(I,!0),ot(R,[I])},onLeaveCancelled(I){A(I),ot(P,[I])}})}function $c(e){if(e==null)return null;if(Z(e))return[cr(e.enter),cr(e.leave)];{const t=cr(e);return[t,t]}}function cr(e){return Hi(e)}function qe(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e[Wt]||(e[Wt]=new Set)).add(t)}function it(e,t){t.split(/\s+/).forEach(r=>r&&e.classList.remove(r));const n=e[Wt];n&&(n.delete(t),n.size||(e[Wt]=void 0))}function Is(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let Hc=0;function Ps(e,t,n,r){const s=e._endId=++Hc,o=()=>{s===e._endId&&r()};if(n)return setTimeout(o,n);const{type:i,timeout:l,propCount:c}=jc(e,t);if(!i)return r();const a=i+"end";let f=0;const h=()=>{e.removeEventListener(a,p),o()},p=y=>{y.target===e&&++f>=c&&h()};setTimeout(()=>{f(n[v]||"").split(", "),s=r(`${We}Delay`),o=r(`${We}Duration`),i=Ns(s,o),l=r(`${Mt}Delay`),c=r(`${Mt}Duration`),a=Ns(l,c);let f=null,h=0,p=0;t===We?i>0&&(f=We,h=i,p=o.length):t===Mt?a>0&&(f=Mt,h=a,p=c.length):(h=Math.max(i,a),f=h>0?i>a?We:Mt:null,p=f?f===We?o.length:c.length:0);const y=f===We&&/\b(transform|all)(,|$)/.test(r(`${We}Property`).toString());return{type:f,timeout:h,propCount:p,hasTransform:y}}function Ns(e,t){for(;e.lengthFs(n)+Fs(e[r])))}function Fs(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function Vc(){return document.body.offsetHeight}function Dc(e,t,n){const r=e[Wt];r&&(t=(t?[t,...r]:[...r]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const $s=Symbol("_vod"),kc=Symbol(""),Uc=/(^|;)\s*display\s*:/;function Bc(e,t,n){const r=e.style,s=ne(n),o=r.display;let i=!1;if(n&&!s){if(t&&!ne(t))for(const l in t)n[l]==null&&Mr(r,l,"");for(const l in n)l==="display"&&(i=!0),Mr(r,l,n[l])}else if(s){if(t!==n){const l=r[kc];l&&(n+=";"+l),r.cssText=n,i=Uc.test(n)}}else t&&e.removeAttribute("style");$s in e&&(e[$s]=i?r.display:"",r.display=o)}const Hs=/\s*!important$/;function Mr(e,t,n){if(k(n))n.forEach(r=>Mr(e,t,r));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const r=Kc(e,t);Hs.test(n)?e.setProperty(pt(r),n.replace(Hs,""),"important"):e[r]=n}}const js=["Webkit","Moz","ms"],ar={};function Kc(e,t){const n=ar[t];if(n)return n;let r=He(t);if(r!=="filter"&&r in e)return ar[t]=r;r=Nn(r);for(let s=0;sur||(Yc.then(()=>ur=0),ur=Date.now());function Qc(e,t){const n=r=>{if(!r._vts)r._vts=Date.now();else if(r._vts<=n.attached)return;Te(Zc(r,n.value),t,5,[r])};return n.value=e,n.attached=Jc(),n}function Zc(e,t){if(k(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(r=>s=>!s._stopped&&r&&r(s))}else return t}const Us=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,ea=(e,t,n,r,s,o,i,l,c)=>{const a=s==="svg";t==="class"?Dc(e,r,a):t==="style"?Bc(e,n,r):qt(t)?Nr(t)||zc(e,t,n,r,i):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):ta(e,t,r,a))?qc(e,t,r,o,i,l,c):(t==="true-value"?e._trueValue=r:t==="false-value"&&(e._falseValue=r),Wc(e,t,r,a))};function ta(e,t,n,r){if(r)return!!(t==="innerHTML"||t==="textContent"||t in e&&Us(t)&&q(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const s=e.tagName;if(s==="IMG"||s==="VIDEO"||s==="CANVAS"||s==="SOURCE")return!1}return Us(t)&&ne(n)?!1:t in e}const Mn=e=>{const t=e.props["onUpdate:modelValue"]||!1;return k(t)?n=>_n(t,n):t};function na(e){e.target.composing=!0}function Bs(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const St=Symbol("_assign"),xu={created(e,{modifiers:{lazy:t,trim:n,number:r}},s){e[St]=Mn(s);const o=r||s.props&&s.props.type==="number";at(e,t?"change":"input",i=>{if(i.target.composing)return;let l=e.value;n&&(l=l.trim()),o&&(l=yr(l)),e[St](l)}),n&&at(e,"change",()=>{e.value=e.value.trim()}),t||(at(e,"compositionstart",na),at(e,"compositionend",Bs),at(e,"change",Bs))},mounted(e,{value:t}){e.value=t??""},beforeUpdate(e,{value:t,modifiers:{lazy:n,trim:r,number:s}},o){if(e[St]=Mn(o),e.composing)return;const i=s||e.type==="number"?yr(e.value):e.value,l=t??"";i!==l&&(document.activeElement===e&&e.type!=="range"&&(n||r&&e.value.trim()===l)||(e.value=l))}},Tu={created(e,{value:t},n){e.checked=En(t,n.props.value),e[St]=Mn(n),at(e,"change",()=>{e[St](ra(e))})},beforeUpdate(e,{value:t,oldValue:n},r){e[St]=Mn(r),t!==n&&(e.checked=En(t,r.props.value))}};function ra(e){return"_value"in e?e._value:e.value}const sa=["ctrl","shift","alt","meta"],oa={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>sa.some(n=>e[`${n}Key`]&&!t.includes(n))},Su=(e,t)=>{const n=e._withMods||(e._withMods={}),r=t.join(".");return n[r]||(n[r]=(s,...o)=>{for(let i=0;i{const n=e._withKeys||(e._withKeys={}),r=t.join(".");return n[r]||(n[r]=s=>{if(!("key"in s))return;const o=pt(s.key);if(t.some(i=>i===o||ia[i]===o))return e(s)})},di=ce({patchProp:ea},Nc);let Dt,Ks=!1;function la(){return Dt||(Dt=hc(di))}function ca(){return Dt=Ks?Dt:pc(di),Ks=!0,Dt}const Ru=(...e)=>{const t=la().createApp(...e),{mount:n}=t;return t.mount=r=>{const s=pi(r);if(!s)return;const o=t._component;!q(o)&&!o.render&&!o.template&&(o.template=s.innerHTML),s.innerHTML="";const i=n(s,!1,hi(s));return s instanceof Element&&(s.removeAttribute("v-cloak"),s.setAttribute("data-v-app","")),i},t},Ou=(...e)=>{const t=ca().createApp(...e),{mount:n}=t;return t.mount=r=>{const s=pi(r);if(s)return n(s,!0,hi(s))},t};function hi(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function pi(e){return ne(e)?document.querySelector(e):e}const Lu=(e,t)=>{const n=e.__vccOpts||e;for(const[r,s]of t)n[r]=s;return n},aa="modulepreload",ua=function(e){return"/iroha-2-docs/"+e},Ws={},Mu=function(t,n,r){let s=Promise.resolve();if(n&&n.length>0){const o=document.getElementsByTagName("link");s=Promise.all(n.map(i=>{if(i=ua(i),i in Ws)return;Ws[i]=!0;const l=i.endsWith(".css"),c=l?'[rel="stylesheet"]':"";if(!!r)for(let h=o.length-1;h>=0;h--){const p=o[h];if(p.href===i&&(!l||p.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${i}"]${c}`))return;const f=document.createElement("link");if(f.rel=l?"stylesheet":aa,l||(f.as="script",f.crossOrigin=""),f.href=i,document.head.appendChild(f),l)return new Promise((h,p)=>{f.addEventListener("load",h),f.addEventListener("error",()=>p(new Error(`Unable to preload CSS for ${i}`)))})}))}return s.then(()=>t()).catch(o=>{const i=new Event("vite:preloadError",{cancelable:!0});if(i.payload=o,window.dispatchEvent(i),!i.defaultPrevented)throw o})},fa=window.__VP_SITE_DATA__;function Iu(e,t){var n;const r=kn();return qn(()=>{r.value=e()},{...t,flush:(n=t==null?void 0:t.flush)!=null?n:"sync"}),zt(r)}function Qn(e){return co()?(qi(e),!0):!1}function Le(e){return typeof e=="function"?e():So(e)}const gi=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const da=e=>e!=null,ha=Object.prototype.toString,pa=e=>ha.call(e)==="[object Object]",Me=()=>{},Ir=ga();function ga(){var e,t;return gi&&((e=window==null?void 0:window.navigator)==null?void 0:e.userAgent)&&(/iP(ad|hone|od)/.test(window.navigator.userAgent)||((t=window==null?void 0:window.navigator)==null?void 0:t.maxTouchPoints)>2&&/iPad|Macintosh/.test(window==null?void 0:window.navigator.userAgent))}function ma(e,t){function n(...r){return new Promise((s,o)=>{Promise.resolve(e(()=>t.apply(this,r),{fn:t,thisArg:this,args:r})).then(s).catch(o)})}return n}const mi=e=>e();function ya(e,t={}){let n,r,s=Me;const o=l=>{clearTimeout(l),s(),s=Me};return l=>{const c=Le(e),a=Le(t.maxWait);return n&&o(n),c<=0||a!==void 0&&a<=0?(r&&(o(r),r=null),Promise.resolve(l())):new Promise((f,h)=>{s=t.rejectOnCancel?h:f,a&&!r&&(r=setTimeout(()=>{n&&o(n),r=null,f(l())},a)),n=setTimeout(()=>{r&&o(r),r=null,f(l())},c)})}}function _a(e=mi){const t=oe(!0);function n(){t.value=!1}function r(){t.value=!0}const s=(...o)=>{t.value&&e(...o)};return{isActive:zt(t),pause:n,resume:r,eventFilter:s}}function va(e){return e||Jt()}function yi(...e){if(e.length!==1)return bl(...e);const t=e[0];return typeof t=="function"?zt(Ro(()=>({get:t,set:Me}))):oe(t)}function _i(e,t,n={}){const{eventFilter:r=mi,...s}=n;return $e(e,ma(r,t),s)}function ba(e,t,n={}){const{eventFilter:r,...s}=n,{eventFilter:o,pause:i,resume:l,isActive:c}=_a(r);return{stop:_i(e,t,{...s,eventFilter:o}),pause:i,resume:l,isActive:c}}function Yr(e,t=!0,n){va()?Ot(e,n):t?e():Un(e)}function Pu(e,t,n={}){const{debounce:r=0,maxWait:s=void 0,...o}=n;return _i(e,t,{...o,eventFilter:ya(r,{maxWait:s})})}function Nu(e,t,n){return $e(e,(r,s,o)=>{r&&t(r,s,o)},n)}function Fu(e,t,n){let r;de(n)?r={evaluating:n}:r=n||{};const{lazy:s=!1,evaluating:o=void 0,shallow:i=!0,onError:l=Me}=r,c=oe(!s),a=i?kn(t):oe(t);let f=0;return qn(async h=>{if(!c.value)return;f++;const p=f;let y=!1;o&&Promise.resolve().then(()=>{o.value=!0});try{const v=await e(T=>{h(()=>{o&&(o.value=!1),y||T()})});p===f&&(a.value=v)}catch(v){l(v)}finally{o&&p===f&&(o.value=!1),y=!0}}),s?re(()=>(c.value=!0,a.value)):a}function De(e){var t;const n=Le(e);return(t=n==null?void 0:n.$el)!=null?t:n}const Se=gi?window:void 0;function Ze(...e){let t,n,r,s;if(typeof e[0]=="string"||Array.isArray(e[0])?([n,r,s]=e,t=Se):[t,n,r,s]=e,!t)return Me;Array.isArray(n)||(n=[n]),Array.isArray(r)||(r=[r]);const o=[],i=()=>{o.forEach(f=>f()),o.length=0},l=(f,h,p,y)=>(f.addEventListener(h,p,y),()=>f.removeEventListener(h,p,y)),c=$e(()=>[De(t),Le(s)],([f,h])=>{if(i(),!f)return;const p=pa(h)?{...h}:h;o.push(...n.flatMap(y=>r.map(v=>l(f,y,v,p))))},{immediate:!0,flush:"post"}),a=()=>{c(),i()};return Qn(a),a}let qs=!1;function $u(e,t,n={}){const{window:r=Se,ignore:s=[],capture:o=!0,detectIframe:i=!1}=n;if(!r)return Me;Ir&&!qs&&(qs=!0,Array.from(r.document.body.children).forEach(p=>p.addEventListener("click",Me)),r.document.documentElement.addEventListener("click",Me));let l=!0;const c=p=>s.some(y=>{if(typeof y=="string")return Array.from(r.document.querySelectorAll(y)).some(v=>v===p.target||p.composedPath().includes(v));{const v=De(y);return v&&(p.target===v||p.composedPath().includes(v))}}),f=[Ze(r,"click",p=>{const y=De(e);if(!(!y||y===p.target||p.composedPath().includes(y))){if(p.detail===0&&(l=!c(p)),!l){l=!0;return}t(p)}},{passive:!0,capture:o}),Ze(r,"pointerdown",p=>{const y=De(e);l=!c(p)&&!!(y&&!p.composedPath().includes(y))},{passive:!0}),i&&Ze(r,"blur",p=>{setTimeout(()=>{var y;const v=De(e);((y=r.document.activeElement)==null?void 0:y.tagName)==="IFRAME"&&!(v!=null&&v.contains(r.document.activeElement))&&t(p)},0)})].filter(Boolean);return()=>f.forEach(p=>p())}function wa(e){return typeof e=="function"?e:typeof e=="string"?t=>t.key===e:Array.isArray(e)?t=>e.includes(t.key):()=>!0}function Hu(...e){let t,n,r={};e.length===3?(t=e[0],n=e[1],r=e[2]):e.length===2?typeof e[1]=="object"?(t=!0,n=e[0],r=e[1]):(t=e[0],n=e[1]):(t=!0,n=e[0]);const{target:s=Se,eventName:o="keydown",passive:i=!1,dedupe:l=!1}=r,c=wa(t);return Ze(s,o,f=>{f.repeat&&Le(l)||c(f)&&n(f)},i)}function ju(e,t=null){const n=Jt();let r=()=>{};const s=Ro((o,i)=>(r=i,{get(){var l,c;return o(),(c=(l=n==null?void 0:n.proxy)==null?void 0:l.$refs[e])!=null?c:t},set(){}}));return Yr(r),ko(r),s}function Ea(){const e=oe(!1);return Jt()&&Ot(()=>{e.value=!0}),e}function vi(e){const t=Ea();return re(()=>(t.value,!!e()))}function Ca(e,t={}){const{window:n=Se}=t,r=vi(()=>n&&"matchMedia"in n&&typeof n.matchMedia=="function");let s;const o=oe(!1),i=a=>{o.value=a.matches},l=()=>{s&&("removeEventListener"in s?s.removeEventListener("change",i):s.removeListener(i))},c=qn(()=>{r.value&&(l(),s=n.matchMedia(Le(e)),"addEventListener"in s?s.addEventListener("change",i):s.addListener(i),o.value=s.matches)});return Qn(()=>{c(),l(),s=void 0}),o}const hn=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},pn="__vueuse_ssr_handlers__",xa=Ta();function Ta(){return pn in hn||(hn[pn]=hn[pn]||{}),hn[pn]}function bi(e,t){return xa[e]||t}function Sa(e){return e==null?"any":e instanceof Set?"set":e instanceof Map?"map":e instanceof Date?"date":typeof e=="boolean"?"boolean":typeof e=="string"?"string":typeof e=="object"?"object":Number.isNaN(e)?"any":"number"}const Aa={boolean:{read:e=>e==="true",write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}},Gs="vueuse-storage";function Jr(e,t,n,r={}){var s;const{flush:o="pre",deep:i=!0,listenToStorageChanges:l=!0,writeDefaults:c=!0,mergeDefaults:a=!1,shallow:f,window:h=Se,eventFilter:p,onError:y=S=>{console.error(S)},initOnMounted:v}=r,T=(f?kn:oe)(typeof t=="function"?t():t);if(!n)try{n=bi("getDefaultStorage",()=>{var S;return(S=Se)==null?void 0:S.localStorage})()}catch(S){y(S)}if(!n)return T;const F=Le(t),U=Sa(F),B=(s=r.serializer)!=null?s:Aa[U],{pause:g,resume:_}=ba(T,()=>P(T.value),{flush:o,deep:i,eventFilter:p});return h&&l&&Yr(()=>{Ze(h,"storage",R),Ze(h,Gs,$),v&&R()}),v||R(),T;function P(S){try{if(S==null)n.removeItem(e);else{const A=B.write(S),K=n.getItem(e);K!==A&&(n.setItem(e,A),h&&h.dispatchEvent(new CustomEvent(Gs,{detail:{key:e,oldValue:K,newValue:A,storageArea:n}})))}}catch(A){y(A)}}function L(S){const A=S?S.newValue:n.getItem(e);if(A==null)return c&&F!=null&&n.setItem(e,B.write(F)),F;if(!S&&a){const K=B.read(A);return typeof a=="function"?a(K,F):U==="object"&&!Array.isArray(K)?{...F,...K}:K}else return typeof A!="string"?A:B.read(A)}function $(S){R(S.detail)}function R(S){if(!(S&&S.storageArea!==n)){if(S&&S.key==null){T.value=F;return}if(!(S&&S.key!==e)){g();try{(S==null?void 0:S.newValue)!==B.write(T.value)&&(T.value=L(S))}catch(A){y(A)}finally{S?Un(_):_()}}}}}function wi(e){return Ca("(prefers-color-scheme: dark)",e)}function Ra(e={}){const{selector:t="html",attribute:n="class",initialValue:r="auto",window:s=Se,storage:o,storageKey:i="vueuse-color-scheme",listenToStorageChanges:l=!0,storageRef:c,emitAuto:a,disableTransition:f=!0}=e,h={auto:"",light:"light",dark:"dark",...e.modes||{}},p=wi({window:s}),y=re(()=>p.value?"dark":"light"),v=c||(i==null?yi(r):Jr(i,r,o,{window:s,listenToStorageChanges:l})),T=re(()=>v.value==="auto"?y.value:v.value),F=bi("updateHTMLAttrs",(_,P,L)=>{const $=typeof _=="string"?s==null?void 0:s.document.querySelector(_):De(_);if(!$)return;let R;if(f&&(R=s.document.createElement("style"),R.appendChild(document.createTextNode("*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}")),s.document.head.appendChild(R)),P==="class"){const S=L.split(/\s/g);Object.values(h).flatMap(A=>(A||"").split(/\s/g)).filter(Boolean).forEach(A=>{S.includes(A)?$.classList.add(A):$.classList.remove(A)})}else $.setAttribute(P,L);f&&(s.getComputedStyle(R).opacity,document.head.removeChild(R))});function U(_){var P;F(t,n,(P=h[_])!=null?P:_)}function B(_){e.onChanged?e.onChanged(_,U):U(_)}$e(T,B,{flush:"post",immediate:!0}),Yr(()=>B(T.value));const g=re({get(){return a?v.value:T.value},set(_){v.value=_}});try{return Object.assign(g,{store:v,system:y,state:T})}catch{return g}}function Oa(e={}){const{valueDark:t="dark",valueLight:n="",window:r=Se}=e,s=Ra({...e,onChanged:(l,c)=>{var a;e.onChanged?(a=e.onChanged)==null||a.call(e,l==="dark",c,l):c(l)},modes:{dark:t,light:n}}),o=re(()=>s.system?s.system.value:wi({window:r}).value?"dark":"light");return re({get(){return s.value==="dark"},set(l){const c=l?"dark":"light";o.value===c?s.value="auto":s.value=c}})}function Vu(e,t,n={}){const{root:r,rootMargin:s="0px",threshold:o=.1,window:i=Se,immediate:l=!0}=n,c=vi(()=>i&&"IntersectionObserver"in i),a=re(()=>{const v=Le(e);return(Array.isArray(v)?v:[v]).map(De).filter(da)});let f=Me;const h=oe(l),p=c.value?$e(()=>[a.value,De(r),h.value],([v,T])=>{if(f(),!h.value||!v.length)return;const F=new IntersectionObserver(t,{root:De(T),rootMargin:s,threshold:o});v.forEach(U=>U&&F.observe(U)),f=()=>{F.disconnect(),f=Me}},{immediate:l,flush:"post"}):Me,y=()=>{f(),p(),h.value=!1};return Qn(y),{isSupported:c,isActive:h,pause(){f(),h.value=!1},resume(){h.value=!0},stop:y}}function fr(e){return typeof Window<"u"&&e instanceof Window?e.document.documentElement:typeof Document<"u"&&e instanceof Document?e.documentElement:e}function Du(e,t,n={}){const{window:r=Se}=n;return Jr(e,t,r==null?void 0:r.localStorage,n)}function Ei(e){const t=window.getComputedStyle(e);if(t.overflowX==="scroll"||t.overflowY==="scroll"||t.overflowX==="auto"&&e.clientWidth1?!0:(t.preventDefault&&t.preventDefault(),!1)}const gn=new WeakMap;function ku(e,t=!1){const n=oe(t);let r=null,s;$e(yi(e),l=>{const c=fr(Le(l));if(c){const a=c;gn.get(a)||gn.set(a,s),n.value&&(a.style.overflow="hidden")}},{immediate:!0});const o=()=>{const l=fr(Le(e));!l||n.value||(Ir&&(r=Ze(l,"touchmove",c=>{La(c)},{passive:!1})),l.style.overflow="hidden",n.value=!0)},i=()=>{var l;const c=fr(Le(e));!c||!n.value||(Ir&&(r==null||r()),c.style.overflow=(l=gn.get(c))!=null?l:"",gn.delete(c),n.value=!1)};return Qn(i),re({get(){return n.value},set(l){l?o():i()}})}function Uu(e,t,n={}){const{window:r=Se}=n;return Jr(e,t,r==null?void 0:r.sessionStorage,n)}function Bu(e={}){const{window:t=Se,behavior:n="auto"}=e;if(!t)return{x:oe(0),y:oe(0)};const r=oe(t.scrollX),s=oe(t.scrollY),o=re({get(){return r.value},set(l){scrollTo({left:l,behavior:n})}}),i=re({get(){return s.value},set(l){scrollTo({top:l,behavior:n})}});return Ze(t,"scroll",()=>{r.value=t.scrollX,s.value=t.scrollY},{capture:!1,passive:!0}),{x:o,y:i}}var dr={VITE_FEEDBACK_URL:"https://164.92.190.45/feedback/form",VITE_COMPAT_MATRIX_URL:"https://docs-compat.iroha2.tachi.soramitsu.co.jp/compat-matrix",BASE_URL:"/iroha-2-docs/",MODE:"production",DEV:!1,PROD:!0,SSR:!1},Ma={};const Ci=/^(?:[a-z]+:|\/\/)/i,Ia="vitepress-theme-appearance",Pa=/#.*$/,Na=/[?#].*$/,Fa=/(?:(^|\/)index)?\.(?:md|html)$/,Ce=typeof document<"u",xi={relativePath:"",filePath:"",title:"404",description:"Not Found",headers:[],frontmatter:{sidebar:!1,layout:"page"},lastUpdated:0,isNotFound:!0};function $a(e,t,n=!1){if(t===void 0)return!1;if(e=zs(`/${e}`),n)return new RegExp(t).test(e);if(zs(t)!==e)return!1;const r=t.match(Pa);return r?(Ce?location.hash:"")===r[0]:!0}function zs(e){return decodeURI(e).replace(Na,"").replace(Fa,"$1")}function Ha(e){return Ci.test(e)}function ja(e,t){var r,s,o,i,l,c,a;const n=Object.keys(e.locales).find(f=>f!=="root"&&!Ha(f)&&$a(t,`/${f}/`,!0))||"root";return Object.assign({},e,{localeIndex:n,lang:((r=e.locales[n])==null?void 0:r.lang)??e.lang,dir:((s=e.locales[n])==null?void 0:s.dir)??e.dir,title:((o=e.locales[n])==null?void 0:o.title)??e.title,titleTemplate:((i=e.locales[n])==null?void 0:i.titleTemplate)??e.titleTemplate,description:((l=e.locales[n])==null?void 0:l.description)??e.description,head:Si(e.head,((c=e.locales[n])==null?void 0:c.head)??[]),themeConfig:{...e.themeConfig,...(a=e.locales[n])==null?void 0:a.themeConfig}})}function Ti(e,t){const n=t.title||e.title,r=t.titleTemplate??e.titleTemplate;if(typeof r=="string"&&r.includes(":title"))return r.replace(/:title/g,n);const s=Va(e.title,r);return n===s.slice(3)?n:`${n}${s}`}function Va(e,t){return t===!1?"":t===!0||t===void 0?` | ${e}`:e===t?"":` | ${t}`}function Da(e,t){const[n,r]=t;if(n!=="meta")return!1;const s=Object.entries(r)[0];return s==null?!1:e.some(([o,i])=>o===n&&i[s[0]]===s[1])}function Si(e,t){return[...e.filter(n=>!Da(t,n)),...t]}const ka=/[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g,Ua=/^[a-z]:/i;function Xs(e){const t=Ua.exec(e),n=t?t[0]:"";return n+e.slice(n.length).replace(ka,"_").replace(/(^|\/)_+(?=[^/]*$)/,"$1")}const hr=new Set;function Ba(e){if(hr.size===0){const n=typeof process=="object"&&Ma.VITE_EXTRA_EXTENSIONS||(dr==null?void 0:dr.VITE_EXTRA_EXTENSIONS)||"";("3g2,3gp,aac,ai,apng,au,avif,bin,bmp,cer,class,conf,crl,css,csv,dll,doc,eps,epub,exe,gif,gz,ics,ief,jar,jpe,jpeg,jpg,js,json,jsonld,m4a,man,mid,midi,mjs,mov,mp2,mp3,mp4,mpe,mpeg,mpg,mpp,oga,ogg,ogv,ogx,opus,otf,p10,p7c,p7m,p7s,pdf,png,ps,qt,roff,rtf,rtx,ser,svg,t,tif,tiff,tr,ts,tsv,ttf,txt,vtt,wav,weba,webm,webp,woff,woff2,xhtml,xml,yaml,yml,zip"+(n&&typeof n=="string"?","+n:"")).split(",").forEach(r=>hr.add(r))}const t=e.split(".").pop();return t==null||!hr.has(t.toLowerCase())}function Ku(e){return e.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d")}const Ka=Symbol(),ht=kn(fa);function Wu(e){const t=re(()=>ja(ht.value,e.data.relativePath)),n=t.value.appearance,r=n==="force-dark"?oe(!0):n?Oa({storageKey:Ia,initialValue:()=>typeof n=="string"?n:"auto",...typeof n=="object"?n:{}}):oe(!1);return{site:t,theme:re(()=>t.value.themeConfig),page:re(()=>e.data),frontmatter:re(()=>e.data.frontmatter),params:re(()=>e.data.params),lang:re(()=>t.value.lang),dir:re(()=>e.data.frontmatter.dir||t.value.dir),localeIndex:re(()=>t.value.localeIndex||"root"),title:re(()=>Ti(t.value,e.data)),description:re(()=>e.data.description||t.value.description),isDark:r}}function Wa(){const e=Tt(Ka);if(!e)throw new Error("vitepress data not properly injected in app");return e}function qa(e,t){return`${e}${t}`.replace(/\/+/g,"/")}function Ys(e){return Ci.test(e)||!e.startsWith("/")?e:qa(ht.value.base,e)}function Ga(e){let t=e.replace(/\.html$/,"");if(t=decodeURIComponent(t),t=t.replace(/\/$/,"/index"),Ce){const n="/iroha-2-docs/";t=Xs(t.slice(n.length).replace(/\//g,"_")||"index")+".md";let r=__VP_HASH_MAP__[t.toLowerCase()];if(r||(t=t.endsWith("_index.md")?t.slice(0,-9)+".md":t.slice(0,-3)+"_index.md",r=__VP_HASH_MAP__[t.toLowerCase()]),!r)return null;t=`${n}assets/${t}.${r}.js`}else t=`./${Xs(t.slice(1).replace(/\//g,"_"))}.md.js`;return t}let bn=[];function qu(e){bn.push(e),Xn(()=>{bn=bn.filter(t=>t!==e)})}function za(){let e=ht.value.scrollOffset,t=0,n=24;if(typeof e=="object"&&"padding"in e&&(n=e.padding,e=e.selector),typeof e=="number")t=e;else if(typeof e=="string")t=Js(e,n);else if(Array.isArray(e))for(const r of e){const s=Js(r,n);if(s){t=s;break}}return t}function Js(e,t){const n=document.querySelector(e);if(!n)return 0;const r=n.getBoundingClientRect().bottom;return r<0?0:r+t}const Xa=Symbol(),Ai="http://a.com",Ya=()=>({path:"/",component:null,data:xi});function Gu(e,t){const n=Vn(Ya()),r={route:n,go:s};async function s(l=Ce?location.href:"/"){var c,a;l=In(l),await((c=r.onBeforeRouteChange)==null?void 0:c.call(r,l))!==!1&&(Zs(l),await i(l),await((a=r.onAfterRouteChanged)==null?void 0:a.call(r,l)))}let o=null;async function i(l,c=0,a=!1){var p;if(await((p=r.onBeforePageLoad)==null?void 0:p.call(r,l))===!1)return;const f=new URL(l,Ai),h=o=f.pathname;try{let y=await e(h);if(!y)throw new Error(`Page not found: ${h}`);if(o===h){o=null;const{default:v,__pageData:T}=y;if(!v)throw new Error(`Invalid route component: ${v}`);n.path=Ce?h:Ys(h),n.component=Pt(v),n.data=Pt(T),Ce&&Un(()=>{let F=ht.value.base+T.relativePath.replace(/(?:(^|\/)index)?\.md$/,"$1");if(!ht.value.cleanUrls&&!F.endsWith("/")&&(F+=".html"),F!==f.pathname&&(f.pathname=F,l=F+f.search+f.hash,history.replaceState(null,"",l)),f.hash&&!c){let U=null;try{U=document.getElementById(decodeURIComponent(f.hash).slice(1))}catch(B){console.warn(B)}if(U){Qs(U,f.hash);return}}window.scrollTo(0,c)})}}catch(y){if(!/fetch|Page not found/.test(y.message)&&!/^\/404(\.html|\/)?$/.test(l)&&console.error(y),!a)try{const v=await fetch(ht.value.base+"hashmap.json");window.__VP_HASH_MAP__=await v.json(),await i(l,c,!0);return}catch{}o===h&&(o=null,n.path=Ce?h:Ys(h),n.component=t?Pt(t):null,n.data=xi)}}return Ce&&(window.addEventListener("click",l=>{if(l.target.closest("button"))return;const a=l.target.closest("a");if(a&&!a.closest(".vp-raw")&&(a instanceof SVGElement||!a.download)){const{target:f}=a,{href:h,origin:p,pathname:y,hash:v,search:T}=new URL(a.href instanceof SVGAnimatedString?a.href.animVal:a.href,a.baseURI),F=window.location;!l.ctrlKey&&!l.shiftKey&&!l.altKey&&!l.metaKey&&!f&&p===F.origin&&Ba(y)&&(l.preventDefault(),y===F.pathname&&T===F.search?(v!==F.hash&&(history.pushState(null,"",v),window.dispatchEvent(new Event("hashchange"))),v?Qs(a,v,a.classList.contains("header-anchor")):(Zs(h),window.scrollTo(0,0))):s(h))}},{capture:!0}),window.addEventListener("popstate",async l=>{var c;await i(In(location.href),l.state&&l.state.scrollPosition||0),(c=r.onAfterRouteChanged)==null||c.call(r,location.href)}),window.addEventListener("hashchange",l=>{l.preventDefault()})),r}function Ja(){const e=Tt(Xa);if(!e)throw new Error("useRouter() is called without provider.");return e}function Ri(){return Ja().route}function Qs(e,t,n=!1){let r=null;try{r=e.classList.contains("header-anchor")?e:document.getElementById(decodeURIComponent(t).slice(1))}catch(s){console.warn(s)}if(r){let s=function(){!n||Math.abs(i-window.scrollY)>window.innerHeight?window.scrollTo(0,i):window.scrollTo({left:0,top:i,behavior:"smooth"})};const o=parseInt(window.getComputedStyle(r).paddingTop,10),i=window.scrollY+r.getBoundingClientRect().top-za()+o;requestAnimationFrame(s)}}function Zs(e){Ce&&In(e)!==In(location.href)&&(history.replaceState({scrollPosition:window.scrollY},document.title),history.pushState(null,"",e))}function In(e){const t=new URL(e,Ai);return t.pathname=t.pathname.replace(/(^|\/)index(\.html)?$/,"$1"),ht.value.cleanUrls?t.pathname=t.pathname.replace(/\.html$/,""):!t.pathname.endsWith("/")&&!t.pathname.endsWith(".html")&&(t.pathname+=".html"),t.pathname+t.search+t.hash}const pr=()=>bn.forEach(e=>e()),zu=Wr({name:"VitePressContent",props:{as:{type:[Object,String],default:"div"}},setup(e){const t=Ri(),{site:n}=Wa();return()=>Lr(e.as,n.value.contentProps??{style:{position:"relative"}},[t.component?Lr(t.component,{onVnodeMounted:pr,onVnodeUpdated:pr,onVnodeUnmounted:pr}):"404 Page Not Found"])}}),Xu=Wr({setup(e,{slots:t}){const n=oe(!1);return Ot(()=>{n.value=!0}),()=>n.value&&t.default?t.default():null}});function Yu(){Ce&&window.addEventListener("click",e=>{var n;const t=e.target;if(t.matches(".vp-code-group input")){const r=(n=t.parentElement)==null?void 0:n.parentElement;if(!r)return;const s=Array.from(r.querySelectorAll("input")).indexOf(t);if(s<0)return;const o=r.querySelector(".blocks");if(!o)return;const i=Array.from(o.children).find(a=>a.classList.contains("active"));if(!i)return;const l=o.children[s];if(!l||i===l)return;i.classList.remove("active"),l.classList.add("active");const c=r==null?void 0:r.querySelector(`label[for="${t.id}"]`);c==null||c.scrollIntoView({block:"nearest"})}})}function Ju(){if(Ce){const e=new WeakMap;window.addEventListener("click",t=>{var r;const n=t.target;if(n.matches('div[class*="language-"] > button.copy')){const s=n.parentElement,o=(r=n.nextElementSibling)==null?void 0:r.nextElementSibling;if(!s||!o)return;const i=/language-(shellscript|shell|bash|sh|zsh)/.test(s.className),l=[".vp-copy-ignore",".diff.remove"],c=o.cloneNode(!0);c.querySelectorAll(l.join(",")).forEach(f=>f.remove());let a=c.textContent||"";i&&(a=a.replace(/^ *(\$|>) /gm,"").trim()),Qa(a).then(()=>{n.classList.add("copied"),clearTimeout(e.get(n));const f=setTimeout(()=>{n.classList.remove("copied"),n.blur(),e.delete(n)},2e3);e.set(n,f)})}})}}async function Qa(e){try{return navigator.clipboard.writeText(e)}catch{const t=document.createElement("textarea"),n=document.activeElement;t.value=e,t.setAttribute("readonly",""),t.style.contain="strict",t.style.position="absolute",t.style.left="-9999px",t.style.fontSize="12pt";const r=document.getSelection(),s=r?r.rangeCount>0&&r.getRangeAt(0):null;document.body.appendChild(t),t.select(),t.selectionStart=0,t.selectionEnd=e.length,document.execCommand("copy"),document.body.removeChild(t),s&&(r.removeAllRanges(),r.addRange(s)),n&&n.focus()}}function Qu(e,t){let n=!0,r=[];const s=o=>{if(n){n=!1,o.forEach(l=>{const c=gr(l);for(const a of document.head.children)if(a.isEqualNode(c)){r.push(a);return}});return}const i=o.map(gr);r.forEach((l,c)=>{const a=i.findIndex(f=>f==null?void 0:f.isEqualNode(l??null));a!==-1?delete i[a]:(l==null||l.remove(),delete r[c])}),i.forEach(l=>l&&document.head.appendChild(l)),r=[...r,...i].filter(Boolean)};qn(()=>{const o=e.data,i=t.value,l=o&&o.description,c=o&&o.frontmatter.head||[],a=Ti(i,o);a!==document.title&&(document.title=a);const f=l||i.description;let h=document.querySelector("meta[name=description]");h?h.getAttribute("content")!==f&&h.setAttribute("content",f):gr(["meta",{name:"description",content:f}]),s(Si(i.head,eu(c)))})}function gr([e,t,n]){const r=document.createElement(e);for(const s in t)r.setAttribute(s,t[s]);return n&&(r.innerHTML=n),e==="script"&&!t.async&&(r.async=!1),r}function Za(e){return e[0]==="meta"&&e[1]&&e[1].name==="description"}function eu(e){return e.filter(t=>!Za(t))}const mr=new Set,Oi=()=>document.createElement("link"),tu=e=>{const t=Oi();t.rel="prefetch",t.href=e,document.head.appendChild(t)},nu=e=>{const t=new XMLHttpRequest;t.open("GET",e,t.withCredentials=!0),t.send()};let mn;const ru=Ce&&(mn=Oi())&&mn.relList&&mn.relList.supports&&mn.relList.supports("prefetch")?tu:nu;function Zu(){if(!Ce||!window.IntersectionObserver)return;let e;if((e=navigator.connection)&&(e.saveData||/2g/.test(e.effectiveType)))return;const t=window.requestIdleCallback||setTimeout;let n=null;const r=()=>{n&&n.disconnect(),n=new IntersectionObserver(o=>{o.forEach(i=>{if(i.isIntersecting){const l=i.target;n.unobserve(l);const{pathname:c}=l;if(!mr.has(c)){mr.add(c);const a=Ga(c);a&&ru(a)}}})}),t(()=>{document.querySelectorAll("#app a").forEach(o=>{const{hostname:i,pathname:l}=new URL(o.href instanceof SVGAnimatedString?o.href.animVal:o.href,o.baseURI),c=l.match(/\.\w+$/);c&&c[0]!==".html"||o.target!=="_blank"&&i===location.hostname&&(l!==location.pathname?n.observe(o):mr.add(l))})})};Ot(r);const s=Ri();$e(()=>s.path,r),Xn(()=>{n&&n.disconnect()})}export{sc as $,Xn as A,du as B,ko as C,za as D,uu as E,me as F,gu as G,kn as H,qu as I,se as J,fu as K,Ci as L,Ri as M,Ec as N,Tt as O,$u as P,Hu as Q,Fn as R,Un as S,ui as T,Bu as U,Eu as V,zt as W,pu as X,Mu as Y,ku as Z,Lu as _,ii as a,Au as a0,_u as a1,Su as a2,vu as a3,mu as a4,su as a5,wc as a6,Qu as a7,Xa as a8,Wu as a9,hu as aA,Tu as aB,xu as aC,De as aD,Qn as aE,Fu as aF,Uu as aG,Du as aH,Pu as aI,Ja as aJ,Ze as aK,Uo as aL,Ru as aM,Ku as aN,Ka as aa,zu as ab,Xu as ac,ht as ad,Ou as ae,Gu as af,Ga as ag,Zu as ah,Ju as ai,Yu as aj,Lr as ak,hl as al,iu as am,lu as an,de as ao,Pt as ap,co as aq,Vu as ar,ju as as,Iu as at,nt as au,bu as av,Vn as aw,Jt as ax,Le as ay,Nu as az,ri as b,wu as c,Wr as d,Cu as e,Ba as f,Ys as g,oe as h,Ha as i,Ce as j,re as k,Ot as l,oi as m,$n as n,ti as o,So as p,cu as q,yu as r,au as s,ou as t,Wa as u,$a as v,Rl as w,Ca as x,$e as y,qn as z}; diff --git a/assets/chunks/theme.BX4Y5IZy.js b/assets/chunks/theme.BX4Y5IZy.js new file mode 100644 index 00000000..94ce062b --- /dev/null +++ b/assets/chunks/theme.BX4Y5IZy.js @@ -0,0 +1,7 @@ +import{d as g,o as a,c as l,r as c,n as T,a as H,t as L,b as $,w as v,T as pe,e as f,_ as m,u as Ge,i as Re,f as je,g as _e,h as M,j as W,k as b,l as R,m as d,p as r,q as z,s as D,v as G,x as ce,y as j,z as te,A as fe,B as Ve,C as Ke,D as We,E as F,F as I,G as B,H as Le,I as se,J as _,K as x,L as Se,M as oe,N as Z,O as ne,P as qe,Q as ue,R as Ye,S as Je,U as Me,V as Xe,W as Ze,X as q,Y,Z as Ce,$ as Te,a0 as Qe,a1 as et,a2 as tt,a3 as st,a4 as ot,a5 as nt,a6 as at}from"./framework.B6c1f-8R.js";const rt=g({__name:"VPBadge",props:{text:{},type:{default:"tip"}},setup(s){return(e,t)=>(a(),l("span",{class:T(["VPBadge",e.type])},[c(e.$slots,"default",{},()=>[H(L(e.text),1)])],2))}}),it={key:0,class:"VPBackdrop"},lt=g({__name:"VPBackdrop",props:{show:{type:Boolean}},setup(s){return(e,t)=>(a(),$(pe,{name:"fade"},{default:v(()=>[e.show?(a(),l("div",it)):f("",!0)]),_:1}))}}),ct=m(lt,[["__scopeId","data-v-eab8694c"]]),w=Ge;function ut(s,e){let t,o=!1;return()=>{t&&clearTimeout(t),o?t=setTimeout(s,e):(s(),(o=!0)&&setTimeout(()=>o=!1,e))}}function de(s){return/^\//.test(s)?s:`/${s}`}function me(s){const{pathname:e,search:t,hash:o,protocol:n}=new URL(s,"http://a.com");if(Re(s)||s.startsWith("#")||!n.startsWith("http")||!je(e))return s;const{site:i}=w(),u=e.endsWith("/")||e.endsWith(".html")?s:s.replace(/(?:(^\.+)\/)?.*$/,`$1${e.replace(/(\.md)?$/,i.value.cleanUrls?"":".html")}${t}${o}`);return _e(u)}const ge=M(W?location.hash:"");W&&window.addEventListener("hashchange",()=>{ge.value=location.hash});function J({removeCurrent:s=!0,correspondingLink:e=!1}={}){const{site:t,localeIndex:o,page:n,theme:i}=w(),u=b(()=>{var h,k;return{label:(h=t.value.locales[o.value])==null?void 0:h.label,link:((k=t.value.locales[o.value])==null?void 0:k.link)||(o.value==="root"?"/":`/${o.value}/`)}});return{localeLinks:b(()=>Object.entries(t.value.locales).flatMap(([h,k])=>s&&u.value.label===k.label?[]:{text:k.label,link:dt(k.link||(h==="root"?"/":`/${h}/`),i.value.i18nRouting!==!1&&e,n.value.relativePath.slice(u.value.link.length-1),!t.value.cleanUrls)+ge.value})),currentLang:u}}function dt(s,e,t,o){return e?s.replace(/\/$/,"")+de(t.replace(/(^|\/)index\.md$/,"$1").replace(/\.md$/,o?".html":"")):s}const vt=s=>(z("data-v-20cd492c"),s=s(),D(),s),ht={class:"NotFound"},pt={class:"code"},_t={class:"title"},ft=vt(()=>d("div",{class:"divider"},null,-1)),mt={class:"quote"},gt={class:"action"},$t=["href","aria-label"],kt=g({__name:"NotFound",setup(s){const{site:e,theme:t}=w(),{localeLinks:o}=J({removeCurrent:!1}),n=M("/");return R(()=>{var u;const i=window.location.pathname.replace(e.value.base,"").replace(/(^.*?\/).*$/,"/$1");o.value.length&&(n.value=((u=o.value.find(({link:p})=>p.startsWith(i)))==null?void 0:u.link)||o.value[0].link)}),(i,u)=>{var p,h,k,P,y;return a(),l("div",ht,[d("p",pt,L(((p=r(t).notFound)==null?void 0:p.code)??"404"),1),d("h1",_t,L(((h=r(t).notFound)==null?void 0:h.title)??"PAGE NOT FOUND"),1),ft,d("blockquote",mt,L(((k=r(t).notFound)==null?void 0:k.quote)??"But if you don't change your direction, and if you keep looking, you may end up where you are heading."),1),d("div",gt,[d("a",{class:"link",href:r(_e)(n.value),"aria-label":((P=r(t).notFound)==null?void 0:P.linkLabel)??"go to home"},L(((y=r(t).notFound)==null?void 0:y.linkText)??"Take me home"),9,$t)])])}}}),bt=m(kt,[["__scopeId","data-v-20cd492c"]]);function Ie(s,e){if(Array.isArray(s))return Q(s);if(s==null)return[];e=de(e);const t=Object.keys(s).sort((n,i)=>i.split("/").length-n.split("/").length).find(n=>e.startsWith(de(n))),o=t?s[t]:[];return Array.isArray(o)?Q(o):Q(o.items,o.base)}function yt(s){const e=[];let t=0;for(const o in s){const n=s[o];if(n.items){t=e.push(n);continue}e[t]||e.push({items:[]}),e[t].items.push(n)}return e}function Pt(s){const e=[];function t(o){for(const n of o)n.text&&n.link&&e.push({text:n.text,link:n.link,docFooterText:n.docFooterText}),n.items&&t(n.items)}return t(s),e}function ve(s,e){return Array.isArray(e)?e.some(t=>ve(s,t)):G(s,e.link)?!0:e.items?ve(s,e.items):!1}function Q(s,e){return[...s].map(t=>{const o={...t},n=o.base||e;return n&&o.link&&(o.link=n+o.link),o.items&&(o.items=Q(o.items,n)),o})}function O(){const{frontmatter:s,page:e,theme:t}=w(),o=ce("(min-width: 960px)"),n=M(!1),i=b(()=>{const A=t.value.sidebar,C=e.value.relativePath;return A?Ie(A,C):[]}),u=M(i.value);j(i,(A,C)=>{JSON.stringify(A)!==JSON.stringify(C)&&(u.value=i.value)});const p=b(()=>s.value.sidebar!==!1&&u.value.length>0&&s.value.layout!=="home"),h=b(()=>k?s.value.aside==null?t.value.aside==="left":s.value.aside==="left":!1),k=b(()=>s.value.layout==="home"?!1:s.value.aside!=null?!!s.value.aside:t.value.aside!==!1),P=b(()=>p.value&&o.value),y=b(()=>p.value?yt(u.value):[]);function V(){n.value=!0}function S(){n.value=!1}function N(){n.value?S():V()}return{isOpen:n,sidebar:u,sidebarGroups:y,hasSidebar:p,hasAside:k,leftAside:h,isSidebarEnabled:P,open:V,close:S,toggle:N}}function wt(s,e){let t;te(()=>{t=s.value?document.activeElement:void 0}),R(()=>{window.addEventListener("keyup",o)}),fe(()=>{window.removeEventListener("keyup",o)});function o(n){n.key==="Escape"&&s.value&&(e(),t==null||t.focus())}}function Vt(s){const{page:e}=w(),t=M(!1),o=b(()=>s.value.collapsed!=null),n=b(()=>!!s.value.link),i=M(!1),u=()=>{i.value=G(e.value.relativePath,s.value.link)};j([e,s,ge],u),R(u);const p=b(()=>i.value?!0:s.value.items?ve(e.value.relativePath,s.value.items):!1),h=b(()=>!!(s.value.items&&s.value.items.length));te(()=>{t.value=!!(o.value&&s.value.collapsed)}),Ve(()=>{(i.value||p.value)&&(t.value=!1)});function k(){o.value&&(t.value=!t.value)}return{collapsed:t,collapsible:o,isLink:n,isActiveLink:i,hasActiveLink:p,hasChildren:h,toggle:k}}function Lt(){const{hasSidebar:s}=O(),e=ce("(min-width: 960px)"),t=ce("(min-width: 1280px)");return{isAsideEnabled:b(()=>!t.value&&!e.value?!1:s.value?t.value:e.value)}}const he=[];function Ne(s){return typeof s.outline=="object"&&!Array.isArray(s.outline)&&s.outline.label||s.outlineTitle||"On this page"}function $e(s){const e=[...document.querySelectorAll(".VPDoc :where(h1,h2,h3,h4,h5,h6)")].filter(t=>t.id&&t.hasChildNodes()).map(t=>{const o=Number(t.tagName[1]);return{element:t,title:St(t),link:"#"+t.id,level:o}});return Mt(e,s)}function St(s){let e="";for(const t of s.childNodes)if(t.nodeType===1){if(t.classList.contains("VPBadge")||t.classList.contains("header-anchor")||t.classList.contains("ignore-header"))continue;e+=t.textContent}else t.nodeType===3&&(e+=t.textContent);return e.trim()}function Mt(s,e){if(e===!1)return[];const t=(typeof e=="object"&&!Array.isArray(e)?e.level:e)||2,[o,n]=typeof t=="number"?[t,t]:t==="deep"?[2,6]:t;s=s.filter(u=>u.level>=o&&u.level<=n),he.length=0;for(const{element:u,link:p}of s)he.push({element:u,link:p});const i=[];e:for(let u=0;u=0;h--){const k=s[h];if(k.level{requestAnimationFrame(i),window.addEventListener("scroll",o)}),Ke(()=>{u(location.hash)}),fe(()=>{window.removeEventListener("scroll",o)});function i(){if(!t.value)return;const p=window.scrollY,h=window.innerHeight,k=document.body.offsetHeight,P=Math.abs(p+h-k)<1,y=he.map(({element:S,link:N})=>({link:N,top:Tt(S)})).filter(({top:S})=>!Number.isNaN(S)).sort((S,N)=>S.top-N.top);if(!y.length){u(null);return}if(p<1){u(null);return}if(P){u(y[y.length-1].link);return}let V=null;for(const{link:S,top:N}of y){if(N>p+We()+4)break;V=S}u(V)}function u(p){n&&n.classList.remove("active"),p==null?n=null:n=s.value.querySelector(`a[href="${decodeURIComponent(p)}"]`);const h=n;h?(h.classList.add("active"),e.value.style.top=h.offsetTop+39+"px",e.value.style.opacity="1"):(e.value.style.top="33px",e.value.style.opacity="0")}}function Tt(s){let e=0;for(;s!==document.body;){if(s===null)return NaN;e+=s.offsetTop,s=s.offsetParent}return e}const It=["href","title"],Nt=g({__name:"VPDocOutlineItem",props:{headers:{},root:{type:Boolean}},setup(s){function e({target:t}){const o=t.href.split("#")[1],n=document.getElementById(decodeURIComponent(o));n==null||n.focus({preventScroll:!0})}return(t,o)=>{const n=F("VPDocOutlineItem",!0);return a(),l("ul",{class:T(["VPDocOutlineItem",t.root?"root":"nested"])},[(a(!0),l(I,null,B(t.headers,({children:i,link:u,title:p})=>(a(),l("li",null,[d("a",{class:"outline-link",href:u,onClick:e,title:p},L(p),9,It),i!=null&&i.length?(a(),$(n,{key:0,headers:i},null,8,["headers"])):f("",!0)]))),256))],2)}}}),Ae=m(Nt,[["__scopeId","data-v-12d62b85"]]),At=s=>(z("data-v-4c932924"),s=s(),D(),s),Bt={class:"content"},Ht={class:"outline-title",role:"heading","aria-level":"2"},Et={"aria-labelledby":"doc-outline-aria-label"},zt=At(()=>d("span",{class:"visually-hidden",id:"doc-outline-aria-label"}," Table of Contents for current page ",-1)),Dt=g({__name:"VPDocAsideOutline",setup(s){const{frontmatter:e,theme:t}=w(),o=Le([]);se(()=>{o.value=$e(e.value.outline??t.value.outline)});const n=M(),i=M();return Ct(n,i),(u,p)=>(a(),l("div",{class:T(["VPDocAsideOutline",{"has-outline":o.value.length>0}]),ref_key:"container",ref:n,role:"navigation"},[d("div",Bt,[d("div",{class:"outline-marker",ref_key:"marker",ref:i},null,512),d("div",Ht,L(r(Ne)(r(t))),1),d("nav",Et,[zt,_(Ae,{headers:o.value,root:!0},null,8,["headers"])])])],2))}}),Ft=m(Dt,[["__scopeId","data-v-4c932924"]]),Ot={class:"VPDocAsideCarbonAds"},Ut=g({__name:"VPDocAsideCarbonAds",props:{carbonAds:{}},setup(s){const e=()=>null;return(t,o)=>(a(),l("div",Ot,[_(r(e),{"carbon-ads":t.carbonAds},null,8,["carbon-ads"])]))}}),xt=s=>(z("data-v-8d28afd0"),s=s(),D(),s),Gt={class:"VPDocAside"},Rt=xt(()=>d("div",{class:"spacer"},null,-1)),jt=g({__name:"VPDocAside",setup(s){const{theme:e}=w();return(t,o)=>(a(),l("div",Gt,[c(t.$slots,"aside-top",{},void 0,!0),c(t.$slots,"aside-outline-before",{},void 0,!0),_(Ft),c(t.$slots,"aside-outline-after",{},void 0,!0),Rt,c(t.$slots,"aside-ads-before",{},void 0,!0),r(e).carbonAds?(a(),$(Ut,{key:0,"carbon-ads":r(e).carbonAds},null,8,["carbon-ads"])):f("",!0),c(t.$slots,"aside-ads-after",{},void 0,!0),c(t.$slots,"aside-bottom",{},void 0,!0)]))}}),Kt=m(jt,[["__scopeId","data-v-8d28afd0"]]);function Wt(){const{theme:s,page:e}=w();return b(()=>{const{text:t="Edit this page",pattern:o=""}=s.value.editLink||{};let n;return typeof o=="function"?n=o(e.value):n=o.replace(/:path/g,e.value.filePath),{url:n,text:t}})}function qt(){const{page:s,theme:e,frontmatter:t}=w();return b(()=>{var h,k,P,y,V,S,N,A;const o=Ie(e.value.sidebar,s.value.relativePath),n=Pt(o),i=n.findIndex(C=>G(s.value.relativePath,C.link)),u=((h=e.value.docFooter)==null?void 0:h.prev)===!1&&!t.value.prev||t.value.prev===!1,p=((k=e.value.docFooter)==null?void 0:k.next)===!1&&!t.value.next||t.value.next===!1;return{prev:u?void 0:{text:(typeof t.value.prev=="string"?t.value.prev:typeof t.value.prev=="object"?t.value.prev.text:void 0)??((P=n[i-1])==null?void 0:P.docFooterText)??((y=n[i-1])==null?void 0:y.text),link:(typeof t.value.prev=="object"?t.value.prev.link:void 0)??((V=n[i-1])==null?void 0:V.link)},next:p?void 0:{text:(typeof t.value.next=="string"?t.value.next:typeof t.value.next=="object"?t.value.next.text:void 0)??((S=n[i+1])==null?void 0:S.docFooterText)??((N=n[i+1])==null?void 0:N.text),link:(typeof t.value.next=="object"?t.value.next.link:void 0)??((A=n[i+1])==null?void 0:A.link)}}})}const Yt={},Jt={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},Xt=d("path",{d:"M18,23H4c-1.7,0-3-1.3-3-3V6c0-1.7,1.3-3,3-3h7c0.6,0,1,0.4,1,1s-0.4,1-1,1H4C3.4,5,3,5.4,3,6v14c0,0.6,0.4,1,1,1h14c0.6,0,1-0.4,1-1v-7c0-0.6,0.4-1,1-1s1,0.4,1,1v7C21,21.7,19.7,23,18,23z"},null,-1),Zt=d("path",{d:"M8,17c-0.3,0-0.5-0.1-0.7-0.3C7,16.5,6.9,16.1,7,15.8l1-4c0-0.2,0.1-0.3,0.3-0.5l9.5-9.5c1.2-1.2,3.2-1.2,4.4,0c1.2,1.2,1.2,3.2,0,4.4l-9.5,9.5c-0.1,0.1-0.3,0.2-0.5,0.3l-4,1C8.2,17,8.1,17,8,17zM9.9,12.5l-0.5,2.1l2.1-0.5l9.3-9.3c0.4-0.4,0.4-1.1,0-1.6c-0.4-0.4-1.2-0.4-1.6,0l0,0L9.9,12.5z M18.5,2.5L18.5,2.5L18.5,2.5z"},null,-1),Qt=[Xt,Zt];function es(s,e){return a(),l("svg",Jt,Qt)}const ts=m(Yt,[["render",es]]),E=g({__name:"VPLink",props:{tag:{},href:{},noIcon:{type:Boolean},target:{},rel:{}},setup(s){const e=s,t=b(()=>e.tag??(e.href?"a":"span")),o=b(()=>e.href&&Se.test(e.href));return(n,i)=>(a(),$(x(t.value),{class:T(["VPLink",{link:n.href,"vp-external-link-icon":o.value,"no-icon":n.noIcon}]),href:n.href?r(me)(n.href):void 0,target:n.target??(o.value?"_blank":void 0),rel:n.rel??(o.value?"noreferrer":void 0)},{default:v(()=>[c(n.$slots,"default")]),_:3},8,["class","href","target","rel"]))}}),ss={class:"VPLastUpdated"},os=["datetime"],ns=g({__name:"VPDocFooterLastUpdated",setup(s){const{theme:e,page:t,frontmatter:o,lang:n}=w(),i=b(()=>new Date(o.value.lastUpdated??t.value.lastUpdated)),u=b(()=>i.value.toISOString()),p=M("");return R(()=>{te(()=>{var h,k,P;p.value=new Intl.DateTimeFormat((k=(h=e.value.lastUpdated)==null?void 0:h.formatOptions)!=null&&k.forceLocale?n.value:void 0,((P=e.value.lastUpdated)==null?void 0:P.formatOptions)??{dateStyle:"short",timeStyle:"short"}).format(i.value)})}),(h,k)=>{var P;return a(),l("p",ss,[H(L(((P=r(e).lastUpdated)==null?void 0:P.text)||r(e).lastUpdatedText||"Last updated")+": ",1),d("time",{datetime:u.value},L(p.value),9,os)])}}}),as=m(ns,[["__scopeId","data-v-7a71ca77"]]),rs={key:0,class:"VPDocFooter"},is={key:0,class:"edit-info"},ls={key:0,class:"edit-link"},cs={key:1,class:"last-updated"},us={key:1,class:"prev-next"},ds={class:"pager"},vs=["innerHTML"],hs=["innerHTML"],ps={class:"pager"},_s=["innerHTML"],fs=["innerHTML"],ms=g({__name:"VPDocFooter",setup(s){const{theme:e,page:t,frontmatter:o}=w(),n=Wt(),i=qt(),u=b(()=>e.value.editLink&&o.value.editLink!==!1),p=b(()=>t.value.lastUpdated&&o.value.lastUpdated!==!1),h=b(()=>u.value||p.value||i.value.prev||i.value.next);return(k,P)=>{var y,V,S,N;return h.value?(a(),l("footer",rs,[c(k.$slots,"doc-footer-before",{},void 0,!0),u.value||p.value?(a(),l("div",is,[u.value?(a(),l("div",ls,[_(E,{class:"edit-link-button",href:r(n).url,"no-icon":!0},{default:v(()=>[_(ts,{class:"edit-link-icon","aria-label":"edit icon"}),H(" "+L(r(n).text),1)]),_:1},8,["href"])])):f("",!0),p.value?(a(),l("div",cs,[_(as)])):f("",!0)])):f("",!0),(y=r(i).prev)!=null&&y.link||(V=r(i).next)!=null&&V.link?(a(),l("nav",us,[d("div",ds,[(S=r(i).prev)!=null&&S.link?(a(),$(E,{key:0,class:"pager-link prev",href:r(i).prev.link},{default:v(()=>{var A;return[d("span",{class:"desc",innerHTML:((A=r(e).docFooter)==null?void 0:A.prev)||"Previous page"},null,8,vs),d("span",{class:"title",innerHTML:r(i).prev.text},null,8,hs)]}),_:1},8,["href"])):f("",!0)]),d("div",ps,[(N=r(i).next)!=null&&N.link?(a(),$(E,{key:0,class:"pager-link next",href:r(i).next.link},{default:v(()=>{var A;return[d("span",{class:"desc",innerHTML:((A=r(e).docFooter)==null?void 0:A.next)||"Next page"},null,8,_s),d("span",{class:"title",innerHTML:r(i).next.text},null,8,fs)]}),_:1},8,["href"])):f("",!0)])])):f("",!0)])):f("",!0)}}}),gs=m(ms,[["__scopeId","data-v-3ac27828"]]),$s=s=>(z("data-v-a8702f5f"),s=s(),D(),s),ks={class:"container"},bs=$s(()=>d("div",{class:"aside-curtain"},null,-1)),ys={class:"aside-container"},Ps={class:"aside-content"},ws={class:"content"},Vs={class:"content-container"},Ls={class:"main"},Ss=g({__name:"VPDoc",setup(s){const{theme:e}=w(),t=oe(),{hasSidebar:o,hasAside:n,leftAside:i}=O(),u=b(()=>t.path.replace(/[./]+/g,"_").replace(/_html$/,""));return(p,h)=>{const k=F("Content");return a(),l("div",{class:T(["VPDoc",{"has-sidebar":r(o),"has-aside":r(n)}])},[c(p.$slots,"doc-top",{},void 0,!0),d("div",ks,[r(n)?(a(),l("div",{key:0,class:T(["aside",{"left-aside":r(i)}])},[bs,d("div",ys,[d("div",Ps,[_(Kt,null,{"aside-top":v(()=>[c(p.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":v(()=>[c(p.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":v(()=>[c(p.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":v(()=>[c(p.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":v(()=>[c(p.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":v(()=>[c(p.$slots,"aside-ads-after",{},void 0,!0)]),_:3})])])],2)):f("",!0),d("div",ws,[d("div",Vs,[c(p.$slots,"doc-before",{},void 0,!0),d("main",Ls,[_(k,{class:T(["vp-doc",[u.value,r(e).externalLinkIcon&&"external-link-icon-enabled"]])},null,8,["class"])]),_(gs,null,{"doc-footer-before":v(()=>[c(p.$slots,"doc-footer-before",{},void 0,!0)]),_:3}),c(p.$slots,"doc-after",{},void 0,!0)])])]),c(p.$slots,"doc-bottom",{},void 0,!0)],2)}}}),Ms=m(Ss,[["__scopeId","data-v-a8702f5f"]]),Cs=g({__name:"VPButton",props:{tag:{},size:{default:"medium"},theme:{default:"brand"},text:{},href:{},target:{},rel:{}},setup(s){const e=s,t=b(()=>e.href&&Se.test(e.href)),o=b(()=>e.tag||e.href?"a":"button");return(n,i)=>(a(),$(x(o.value),{class:T(["VPButton",[n.size,n.theme]]),href:n.href?r(me)(n.href):void 0,target:e.target??(t.value?"_blank":void 0),rel:e.rel??(t.value?"noreferrer":void 0)},{default:v(()=>[H(L(n.text),1)]),_:1},8,["class","href","target","rel"]))}}),Ts=m(Cs,[["__scopeId","data-v-63241e40"]]),Is=["src","alt"],Ns=g({inheritAttrs:!1,__name:"VPImage",props:{image:{},alt:{}},setup(s){return(e,t)=>{const o=F("VPImage",!0);return e.image?(a(),l(I,{key:0},[typeof e.image=="string"||"src"in e.image?(a(),l("img",Z({key:0,class:"VPImage"},typeof e.image=="string"?e.$attrs:{...e.image,...e.$attrs},{src:r(_e)(typeof e.image=="string"?e.image:e.image.src),alt:e.alt??(typeof e.image=="string"?"":e.image.alt||"")}),null,16,Is)):(a(),l(I,{key:1},[_(o,Z({class:"dark",image:e.image.dark,alt:e.image.alt},e.$attrs),null,16,["image","alt"]),_(o,Z({class:"light",image:e.image.light,alt:e.image.alt},e.$attrs),null,16,["image","alt"])],64))],64)):f("",!0)}}}),ee=m(Ns,[["__scopeId","data-v-cb1eaea6"]]),As=s=>(z("data-v-b8540496"),s=s(),D(),s),Bs={class:"container"},Hs={class:"main"},Es={key:0,class:"name"},zs=["innerHTML"],Ds=["innerHTML"],Fs=["innerHTML"],Os={key:0,class:"actions"},Us={key:0,class:"image"},xs={class:"image-container"},Gs=As(()=>d("div",{class:"image-bg"},null,-1)),Rs=g({__name:"VPHero",props:{name:{},text:{},tagline:{},image:{},actions:{}},setup(s){const e=ne("hero-image-slot-exists");return(t,o)=>(a(),l("div",{class:T(["VPHero",{"has-image":t.image||r(e)}])},[d("div",Bs,[d("div",Hs,[c(t.$slots,"home-hero-info-before",{},void 0,!0),c(t.$slots,"home-hero-info",{},()=>[t.name?(a(),l("h1",Es,[d("span",{innerHTML:t.name,class:"clip"},null,8,zs)])):f("",!0),t.text?(a(),l("p",{key:1,innerHTML:t.text,class:"text"},null,8,Ds)):f("",!0),t.tagline?(a(),l("p",{key:2,innerHTML:t.tagline,class:"tagline"},null,8,Fs)):f("",!0)],!0),c(t.$slots,"home-hero-info-after",{},void 0,!0),t.actions?(a(),l("div",Os,[(a(!0),l(I,null,B(t.actions,n=>(a(),l("div",{key:n.link,class:"action"},[_(Ts,{tag:"a",size:"medium",theme:n.theme,text:n.text,href:n.link,target:n.target,rel:n.rel},null,8,["theme","text","href","target","rel"])]))),128))])):f("",!0),c(t.$slots,"home-hero-actions-after",{},void 0,!0)]),t.image||r(e)?(a(),l("div",Us,[d("div",xs,[Gs,c(t.$slots,"home-hero-image",{},()=>[t.image?(a(),$(ee,{key:0,class:"image-src",image:t.image},null,8,["image"])):f("",!0)],!0)])])):f("",!0)])],2))}}),js=m(Rs,[["__scopeId","data-v-b8540496"]]),Ks=g({__name:"VPHomeHero",setup(s){const{frontmatter:e}=w();return(t,o)=>r(e).hero?(a(),$(js,{key:0,class:"VPHomeHero",name:r(e).hero.name,text:r(e).hero.text,tagline:r(e).hero.tagline,image:r(e).hero.image,actions:r(e).hero.actions},{"home-hero-info-before":v(()=>[c(t.$slots,"home-hero-info-before")]),"home-hero-info":v(()=>[c(t.$slots,"home-hero-info")]),"home-hero-info-after":v(()=>[c(t.$slots,"home-hero-info-after")]),"home-hero-actions-after":v(()=>[c(t.$slots,"home-hero-actions-after")]),"home-hero-image":v(()=>[c(t.$slots,"home-hero-image")]),_:3},8,["name","text","tagline","image","actions"])):f("",!0)}}),Ws={},qs={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},Ys=d("path",{d:"M19.9,12.4c0.1-0.2,0.1-0.5,0-0.8c-0.1-0.1-0.1-0.2-0.2-0.3l-7-7c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l5.3,5.3H5c-0.6,0-1,0.4-1,1s0.4,1,1,1h11.6l-5.3,5.3c-0.4,0.4-0.4,1,0,1.4c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3l7-7C19.8,12.6,19.9,12.5,19.9,12.4z"},null,-1),Js=[Ys];function Xs(s,e){return a(),l("svg",qs,Js)}const Zs=m(Ws,[["render",Xs]]),Qs={class:"box"},eo={key:0,class:"icon"},to=["innerHTML"],so=["innerHTML"],oo=["innerHTML"],no={key:4,class:"link-text"},ao={class:"link-text-value"},ro=g({__name:"VPFeature",props:{icon:{},title:{},details:{},link:{},linkText:{},rel:{},target:{}},setup(s){return(e,t)=>(a(),$(E,{class:"VPFeature",href:e.link,rel:e.rel,target:e.target,"no-icon":!0,tag:e.link?"a":"div"},{default:v(()=>[d("article",Qs,[typeof e.icon=="object"&&e.icon.wrap?(a(),l("div",eo,[_(ee,{image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])])):typeof e.icon=="object"?(a(),$(ee,{key:1,image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])):e.icon?(a(),l("div",{key:2,class:"icon",innerHTML:e.icon},null,8,to)):f("",!0),d("h2",{class:"title",innerHTML:e.title},null,8,so),e.details?(a(),l("p",{key:3,class:"details",innerHTML:e.details},null,8,oo)):f("",!0),e.linkText?(a(),l("div",no,[d("p",ao,[H(L(e.linkText)+" ",1),_(Zs,{class:"link-text-icon"})])])):f("",!0)])]),_:1},8,["href","rel","target","tag"]))}}),io=m(ro,[["__scopeId","data-v-8870a6fd"]]),lo={key:0,class:"VPFeatures"},co={class:"container"},uo={class:"items"},vo=g({__name:"VPFeatures",props:{features:{}},setup(s){const e=s,t=b(()=>{const o=e.features.length;if(o){if(o===2)return"grid-2";if(o===3)return"grid-3";if(o%3===0)return"grid-6";if(o>3)return"grid-4"}else return});return(o,n)=>o.features?(a(),l("div",lo,[d("div",co,[d("div",uo,[(a(!0),l(I,null,B(o.features,i=>(a(),l("div",{key:i.title,class:T(["item",[t.value]])},[_(io,{icon:i.icon,title:i.title,details:i.details,link:i.link,"link-text":i.linkText,rel:i.rel,target:i.target},null,8,["icon","title","details","link","link-text","rel","target"])],2))),128))])])])):f("",!0)}}),ho=m(vo,[["__scopeId","data-v-36653953"]]),po=g({__name:"VPHomeFeatures",setup(s){const{frontmatter:e}=w();return(t,o)=>r(e).features?(a(),$(ho,{key:0,class:"VPHomeFeatures",features:r(e).features},null,8,["features"])):f("",!0)}}),_o={class:"VPHome"},fo=g({__name:"VPHome",setup(s){return(e,t)=>{const o=F("Content");return a(),l("div",_o,[c(e.$slots,"home-hero-before",{},void 0,!0),_(Ks,null,{"home-hero-info-before":v(()=>[c(e.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":v(()=>[c(e.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":v(()=>[c(e.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":v(()=>[c(e.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":v(()=>[c(e.$slots,"home-hero-image",{},void 0,!0)]),_:3}),c(e.$slots,"home-hero-after",{},void 0,!0),c(e.$slots,"home-features-before",{},void 0,!0),_(po),c(e.$slots,"home-features-after",{},void 0,!0),_(o)])}}}),mo=m(fo,[["__scopeId","data-v-a55404ac"]]),go={},$o={class:"VPPage"};function ko(s,e){const t=F("Content");return a(),l("div",$o,[c(s.$slots,"page-top"),_(t),c(s.$slots,"page-bottom")])}const bo=m(go,[["render",ko]]),yo=g({__name:"VPContent",setup(s){const{page:e,frontmatter:t}=w(),{hasSidebar:o}=O();return(n,i)=>(a(),l("div",{class:T(["VPContent",{"has-sidebar":r(o),"is-home":r(t).layout==="home"}]),id:"VPContent"},[r(e).isNotFound?c(n.$slots,"not-found",{key:0},()=>[_(bt)],!0):r(t).layout==="page"?(a(),$(bo,{key:1},{"page-top":v(()=>[c(n.$slots,"page-top",{},void 0,!0)]),"page-bottom":v(()=>[c(n.$slots,"page-bottom",{},void 0,!0)]),_:3})):r(t).layout==="home"?(a(),$(mo,{key:2},{"home-hero-before":v(()=>[c(n.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info-before":v(()=>[c(n.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":v(()=>[c(n.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":v(()=>[c(n.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":v(()=>[c(n.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":v(()=>[c(n.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":v(()=>[c(n.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":v(()=>[c(n.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":v(()=>[c(n.$slots,"home-features-after",{},void 0,!0)]),_:3})):r(t).layout&&r(t).layout!=="doc"?(a(),$(x(r(t).layout),{key:3})):(a(),$(Ms,{key:4},{"doc-top":v(()=>[c(n.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":v(()=>[c(n.$slots,"doc-bottom",{},void 0,!0)]),"doc-footer-before":v(()=>[c(n.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":v(()=>[c(n.$slots,"doc-before",{},void 0,!0)]),"doc-after":v(()=>[c(n.$slots,"doc-after",{},void 0,!0)]),"aside-top":v(()=>[c(n.$slots,"aside-top",{},void 0,!0)]),"aside-outline-before":v(()=>[c(n.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":v(()=>[c(n.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":v(()=>[c(n.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":v(()=>[c(n.$slots,"aside-ads-after",{},void 0,!0)]),"aside-bottom":v(()=>[c(n.$slots,"aside-bottom",{},void 0,!0)]),_:3}))],2))}}),Po=m(yo,[["__scopeId","data-v-bed13fc1"]]),wo={class:"container"},Vo=["innerHTML"],Lo=["innerHTML"],So=g({__name:"VPFooter",setup(s){const{theme:e,frontmatter:t}=w(),{hasSidebar:o}=O();return(n,i)=>r(e).footer&&r(t).footer!==!1?(a(),l("footer",{key:0,class:T(["VPFooter",{"has-sidebar":r(o)}])},[d("div",wo,[r(e).footer.message?(a(),l("p",{key:0,class:"message",innerHTML:r(e).footer.message},null,8,Vo)):f("",!0),r(e).footer.copyright?(a(),l("p",{key:1,class:"copyright",innerHTML:r(e).footer.copyright},null,8,Lo)):f("",!0)])],2)):f("",!0)}}),Mo=m(So,[["__scopeId","data-v-e6702d68"]]);function Be(){const{theme:s,frontmatter:e}=w(),t=Le([]),o=b(()=>t.value.length>0);return se(()=>{t.value=$e(e.value.outline??s.value.outline)}),{headers:t,hasLocalNav:o}}const Co={},To={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Io=d("path",{d:"M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"},null,-1),No=[Io];function Ao(s,e){return a(),l("svg",To,No)}const He=m(Co,[["render",Ao]]),Bo={class:"header"},Ho={class:"outline"},Eo=g({__name:"VPLocalNavOutlineDropdown",props:{headers:{},navHeight:{}},setup(s){const e=s,{theme:t}=w(),o=M(!1),n=M(0),i=M(),u=M();qe(i,()=>{o.value=!1}),ue("Escape",()=>{o.value=!1}),se(()=>{o.value=!1});function p(){o.value=!o.value,n.value=window.innerHeight+Math.min(window.scrollY-e.navHeight,0)}function h(P){P.target.classList.contains("outline-link")&&(u.value&&(u.value.style.transition="none"),Je(()=>{o.value=!1}))}function k(){o.value=!1,window.scrollTo({top:0,left:0,behavior:"smooth"})}return(P,y)=>(a(),l("div",{class:"VPLocalNavOutlineDropdown",style:Ye({"--vp-vh":n.value+"px"}),ref_key:"main",ref:i},[P.headers.length>0?(a(),l("button",{key:0,onClick:p,class:T({open:o.value})},[H(L(r(Ne)(r(t)))+" ",1),_(He,{class:"icon"})],2)):(a(),l("button",{key:1,onClick:k},L(r(t).returnToTopLabel||"Return to top"),1)),_(pe,{name:"flyout"},{default:v(()=>[o.value?(a(),l("div",{key:0,ref_key:"items",ref:u,class:"items",onClick:h},[d("div",Bo,[d("a",{class:"top-link",href:"#",onClick:k},L(r(t).returnToTopLabel||"Return to top"),1)]),d("div",Ho,[_(Ae,{headers:P.headers},null,8,["headers"])])],512)):f("",!0)]),_:1})],4))}}),zo=m(Eo,[["__scopeId","data-v-6839e2e2"]]),Do={},Fo={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Oo=d("path",{d:"M17,11H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,11,17,11z"},null,-1),Uo=d("path",{d:"M21,7H3C2.4,7,2,6.6,2,6s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,7,21,7z"},null,-1),xo=d("path",{d:"M21,15H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,15,21,15z"},null,-1),Go=d("path",{d:"M17,19H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,19,17,19z"},null,-1),Ro=[Oo,Uo,xo,Go];function jo(s,e){return a(),l("svg",Fo,Ro)}const Ko=m(Do,[["render",jo]]),Wo={class:"container"},qo=["aria-expanded"],Yo={class:"menu-text"},Jo=g({__name:"VPLocalNav",props:{open:{type:Boolean}},emits:["open-menu"],setup(s){const{theme:e,frontmatter:t}=w(),{hasSidebar:o}=O(),{headers:n}=Be(),{y:i}=Me(),u=M(0);R(()=>{u.value=parseInt(getComputedStyle(document.documentElement).getPropertyValue("--vp-nav-height"))}),se(()=>{n.value=$e(t.value.outline??e.value.outline)});const p=b(()=>n.value.length===0),h=b(()=>p.value&&!o.value),k=b(()=>({VPLocalNav:!0,"has-sidebar":o.value,empty:p.value,fixed:h.value}));return(P,y)=>r(t).layout!=="home"&&(!h.value||r(i)>=u.value)?(a(),l("div",{key:0,class:T(k.value)},[d("div",Wo,[r(o)?(a(),l("button",{key:0,class:"menu","aria-expanded":P.open,"aria-controls":"VPSidebarNav",onClick:y[0]||(y[0]=V=>P.$emit("open-menu"))},[_(Ko,{class:"menu-icon"}),d("span",Yo,L(r(e).sidebarMenuLabel||"Menu"),1)],8,qo)):f("",!0),_(zo,{headers:r(n),navHeight:u.value},null,8,["headers","navHeight"])])],2)):f("",!0)}}),Xo=m(Jo,[["__scopeId","data-v-e1a8fe1a"]]);function Zo(){const s=M(!1);function e(){s.value=!0,window.addEventListener("resize",n)}function t(){s.value=!1,window.removeEventListener("resize",n)}function o(){s.value?t():e()}function n(){window.outerWidth>=768&&t()}const i=oe();return j(()=>i.path,t),{isScreenOpen:s,openScreen:e,closeScreen:t,toggleScreen:o}}const Qo={},en={class:"VPSwitch",type:"button",role:"switch"},tn={class:"check"},sn={key:0,class:"icon"};function on(s,e){return a(),l("button",en,[d("span",tn,[s.$slots.default?(a(),l("span",sn,[c(s.$slots,"default",{},void 0,!0)])):f("",!0)])])}const nn=m(Qo,[["render",on],["__scopeId","data-v-9f4da114"]]),an={},rn={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},ln=d("path",{d:"M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"},null,-1),cn=[ln];function un(s,e){return a(),l("svg",rn,cn)}const dn=m(an,[["render",un]]),vn={},hn={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},pn=Xe('',9),_n=[pn];function fn(s,e){return a(),l("svg",hn,_n)}const mn=m(vn,[["render",fn]]),gn=g({__name:"VPSwitchAppearance",setup(s){const{isDark:e,theme:t}=w(),o=ne("toggle-appearance",()=>{e.value=!e.value}),n=b(()=>e.value?t.value.lightModeSwitchTitle||"Switch to light theme":t.value.darkModeSwitchTitle||"Switch to dark theme");return(i,u)=>(a(),$(nn,{title:n.value,class:"VPSwitchAppearance","aria-checked":r(e),onClick:r(o)},{default:v(()=>[_(mn,{class:"sun"}),_(dn,{class:"moon"})]),_:1},8,["title","aria-checked","onClick"]))}}),ke=m(gn,[["__scopeId","data-v-2685bbb5"]]),$n={key:0,class:"VPNavBarAppearance"},kn=g({__name:"VPNavBarAppearance",setup(s){const{site:e}=w();return(t,o)=>r(e).appearance&&r(e).appearance!=="force-dark"?(a(),l("div",$n,[_(ke)])):f("",!0)}}),bn=m(kn,[["__scopeId","data-v-ba4bea8e"]]),be=M();let Ee=!1,le=0;function yn(s){const e=M(!1);if(W){!Ee&&Pn(),le++;const t=j(be,o=>{var n,i,u;o===s.el.value||(n=s.el.value)!=null&&n.contains(o)?(e.value=!0,(i=s.onFocus)==null||i.call(s)):(e.value=!1,(u=s.onBlur)==null||u.call(s))});fe(()=>{t(),le--,le||wn()})}return Ze(e)}function Pn(){document.addEventListener("focusin",ze),Ee=!0,be.value=document.activeElement}function wn(){document.removeEventListener("focusin",ze)}function ze(){be.value=document.activeElement}const Vn={},Ln={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Sn=d("path",{d:"M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"},null,-1),Mn=[Sn];function Cn(s,e){return a(),l("svg",Ln,Mn)}const De=m(Vn,[["render",Cn]]),Tn={},In={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Nn=d("circle",{cx:"12",cy:"12",r:"2"},null,-1),An=d("circle",{cx:"19",cy:"12",r:"2"},null,-1),Bn=d("circle",{cx:"5",cy:"12",r:"2"},null,-1),Hn=[Nn,An,Bn];function En(s,e){return a(),l("svg",In,Hn)}const zn=m(Tn,[["render",En]]),Dn={class:"VPMenuLink"},Fn=g({__name:"VPMenuLink",props:{item:{}},setup(s){const{page:e}=w();return(t,o)=>(a(),l("div",Dn,[_(E,{class:T({active:r(G)(r(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel},{default:v(()=>[H(L(t.item.text),1)]),_:1},8,["class","href","target","rel"])]))}}),ae=m(Fn,[["__scopeId","data-v-4ed5728d"]]),On={class:"VPMenuGroup"},Un={key:0,class:"title"},xn=g({__name:"VPMenuGroup",props:{text:{},items:{}},setup(s){return(e,t)=>(a(),l("div",On,[e.text?(a(),l("p",Un,L(e.text),1)):f("",!0),(a(!0),l(I,null,B(e.items,o=>(a(),l(I,null,["link"in o?(a(),$(ae,{key:0,item:o},null,8,["item"])):f("",!0)],64))),256))]))}}),Gn=m(xn,[["__scopeId","data-v-dcb0eb15"]]),Rn={class:"VPMenu"},jn={key:0,class:"items"},Kn=g({__name:"VPMenu",props:{items:{}},setup(s){return(e,t)=>(a(),l("div",Rn,[e.items?(a(),l("div",jn,[(a(!0),l(I,null,B(e.items,o=>(a(),l(I,{key:o.text},["link"in o?(a(),$(ae,{key:0,item:o},null,8,["item"])):(a(),$(Gn,{key:1,text:o.text,items:o.items},null,8,["text","items"]))],64))),128))])):f("",!0),c(e.$slots,"default",{},void 0,!0)]))}}),Wn=m(Kn,[["__scopeId","data-v-70f7bea4"]]),qn=["aria-expanded","aria-label"],Yn={key:0,class:"text"},Jn=["innerHTML"],Xn={class:"menu"},Zn=g({__name:"VPFlyout",props:{icon:{},button:{},label:{},items:{}},setup(s){const e=M(!1),t=M();yn({el:t,onBlur:o});function o(){e.value=!1}return(n,i)=>(a(),l("div",{class:"VPFlyout",ref_key:"el",ref:t,onMouseenter:i[1]||(i[1]=u=>e.value=!0),onMouseleave:i[2]||(i[2]=u=>e.value=!1)},[d("button",{type:"button",class:"button","aria-haspopup":"true","aria-expanded":e.value,"aria-label":n.label,onClick:i[0]||(i[0]=u=>e.value=!e.value)},[n.button||n.icon?(a(),l("span",Yn,[n.icon?(a(),$(x(n.icon),{key:0,class:"option-icon"})):f("",!0),n.button?(a(),l("span",{key:1,innerHTML:n.button},null,8,Jn)):f("",!0),_(De,{class:"text-icon"})])):(a(),$(zn,{key:1,class:"icon"}))],8,qn),d("div",Xn,[_(Wn,{items:n.items},{default:v(()=>[c(n.$slots,"default",{},void 0,!0)]),_:3},8,["items"])])],544))}}),ye=m(Zn,[["__scopeId","data-v-d96262ab"]]),Qn={discord:'Discord',facebook:'Facebook',github:'GitHub',instagram:'Instagram',linkedin:'LinkedIn',mastodon:'Mastodon',npm:'npm',slack:'Slack',twitter:'Twitter',x:'X',youtube:'YouTube'},ea=["href","aria-label","innerHTML"],ta=g({__name:"VPSocialLink",props:{icon:{},link:{},ariaLabel:{}},setup(s){const e=s,t=b(()=>typeof e.icon=="object"?e.icon.svg:Qn[e.icon]);return(o,n)=>(a(),l("a",{class:"VPSocialLink no-icon",href:o.link,"aria-label":o.ariaLabel??(typeof o.icon=="string"?o.icon:""),target:"_blank",rel:"noopener",innerHTML:t.value},null,8,ea))}}),sa=m(ta,[["__scopeId","data-v-adfe1698"]]),oa={class:"VPSocialLinks"},na=g({__name:"VPSocialLinks",props:{links:{}},setup(s){return(e,t)=>(a(),l("div",oa,[(a(!0),l(I,null,B(e.links,({link:o,icon:n,ariaLabel:i})=>(a(),$(sa,{key:o,icon:n,link:o,ariaLabel:i},null,8,["icon","link","ariaLabel"]))),128))]))}}),Pe=m(na,[["__scopeId","data-v-211dec16"]]),aa={key:0,class:"group translations"},ra={class:"trans-title"},ia={key:1,class:"group"},la={class:"item appearance"},ca={class:"label"},ua={class:"appearance-action"},da={key:2,class:"group"},va={class:"item social-links"},ha=g({__name:"VPNavBarExtra",setup(s){const{site:e,theme:t}=w(),{localeLinks:o,currentLang:n}=J({correspondingLink:!0}),i=b(()=>o.value.length&&n.value.label||e.value.appearance||t.value.socialLinks);return(u,p)=>i.value?(a(),$(ye,{key:0,class:"VPNavBarExtra",label:"extra navigation"},{default:v(()=>[r(o).length&&r(n).label?(a(),l("div",aa,[d("p",ra,L(r(n).label),1),(a(!0),l(I,null,B(r(o),h=>(a(),$(ae,{key:h.link,item:h},null,8,["item"]))),128))])):f("",!0),r(e).appearance&&r(e).appearance!=="force-dark"?(a(),l("div",ia,[d("div",la,[d("p",ca,L(r(t).darkModeSwitchLabel||"Appearance"),1),d("div",ua,[_(ke)])])])):f("",!0),r(t).socialLinks?(a(),l("div",da,[d("div",va,[_(Pe,{class:"social-links-list",links:r(t).socialLinks},null,8,["links"])])])):f("",!0)]),_:1})):f("",!0)}}),pa=m(ha,[["__scopeId","data-v-ee189185"]]),_a=s=>(z("data-v-4146a2ef"),s=s(),D(),s),fa=["aria-expanded"],ma=_a(()=>d("span",{class:"container"},[d("span",{class:"top"}),d("span",{class:"middle"}),d("span",{class:"bottom"})],-1)),ga=[ma],$a=g({__name:"VPNavBarHamburger",props:{active:{type:Boolean}},emits:["click"],setup(s){return(e,t)=>(a(),l("button",{type:"button",class:T(["VPNavBarHamburger",{active:e.active}]),"aria-label":"mobile navigation","aria-expanded":e.active,"aria-controls":"VPNavScreen",onClick:t[0]||(t[0]=o=>e.$emit("click"))},ga,10,fa))}}),ka=m($a,[["__scopeId","data-v-4146a2ef"]]),ba=["innerHTML"],ya=g({__name:"VPNavBarMenuLink",props:{item:{}},setup(s){const{page:e}=w();return(t,o)=>(a(),$(E,{class:T({VPNavBarMenuLink:!0,active:r(G)(r(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel,tabindex:"0"},{default:v(()=>[d("span",{innerHTML:t.item.text},null,8,ba)]),_:1},8,["class","href","target","rel"]))}}),Pa=m(ya,[["__scopeId","data-v-07e86fd5"]]),wa=g({__name:"VPNavBarMenuGroup",props:{item:{}},setup(s){const e=s,{page:t}=w(),o=i=>"link"in i?G(t.value.relativePath,i.link,!!e.item.activeMatch):i.items.some(o),n=b(()=>o(e.item));return(i,u)=>(a(),$(ye,{class:T({VPNavBarMenuGroup:!0,active:r(G)(r(t).relativePath,i.item.activeMatch,!!i.item.activeMatch)||n.value}),button:i.item.text,items:i.item.items},null,8,["class","button","items"]))}}),Va=s=>(z("data-v-0c4c2f33"),s=s(),D(),s),La={key:0,"aria-labelledby":"main-nav-aria-label",class:"VPNavBarMenu"},Sa=Va(()=>d("span",{id:"main-nav-aria-label",class:"visually-hidden"},"Main Navigation",-1)),Ma=g({__name:"VPNavBarMenu",setup(s){const{theme:e}=w();return(t,o)=>r(e).nav?(a(),l("nav",La,[Sa,(a(!0),l(I,null,B(r(e).nav,n=>(a(),l(I,{key:n.text},["link"in n?(a(),$(Pa,{key:0,item:n},null,8,["item"])):(a(),$(wa,{key:1,item:n},null,8,["item"]))],64))),128))])):f("",!0)}}),Ca=m(Ma,[["__scopeId","data-v-0c4c2f33"]]);function Ta(s){const{localeIndex:e,theme:t}=w();function o(n){var N,A,C;const i=n.split("."),u=(N=t.value.search)==null?void 0:N.options,p=u&&typeof u=="object",h=p&&((C=(A=u.locales)==null?void 0:A[e.value])==null?void 0:C.translations)||null,k=p&&u.translations||null;let P=h,y=k,V=s;const S=i.pop();for(const X of i){let U=null;const K=V==null?void 0:V[X];K&&(U=V=K);const re=y==null?void 0:y[X];re&&(U=y=re);const ie=P==null?void 0:P[X];ie&&(U=P=ie),K||(V=U),re||(y=U),ie||(P=U)}return(P==null?void 0:P[S])??(y==null?void 0:y[S])??(V==null?void 0:V[S])??""}return o}const Ia=["aria-label"],Na={class:"DocSearch-Button-Container"},Aa=d("svg",{class:"DocSearch-Search-Icon",width:"20",height:"20",viewBox:"0 0 20 20","aria-label":"search icon"},[d("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none","fill-rule":"evenodd","stroke-linecap":"round","stroke-linejoin":"round"})],-1),Ba={class:"DocSearch-Button-Placeholder"},Ha=d("span",{class:"DocSearch-Button-Keys"},[d("kbd",{class:"DocSearch-Button-Key"}),d("kbd",{class:"DocSearch-Button-Key"},"K")],-1),we=g({__name:"VPNavBarSearchButton",setup(s){const t=Ta({button:{buttonText:"Search",buttonAriaLabel:"Search"}});return(o,n)=>(a(),l("button",{type:"button",class:"DocSearch DocSearch-Button","aria-label":r(t)("button.buttonAriaLabel")},[d("span",Na,[Aa,d("span",Ba,L(r(t)("button.buttonText")),1)]),Ha],8,Ia))}}),Ea={class:"VPNavBarSearch"},za={id:"local-search"},Da={key:1,id:"docsearch"},Fa=g({__name:"VPNavBarSearch",setup(s){const e=q(()=>Y(()=>import("./VPLocalSearchBox.BGpAGtia.js"),__vite__mapDeps([0,1]))),t=()=>null,{theme:o}=w(),n=M(!1),i=M(!1);R(()=>{});function u(){n.value||(n.value=!0,setTimeout(p,16))}function p(){const y=new Event("keydown");y.key="k",y.metaKey=!0,window.dispatchEvent(y),setTimeout(()=>{document.querySelector(".DocSearch-Modal")||p()},16)}function h(y){const V=y.target,S=V.tagName;return V.isContentEditable||S==="INPUT"||S==="SELECT"||S==="TEXTAREA"}const k=M(!1);ue("k",y=>{(y.ctrlKey||y.metaKey)&&(y.preventDefault(),k.value=!0)}),ue("/",y=>{h(y)||(y.preventDefault(),k.value=!0)});const P="local";return(y,V)=>{var S;return a(),l("div",Ea,[r(P)==="local"?(a(),l(I,{key:0},[k.value?(a(),$(r(e),{key:0,onClose:V[0]||(V[0]=N=>k.value=!1)})):f("",!0),d("div",za,[_(we,{onClick:V[1]||(V[1]=N=>k.value=!0)})])],64)):r(P)==="algolia"?(a(),l(I,{key:1},[n.value?(a(),$(r(t),{key:0,algolia:((S=r(o).search)==null?void 0:S.options)??r(o).algolia,onVnodeBeforeMount:V[2]||(V[2]=N=>i.value=!0)},null,8,["algolia"])):f("",!0),i.value?f("",!0):(a(),l("div",Da,[_(we,{onClick:u})]))],64)):f("",!0)])}}}),Oa=g({__name:"VPNavBarSocialLinks",setup(s){const{theme:e}=w();return(t,o)=>r(e).socialLinks?(a(),$(Pe,{key:0,class:"VPNavBarSocialLinks",links:r(e).socialLinks},null,8,["links"])):f("",!0)}}),Ua=m(Oa,[["__scopeId","data-v-7a5f4317"]]),xa=["href","rel","target"],Ga={key:1},Ra={key:2},ja=g({__name:"VPNavBarTitle",setup(s){const{site:e,theme:t}=w(),{hasSidebar:o}=O(),{currentLang:n}=J(),i=b(()=>{var h;return typeof t.value.logoLink=="string"?t.value.logoLink:(h=t.value.logoLink)==null?void 0:h.link}),u=b(()=>{var h;return typeof t.value.logoLink=="string"||(h=t.value.logoLink)==null?void 0:h.rel}),p=b(()=>{var h;return typeof t.value.logoLink=="string"||(h=t.value.logoLink)==null?void 0:h.target});return(h,k)=>(a(),l("div",{class:T(["VPNavBarTitle",{"has-sidebar":r(o)}])},[d("a",{class:"title",href:i.value??r(me)(r(n).link),rel:u.value,target:p.value},[c(h.$slots,"nav-bar-title-before",{},void 0,!0),r(t).logo?(a(),$(ee,{key:0,class:"logo",image:r(t).logo},null,8,["image"])):f("",!0),r(t).siteTitle?(a(),l("span",Ga,L(r(t).siteTitle),1)):r(t).siteTitle===void 0?(a(),l("span",Ra,L(r(e).title),1)):f("",!0),c(h.$slots,"nav-bar-title-after",{},void 0,!0)],8,xa)],2))}}),Ka=m(ja,[["__scopeId","data-v-fb02e02e"]]),Wa={},qa={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Ya=d("path",{d:"M0 0h24v24H0z",fill:"none"},null,-1),Ja=d("path",{d:" M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z ",class:"css-c4d79v"},null,-1),Xa=[Ya,Ja];function Za(s,e){return a(),l("svg",qa,Xa)}const Fe=m(Wa,[["render",Za]]),Qa={class:"items"},er={class:"title"},tr=g({__name:"VPNavBarTranslations",setup(s){const{theme:e}=w(),{localeLinks:t,currentLang:o}=J({correspondingLink:!0});return(n,i)=>r(t).length&&r(o).label?(a(),$(ye,{key:0,class:"VPNavBarTranslations",icon:Fe,label:r(e).langMenuLabel||"Change language"},{default:v(()=>[d("div",Qa,[d("p",er,L(r(o).label),1),(a(!0),l(I,null,B(r(t),u=>(a(),$(ae,{key:u.link,item:u},null,8,["item"]))),128))])]),_:1},8,["label"])):f("",!0)}}),sr=m(tr,[["__scopeId","data-v-505f8924"]]),or=s=>(z("data-v-c292e453"),s=s(),D(),s),nr={class:"wrapper"},ar={class:"container"},rr={class:"title"},ir={class:"content"},lr={class:"content-body"},cr=or(()=>d("div",{class:"divider"},[d("div",{class:"divider-line"})],-1)),ur=g({__name:"VPNavBar",props:{isScreenOpen:{type:Boolean}},emits:["toggle-screen"],setup(s){const{y:e}=Me(),{hasSidebar:t}=O(),{hasLocalNav:o}=Be(),{frontmatter:n}=w(),i=M({});return Ve(()=>{i.value={"has-sidebar":t.value,"has-local-nav":o.value,top:n.value.layout==="home"&&e.value===0}}),(u,p)=>(a(),l("div",{class:T(["VPNavBar",i.value])},[d("div",nr,[d("div",ar,[d("div",rr,[_(Ka,null,{"nav-bar-title-before":v(()=>[c(u.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":v(()=>[c(u.$slots,"nav-bar-title-after",{},void 0,!0)]),_:3})]),d("div",ir,[d("div",lr,[c(u.$slots,"nav-bar-content-before",{},void 0,!0),_(Fa,{class:"search"}),_(Ca,{class:"menu"}),_(sr,{class:"translations"}),_(bn,{class:"appearance"}),_(Ua,{class:"social-links"}),_(pa,{class:"extra"}),c(u.$slots,"nav-bar-content-after",{},void 0,!0),_(ka,{class:"hamburger",active:u.isScreenOpen,onClick:p[0]||(p[0]=h=>u.$emit("toggle-screen"))},null,8,["active"])])])])]),cr],2))}}),dr=m(ur,[["__scopeId","data-v-c292e453"]]),vr={key:0,class:"VPNavScreenAppearance"},hr={class:"text"},pr=g({__name:"VPNavScreenAppearance",setup(s){const{site:e,theme:t}=w();return(o,n)=>r(e).appearance&&r(e).appearance!=="force-dark"?(a(),l("div",vr,[d("p",hr,L(r(t).darkModeSwitchLabel||"Appearance"),1),_(ke)])):f("",!0)}}),_r=m(pr,[["__scopeId","data-v-a7a418c5"]]),fr=g({__name:"VPNavScreenMenuLink",props:{item:{}},setup(s){const e=ne("close-screen");return(t,o)=>(a(),$(E,{class:"VPNavScreenMenuLink",href:t.item.link,target:t.item.target,rel:t.item.rel,onClick:r(e)},{default:v(()=>[H(L(t.item.text),1)]),_:1},8,["href","target","rel","onClick"]))}}),mr=m(fr,[["__scopeId","data-v-defd5a1e"]]),gr={},$r={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},kr=d("path",{d:"M18.9,10.9h-6v-6c0-0.6-0.4-1-1-1s-1,0.4-1,1v6h-6c-0.6,0-1,0.4-1,1s0.4,1,1,1h6v6c0,0.6,0.4,1,1,1s1-0.4,1-1v-6h6c0.6,0,1-0.4,1-1S19.5,10.9,18.9,10.9z"},null,-1),br=[kr];function yr(s,e){return a(),l("svg",$r,br)}const Pr=m(gr,[["render",yr]]),wr=g({__name:"VPNavScreenMenuGroupLink",props:{item:{}},setup(s){const e=ne("close-screen");return(t,o)=>(a(),$(E,{class:"VPNavScreenMenuGroupLink",href:t.item.link,target:t.item.target,rel:t.item.rel,onClick:r(e)},{default:v(()=>[H(L(t.item.text),1)]),_:1},8,["href","target","rel","onClick"]))}}),Oe=m(wr,[["__scopeId","data-v-c6f96b6c"]]),Vr={class:"VPNavScreenMenuGroupSection"},Lr={key:0,class:"title"},Sr=g({__name:"VPNavScreenMenuGroupSection",props:{text:{},items:{}},setup(s){return(e,t)=>(a(),l("div",Vr,[e.text?(a(),l("p",Lr,L(e.text),1)):f("",!0),(a(!0),l(I,null,B(e.items,o=>(a(),$(Oe,{key:o.text,item:o},null,8,["item"]))),128))]))}}),Mr=m(Sr,[["__scopeId","data-v-d9999553"]]),Cr=["aria-controls","aria-expanded"],Tr=["innerHTML"],Ir=["id"],Nr={key:1,class:"group"},Ar=g({__name:"VPNavScreenMenuGroup",props:{text:{},items:{}},setup(s){const e=s,t=M(!1),o=b(()=>`NavScreenGroup-${e.text.replace(" ","-").toLowerCase()}`);function n(){t.value=!t.value}return(i,u)=>(a(),l("div",{class:T(["VPNavScreenMenuGroup",{open:t.value}])},[d("button",{class:"button","aria-controls":o.value,"aria-expanded":t.value,onClick:n},[d("span",{class:"button-text",innerHTML:i.text},null,8,Tr),_(Pr,{class:"button-icon"})],8,Cr),d("div",{id:o.value,class:"items"},[(a(!0),l(I,null,B(i.items,p=>(a(),l(I,{key:p.text},["link"in p?(a(),l("div",{key:p.text,class:"item"},[_(Oe,{item:p},null,8,["item"])])):(a(),l("div",Nr,[_(Mr,{text:p.text,items:p.items},null,8,["text","items"])]))],64))),128))],8,Ir)],2))}}),Br=m(Ar,[["__scopeId","data-v-fae047cc"]]),Hr={key:0,class:"VPNavScreenMenu"},Er=g({__name:"VPNavScreenMenu",setup(s){const{theme:e}=w();return(t,o)=>r(e).nav?(a(),l("nav",Hr,[(a(!0),l(I,null,B(r(e).nav,n=>(a(),l(I,{key:n.text},["link"in n?(a(),$(mr,{key:0,item:n},null,8,["item"])):(a(),$(Br,{key:1,text:n.text||"",items:n.items},null,8,["text","items"]))],64))),128))])):f("",!0)}}),zr=g({__name:"VPNavScreenSocialLinks",setup(s){const{theme:e}=w();return(t,o)=>r(e).socialLinks?(a(),$(Pe,{key:0,class:"VPNavScreenSocialLinks",links:r(e).socialLinks},null,8,["links"])):f("",!0)}}),Dr={class:"list"},Fr=g({__name:"VPNavScreenTranslations",setup(s){const{localeLinks:e,currentLang:t}=J({correspondingLink:!0}),o=M(!1);function n(){o.value=!o.value}return(i,u)=>r(e).length&&r(t).label?(a(),l("div",{key:0,class:T(["VPNavScreenTranslations",{open:o.value}])},[d("button",{class:"title",onClick:n},[_(Fe,{class:"icon lang"}),H(" "+L(r(t).label)+" ",1),_(De,{class:"icon chevron"})]),d("ul",Dr,[(a(!0),l(I,null,B(r(e),p=>(a(),l("li",{key:p.link,class:"item"},[_(E,{class:"link",href:p.link},{default:v(()=>[H(L(p.text),1)]),_:2},1032,["href"])]))),128))])],2)):f("",!0)}}),Or=m(Fr,[["__scopeId","data-v-62d810e0"]]),Ur={class:"container"},xr=g({__name:"VPNavScreen",props:{open:{type:Boolean}},setup(s){const e=M(null),t=Ce(W?document.body:null);return(o,n)=>(a(),$(pe,{name:"fade",onEnter:n[0]||(n[0]=i=>t.value=!0),onAfterLeave:n[1]||(n[1]=i=>t.value=!1)},{default:v(()=>[o.open?(a(),l("div",{key:0,class:"VPNavScreen",ref_key:"screen",ref:e,id:"VPNavScreen"},[d("div",Ur,[c(o.$slots,"nav-screen-content-before",{},void 0,!0),_(Er,{class:"menu"}),_(Or,{class:"translations"}),_(_r,{class:"appearance"}),_(zr,{class:"social-links"}),c(o.$slots,"nav-screen-content-after",{},void 0,!0)])],512)):f("",!0)]),_:3}))}}),Gr=m(xr,[["__scopeId","data-v-223ed9ec"]]),Rr={key:0,class:"VPNav"},jr=g({__name:"VPNav",setup(s){const{isScreenOpen:e,closeScreen:t,toggleScreen:o}=Zo(),{frontmatter:n}=w(),i=b(()=>n.value.navbar!==!1);return Te("close-screen",t),te(()=>{W&&document.documentElement.classList.toggle("hide-nav",!i.value)}),(u,p)=>i.value?(a(),l("header",Rr,[_(dr,{"is-screen-open":r(e),onToggleScreen:r(o)},{"nav-bar-title-before":v(()=>[c(u.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":v(()=>[c(u.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":v(()=>[c(u.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":v(()=>[c(u.$slots,"nav-bar-content-after",{},void 0,!0)]),_:3},8,["is-screen-open","onToggleScreen"]),_(Gr,{open:r(e)},{"nav-screen-content-before":v(()=>[c(u.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":v(()=>[c(u.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3},8,["open"])])):f("",!0)}}),Kr=m(jr,[["__scopeId","data-v-b9dbd140"]]),Wr=s=>(z("data-v-b5e6ce1f"),s=s(),D(),s),qr=["role","tabindex"],Yr=Wr(()=>d("div",{class:"indicator"},null,-1)),Jr={key:1,class:"items"},Xr=g({__name:"VPSidebarItem",props:{item:{},depth:{}},setup(s){const e=s,{collapsed:t,collapsible:o,isLink:n,isActiveLink:i,hasActiveLink:u,hasChildren:p,toggle:h}=Vt(b(()=>e.item)),k=b(()=>p.value?"section":"div"),P=b(()=>n.value?"a":"div"),y=b(()=>p.value?e.depth+2===7?"p":`h${e.depth+2}`:"p"),V=b(()=>n.value?void 0:"button"),S=b(()=>[[`level-${e.depth}`],{collapsible:o.value},{collapsed:t.value},{"is-link":n.value},{"is-active":i.value},{"has-active":u.value}]);function N(C){"key"in C&&C.key!=="Enter"||!e.item.link&&h()}function A(){e.item.link&&h()}return(C,X)=>{const U=F("VPSidebarItem",!0);return a(),$(x(k.value),{class:T(["VPSidebarItem",S.value])},{default:v(()=>[C.item.text?(a(),l("div",Z({key:0,class:"item",role:V.value},et(C.item.items?{click:N,keydown:N}:{},!0),{tabindex:C.item.items&&0}),[Yr,C.item.link?(a(),$(E,{key:0,tag:P.value,class:"link",href:C.item.link,rel:C.item.rel,target:C.item.target},{default:v(()=>[(a(),$(x(y.value),{class:"text",innerHTML:C.item.text},null,8,["innerHTML"]))]),_:1},8,["tag","href","rel","target"])):(a(),$(x(y.value),{key:1,class:"text",innerHTML:C.item.text},null,8,["innerHTML"])),C.item.collapsed!=null?(a(),l("div",{key:2,class:"caret",role:"button","aria-label":"toggle section",onClick:A,onKeydown:Qe(A,["enter"]),tabindex:"0"},[_(He,{class:"caret-icon"})],32)):f("",!0)],16,qr)):f("",!0),C.item.items&&C.item.items.length?(a(),l("div",Jr,[C.depth<5?(a(!0),l(I,{key:0},B(C.item.items,K=>(a(),$(U,{key:K.text,item:K,depth:C.depth+1},null,8,["item","depth"]))),128)):f("",!0)])):f("",!0)]),_:1},8,["class"])}}}),Zr=m(Xr,[["__scopeId","data-v-b5e6ce1f"]]),Ue=s=>(z("data-v-6d56fb3e"),s=s(),D(),s),Qr=Ue(()=>d("div",{class:"curtain"},null,-1)),ei={class:"nav",id:"VPSidebarNav","aria-labelledby":"sidebar-aria-label",tabindex:"-1"},ti=Ue(()=>d("span",{class:"visually-hidden",id:"sidebar-aria-label"}," Sidebar Navigation ",-1)),si=g({__name:"VPSidebar",props:{open:{type:Boolean}},setup(s){const{sidebarGroups:e,hasSidebar:t}=O(),o=s,n=M(null),i=Ce(W?document.body:null);return j([o,n],()=>{var u;o.open?(i.value=!0,(u=n.value)==null||u.focus()):i.value=!1},{immediate:!0,flush:"post"}),(u,p)=>r(t)?(a(),l("aside",{key:0,class:T(["VPSidebar",{open:u.open}]),ref_key:"navEl",ref:n,onClick:p[0]||(p[0]=tt(()=>{},["stop"]))},[Qr,d("nav",ei,[ti,c(u.$slots,"sidebar-nav-before",{},void 0,!0),(a(!0),l(I,null,B(r(e),h=>(a(),l("div",{key:h.text,class:"group"},[_(Zr,{item:h,depth:0},null,8,["item"])]))),128)),c(u.$slots,"sidebar-nav-after",{},void 0,!0)])],2)):f("",!0)}}),oi=m(si,[["__scopeId","data-v-6d56fb3e"]]),ni=g({__name:"VPSkipLink",setup(s){const e=oe(),t=M();j(()=>e.path,()=>t.value.focus());function o({target:n}){const i=document.getElementById(decodeURIComponent(n.hash).slice(1));if(i){const u=()=>{i.removeAttribute("tabindex"),i.removeEventListener("blur",u)};i.setAttribute("tabindex","-1"),i.addEventListener("blur",u),i.focus(),window.scrollTo(0,0)}}return(n,i)=>(a(),l(I,null,[d("span",{ref_key:"backToTop",ref:t,tabindex:"-1"},null,512),d("a",{href:"#VPContent",class:"VPSkipLink visually-hidden",onClick:o}," Skip to content ")],64))}}),ai=m(ni,[["__scopeId","data-v-b55af449"]]),ri=g({__name:"Layout",setup(s){const{isOpen:e,open:t,close:o}=O(),n=oe();j(()=>n.path,o),wt(e,o);const{frontmatter:i}=w(),u=st(),p=b(()=>!!u["home-hero-image"]);return Te("hero-image-slot-exists",p),(h,k)=>{const P=F("Content");return r(i).layout!==!1?(a(),l("div",{key:0,class:T(["Layout",r(i).pageClass])},[c(h.$slots,"layout-top",{},void 0,!0),_(ai),_(ct,{class:"backdrop",show:r(e),onClick:r(o)},null,8,["show","onClick"]),_(Kr,null,{"nav-bar-title-before":v(()=>[c(h.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":v(()=>[c(h.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":v(()=>[c(h.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":v(()=>[c(h.$slots,"nav-bar-content-after",{},void 0,!0)]),"nav-screen-content-before":v(()=>[c(h.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":v(()=>[c(h.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3}),_(Xo,{open:r(e),onOpenMenu:r(t)},null,8,["open","onOpenMenu"]),_(oi,{open:r(e)},{"sidebar-nav-before":v(()=>[c(h.$slots,"sidebar-nav-before",{},void 0,!0)]),"sidebar-nav-after":v(()=>[c(h.$slots,"sidebar-nav-after",{},void 0,!0)]),_:3},8,["open"]),_(Po,null,{"page-top":v(()=>[c(h.$slots,"page-top",{},void 0,!0)]),"page-bottom":v(()=>[c(h.$slots,"page-bottom",{},void 0,!0)]),"not-found":v(()=>[c(h.$slots,"not-found",{},void 0,!0)]),"home-hero-before":v(()=>[c(h.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info-before":v(()=>[c(h.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":v(()=>[c(h.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":v(()=>[c(h.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":v(()=>[c(h.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":v(()=>[c(h.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":v(()=>[c(h.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":v(()=>[c(h.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":v(()=>[c(h.$slots,"home-features-after",{},void 0,!0)]),"doc-footer-before":v(()=>[c(h.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":v(()=>[c(h.$slots,"doc-before",{},void 0,!0)]),"doc-after":v(()=>[c(h.$slots,"doc-after",{},void 0,!0)]),"doc-top":v(()=>[c(h.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":v(()=>[c(h.$slots,"doc-bottom",{},void 0,!0)]),"aside-top":v(()=>[c(h.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":v(()=>[c(h.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":v(()=>[c(h.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":v(()=>[c(h.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":v(()=>[c(h.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":v(()=>[c(h.$slots,"aside-ads-after",{},void 0,!0)]),_:3}),_(Mo),c(h.$slots,"layout-bottom",{},void 0,!0)],2)):(a(),$(P,{key:1}))}}}),ii=m(ri,[["__scopeId","data-v-39c7485e"]]),xe={Layout:ii,enhanceApp:({app:s})=>{s.component("Badge",rt)}},li={class:"sticky-container py-4"},ci=g({__name:"LayoutCustom",setup(s){const{Layout:e}=xe,t=q(()=>Y(()=>import("./ShareFeedback.DipQI5HM.js"),__vite__mapDeps([2,1,3,4]))),o="https://164.92.190.45/feedback/form";return(n,i)=>(a(),$(r(e),null,ot({_:2},[r(o)?{name:"sidebar-nav-before",fn:v(()=>[d("div",li,[_(r(t),{"feedback-url":r(o)},null,8,["feedback-url"])])]),key:"0"}:void 0]),1024))}}),ui=m(ci,[["__scopeId","data-v-12fc2a51"]]),di=q(()=>Y(()=>import("./MermaidRender.B5IXDZbC.js"),__vite__mapDeps([5,3,1]))),vi={components:{Mermaid:di},inheritAttrs:!1};function hi(s,e,t,o,n,i){const u=F("Mermaid"),p=F("ClientOnly");return a(),$(p,null,{default:v(()=>[_(u,nt(at(s.$attrs)),null,16)]),_:1})}const pi=m(vi,[["render",hi]]),fi={...xe,Layout:ui,enhanceApp({app:s}){s.component("MermaidRenderWrap",pi),s.component("CompatibilityMatrixTable",q(()=>Y(()=>import("./CompatibilityMatrixTable.CQKxYpI6.js"),__vite__mapDeps([6,3,1,7,4])))),s.component("CompatibilityMatrixTableIcon",q(async()=>Y(()=>import("./CompatibilityMatrixTableIcon.DMA2bqrA.js"),__vite__mapDeps([7,4,1]))))}};export{fi as R,Ta as c,w as u}; +function __vite__mapDeps(indexes) { + if (!__vite__mapDeps.viteFileDeps) { + __vite__mapDeps.viteFileDeps = ["assets/chunks/VPLocalSearchBox.BGpAGtia.js","assets/chunks/framework.B6c1f-8R.js","assets/chunks/ShareFeedback.DipQI5HM.js","assets/chunks/vue-kakuyaku.C7Ook2cc.js","assets/chunks/IconCheck.DOTyKktD.js","assets/chunks/MermaidRender.B5IXDZbC.js","assets/chunks/CompatibilityMatrixTable.CQKxYpI6.js","assets/chunks/CompatibilityMatrixTableIcon.DMA2bqrA.js"] + } + return indexes.map((i) => __vite__mapDeps.viteFileDeps[i]) +} diff --git a/assets/chunks/vue-kakuyaku.C7Ook2cc.js b/assets/chunks/vue-kakuyaku.C7Ook2cc.js new file mode 100644 index 00000000..84460349 --- /dev/null +++ b/assets/chunks/vue-kakuyaku.C7Ook2cc.js @@ -0,0 +1 @@ +import{k as a,y as s,al as f,am as o,H as i,an as d,ao as p,ap as c,aq as m}from"./framework.B6c1f-8R.js";function x(e,n,l){return s(()=>e.fulfilled,u=>u&&n(u.value),l)}function S(e,n,l){return s(()=>e.rejected,u=>u&&n(u.reason),l)}function y(){let e=null;const n=f({pending:!1,fulfilled:null,rejected:null});function l(t){e=t,n.pending=!0,n.fulfilled=null,n.rejected=null,t.then(r=>{t===e&&(n.pending=!1,n.fulfilled=c({value:r}))}).catch(r=>{t===e&&(n.pending=!1,n.rejected=c({reason:r}))})}function u(){e=null,n.pending=!1,n.fulfilled=n.rejected=null}return{state:n,set:l,clear:u}}function P(e,n){const{state:l,set:u,clear:t}=y(),r=()=>u(e());return n!=null&&n.immediate&&r(),{state:l,run:r,clear:t}}function v(){const e=m()||o();let n=null;const l=i(null);function u(r){t(),e.run(()=>{n=o(),n.run(()=>{l.value={expose:r()}})})}function t(){n&&(n.stop(),n=l.value=null)}return{setup:u,dispose:t,scope:d(l)}}function g(e){const n=typeof e;return e===!0||n==="string"||n==="number"||n==="symbol"}function h(e){return g(e)?e:e.key}function w(e){return typeof e=="object"?e:{key:e}}function b(e){return e==null||e===!1?null:{some:e}}function T(e,n){const l=v(),u=a(()=>{const t=p(e)?e.value:e();return b(t)});return s(()=>{const t=u.value;return t?h(t.some):null},t=>{t?l.setup(()=>{if(t===!0)return{expose:n(!0)};const r=u.value.some;return{expose:n(r),...w(r)}}):l.dispose()},{immediate:!0}),a(()=>{var t;return((t=l.scope.value)==null?void 0:t.expose)??null})}export{T as a,y as b,S as c,P as u,x as w}; diff --git a/assets/documenting_snippets.md.C4z1KoPs.js b/assets/documenting_snippets.md.C4z1KoPs.js new file mode 100644 index 00000000..936ba83d --- /dev/null +++ b/assets/documenting_snippets.md.C4z1KoPs.js @@ -0,0 +1,37 @@ +import{_ as s,c as i,o as e,V as a}from"./chunks/framework.B6c1f-8R.js";const E=JSON.parse('{"title":"Code Snippets","description":"","frontmatter":{},"headers":[],"relativePath":"documenting/snippets.md","filePath":"documenting/snippets.md","lastUpdated":1727242778000}'),t={name:"documenting/snippets.md"},n=a(`

Code Snippets

To make code snippets in the documentation more "real" and robust, it is better to fetch them directly from the source files. The sources are located in other repositories, where they are built, run, and tested.

How it works

Snippet Sources

Snippet sources are defined in snippet_sources.ts. The snippet_sources.ts file is located in the documentation repository and has the following format:

ts
export default [
+  {
+    src: 'https://raw.githubusercontent.com/hyperledger/iroha/main/MAINTAINERS.md',
+    filename: 'iroha-maintainers-at-stable.md',
+  },
+  {
+    src: './src/example_code/lorem.rs',
+  },
+]
  • src defines the source file location and could be either an HTTP(s) URI or a relative file path.
  • filename (optional) explicitly defines the local filename.

Fetching Snippets

Code snippets are fetched from the locations specified in snippet_sources.ts and written into the /src/snippets directory. There are two ways to fetch the snippets:

  • Automatically after dependencies were installed (i.e. pnpm install)
  • Manually by calling pnpm get-snippets

TIP

By default, snippets are deleted and reloaded each time pnpm get-snippets is called. For local development it might be more convenient to enable "lazy" behavior by calling pnpm get-snippets --force false.

Using Snippets in Markdown

Use Code Snippets feature in VitePress to include snippets into documentation:

Input

md
<<<@/snippets/lorem.rs
+
+<<<@/snippets/lorem.rs#ipsum

Output

rs
fn main() {
+    // #region ipsum
+    println!("Lorem ipsum");
+    // #endregion ipsum
+}
rs
println!("Lorem ipsum");

Note that we included only the #ipsum code region, not the entire file. This feature is essential when it comes to including code from real source files into the documentation.

Example

Let's add a code snippet from Iroha JavaScript SDK. For example, this one: /packages/docs-recipes/src/1.client-install.ts.

  1. First, get a permalink to the file. Open the file on GitHub and click Raw button to get the link. For example: https://raw.githubusercontent.com/hyperledger/iroha-javascript/e300886e76c777776efad1e2f5cb245bfb8ed02e/packages/docs-recipes/src/1.client-install.ts

  2. Define the new snippet in the Snippet Sources:

    ts
    export default [
    +  /// ...
    +
    +  {
    +    src: 'https://raw.githubusercontent.com/hyperledger/iroha-javascript/e300886e76c777776efad1e2f5cb245bfb8ed02e/packages/docs-recipes/src/1.client-install.ts',
    +    filename: 'js-sdk-1-client-install.ts',
    +  },
    +]

    TIP

    Since snippet_sources.ts is a TypeScript file, we can use all scripting features in it. Meanwhile, we are trying to keep it as simple as possible, so even the one who doesn't know TypeScript at all could edit it.

    However, we use a bit of scripting. We defined several constants with git revisions from multiple repositories:

    ts
    const IROHA_REV_STABLE = 'c4af68c4f7959b154eb5380aa93c894e2e63fe4e'
    +
    +const IROHA_REV_DEV = '...'
    +
    +const IROHA_JS_REV = '...'

    Then we use them in links to snippet sources in place of git revisions, like this:

    ts
    export default [
    +  // ...
    +
    +  {
    +    src: \`https://raw.githubusercontent.com/hyperledger/iroha/\${IROHA_REV_STABLE}/MAINTAINERS.md\`,
    +    //                                                        ^^^^^^^^^^^^^^^^^^^
    +    filename: 'iroha-maintainers-at-stable.md',
    +  },
    +]

    It helps us to reduce repetitions and keep sources clean.

  3. Include the snippet in any Markdown file in the documentation as follows:

    Input

    md
    <<<@/snippets/js-sdk-1-client-install.ts

    Output

    ts
    import { crypto } from '@iroha2/crypto-target-node'
    +import { setCrypto } from '@iroha2/client'
    +
    +setCrypto(crypto)
`,22),p=[n];function l(h,r,o,c,d,k){return e(),i("div",null,p)}const u=s(t,[["render",l]]);export{E as __pageData,u as default}; diff --git a/assets/documenting_snippets.md.C4z1KoPs.lean.js b/assets/documenting_snippets.md.C4z1KoPs.lean.js new file mode 100644 index 00000000..9e7915a9 --- /dev/null +++ b/assets/documenting_snippets.md.C4z1KoPs.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as e,V as a}from"./chunks/framework.B6c1f-8R.js";const E=JSON.parse('{"title":"Code Snippets","description":"","frontmatter":{},"headers":[],"relativePath":"documenting/snippets.md","filePath":"documenting/snippets.md","lastUpdated":1727242778000}'),t={name:"documenting/snippets.md"},n=a("",22),p=[n];function l(h,r,o,c,d,k){return e(),i("div",null,p)}const u=s(t,[["render",l]]);export{E as __pageData,u as default}; diff --git a/assets/ffi.CTI0y00c.png b/assets/ffi.CTI0y00c.png new file mode 100644 index 00000000..36e9b538 Binary files /dev/null and b/assets/ffi.CTI0y00c.png differ diff --git a/assets/guide_advanced_hot-reload.md.DCdI8k4h.js b/assets/guide_advanced_hot-reload.md.DCdI8k4h.js new file mode 100644 index 00000000..82c6beb0 --- /dev/null +++ b/assets/guide_advanced_hot-reload.md.DCdI8k4h.js @@ -0,0 +1 @@ +import{_ as e,c as i,o as a,V as s}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"How to hot reload Iroha in a Docker container","description":"","frontmatter":{},"headers":[],"relativePath":"guide/advanced/hot-reload.md","filePath":"guide/advanced/hot-reload.md","lastUpdated":1727242778000}'),o={name:"guide/advanced/hot-reload.md"},t=s('

How to hot reload Iroha in a Docker container

Here is the overall procedure for hot reloading Iroha in a Docker container:

  1. Build Iroha on your host OS.

    To avoid issues with dynamic linking, run:

    bash
    $ cargo build --release --target x86_64-unknown-linux-musl --features "vendored"
    An explanation for using `cargo build` with these parameters.

    You may experience an issue with dynamic linking if your host OS has a newer version of glibc compared to the one in the Docker container. The options used in the command above resolve the issue:

    • --target x86_64-unknown-linux-musl forces static linking against musl libc implementation
    • --features "vendored" facilitates static linkage of the openssl library
  2. Enter Docker container. For example:

    bash
    $ docker exec -it iroha-iroha0-1 bash
  3. Copy Iroha to the current directory:

    bash
    $ docker cp root/soramitsu/iroha/target/x86_64-unknown-linux-musl/release/iroha .
  4. (Optional) Make any modifications you need:

  5. Exit docker container and restart it using docker restart.

    Note: If you use the combination of container down and container up, any modifications you made on the previous step will be lost. Use docker restart to preserve changes.

If you skip the optional step (step 4), the state of the blockchain after hot reload will be the same as it was before the Docker container was restarted.

Note that if you get the Kura initialisation failed error message, it might mean one of two things: corruption or binary incompatibility of the stored block. To fix this, remove the blocks/ directory.

Wiping previous blockchain state (recommit genesis)

To recommit a custom genesis block, remove the previously stored blocks before restarting the container:

bash
$ rm blocks/*

The new genesis block will be automatically recommited upon container restart.

Use custom configuration files

To use custom configuration files, such as config.json or genesis.json, copy (or bind mount) them to the config/ subvolume before restarting the Docker container.

The changes will take effect upon container restart.

Use custom environment variables

To use custom environment variables (e.g. IROHA_PUBLIC_KEY), simply modify them before restarting the Docker container. For example:

bash
$ IROHA_PUBLIC_KEY=<new_key> docker restart

The changes will take effect upon container restart.

',16),n=[t];function r(l,c,h,d,p,u){return a(),i("div",null,n)}const m=e(o,[["render",r]]);export{g as __pageData,m as default}; diff --git a/assets/guide_advanced_hot-reload.md.DCdI8k4h.lean.js b/assets/guide_advanced_hot-reload.md.DCdI8k4h.lean.js new file mode 100644 index 00000000..0349baf7 --- /dev/null +++ b/assets/guide_advanced_hot-reload.md.DCdI8k4h.lean.js @@ -0,0 +1 @@ +import{_ as e,c as i,o as a,V as s}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"How to hot reload Iroha in a Docker container","description":"","frontmatter":{},"headers":[],"relativePath":"guide/advanced/hot-reload.md","filePath":"guide/advanced/hot-reload.md","lastUpdated":1727242778000}'),o={name:"guide/advanced/hot-reload.md"},t=s("",16),n=[t];function r(l,c,h,d,p,u){return a(),i("div",null,n)}const m=e(o,[["render",r]]);export{g as __pageData,m as default}; diff --git a/assets/guide_advanced_metrics.md.U5tv47Y-.js b/assets/guide_advanced_metrics.md.U5tv47Y-.js new file mode 100644 index 00000000..6033fbbc --- /dev/null +++ b/assets/guide_advanced_metrics.md.U5tv47Y-.js @@ -0,0 +1,15 @@ +import{_ as s,c as e,o as a,V as i}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Metrics","description":"","frontmatter":{},"headers":[],"relativePath":"guide/advanced/metrics.md","filePath":"guide/advanced/metrics.md","lastUpdated":1727242778000}'),n={name:"guide/advanced/metrics.md"},t=i(`

Metrics

To conveniently and thoroughly monitor the performance of your instance of the Iroha network, we recommend using Prometheus. Prometheus is a program that can monitor your Iroha peer over a separate socket and provide different kinds of performance metrics.

This data can help you find performance bottlenecks and optimise your Iroha configuration.

/metrics Endpoint

See Reference > Torii Endpoints: Metrics.

How to use metrics

Work in Progress.

This topic will be updated as part of the new configuration reference.

The progress on the configuration reference can be tracked in the following GitHub issue:
iroha-2-docs > Issue #392: Tracking issue for Configuration Reference as per RFC.

::: note

For examples, see Sample Configuration Files.

:::

After the above is configured, you can use the IP address set in the "TORII_TELEMETRY_URL" variable to access the metrics data from within a running Iroha instance.

Example:

bash
$ curl http://127.0.0.1:8180/metrics

This returns a result similar to the following:

bash
# HELP blocks_height Total number of blocks in chain
+# TYPE blocks_height gauge
+blocks_height 135543
+# HELP peers_number Total number peers to send transactions and request proposals
+# TYPE peers_number gauge
+peers_number 7
+# HELP number_of_domains Total number of domains in WSV
+# TYPE number_of_domains gauge
+number_of_domains 14
+# HELP total_number_of_transactions Total number of transactions in blockchain
+# TYPE total_number_of_transactions gauge
+total_number_of_transactions 216499
+# HELP number_of_signatures_in_last_block Number of signatures in last block
+# TYPE number_of_signatures_in_last_block gauge
+number_of_signatures_in_last_block 5
`,17),r=[t];function o(p,l,h,c,d,k){return a(),e("div",null,r)}const m=s(n,[["render",o]]);export{g as __pageData,m as default}; diff --git a/assets/guide_advanced_metrics.md.U5tv47Y-.lean.js b/assets/guide_advanced_metrics.md.U5tv47Y-.lean.js new file mode 100644 index 00000000..7b0a85e3 --- /dev/null +++ b/assets/guide_advanced_metrics.md.U5tv47Y-.lean.js @@ -0,0 +1 @@ +import{_ as s,c as e,o as a,V as i}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Metrics","description":"","frontmatter":{},"headers":[],"relativePath":"guide/advanced/metrics.md","filePath":"guide/advanced/metrics.md","lastUpdated":1727242778000}'),n={name:"guide/advanced/metrics.md"},t=i("",17),r=[t];function o(p,l,h,c,d,k){return a(),e("div",null,r)}const m=s(n,[["render",o]]);export{g as __pageData,m as default}; diff --git a/assets/guide_advanced_running-iroha-on-bare-metal.md.B38eu74b.js b/assets/guide_advanced_running-iroha-on-bare-metal.md.B38eu74b.js new file mode 100644 index 00000000..13028b48 --- /dev/null +++ b/assets/guide_advanced_running-iroha-on-bare-metal.md.B38eu74b.js @@ -0,0 +1,126 @@ +import{_ as s,c as i,o as a,V as e}from"./chunks/framework.B6c1f-8R.js";const n="/iroha-2-docs/assets/appendix_running-iroha_cli-output.CtJXTWW9.png",E=JSON.parse('{"title":"Iroha on bare metal","description":"","frontmatter":{},"headers":[],"relativePath":"guide/advanced/running-iroha-on-bare-metal.md","filePath":"guide/advanced/running-iroha-on-bare-metal.md","lastUpdated":1727242778000}'),t={name:"guide/advanced/running-iroha-on-bare-metal.md"},l=e(`

Iroha on bare metal

What we are going to do is replicate the setup that we have in docker compose and run Iroha directly, without going through the intermediary of containers. Running Iroha on bare metal involves manipulating files and/or environment variables.

The file-based approach is the easiest to get right. Using environment variables can offer a better user experience if done right, but is more error-prone, particularly for exotic systems (Windows).

INFO

For this chapter, we assume you have learned about configuration and management in Iroha 2. Here we offer you instructions to run Iroha on bare metal without going into details about various configuration options available.

You can always check sample configuration files for configs/peer/genesis.json and configs/peer/config.json, or refer to peer configuration options for more details.

Prerequisites

First of all, we should note that we have only built the Iroha client so far in this tutorial. We also need to build the peer software to run Iroha on bare metal.

INFO

Building in debug mode retains much more information and optimises the binary to a far lesser extent. As such, we advise you to build Iroha in debug mode for testing: it’s faster and it makes it easier for you to find issues and fix them. However, if you intend to actually deploy Iroha, you should build it in --release mode.

  • To build the peer software in debug mode, run:

    kotlin
    cargo build -p iroha
  • To build the peer software in release mode, run:

    kotlin
    cargo build --bin iroha --release

    The release mode binary takes significantly longer to compile than debug mode, but the result is a smaller and faster binary, suitable for deployment in the actual blockchains.

Setup

Setup: Environment variables

We want to make sure that we have the right configuration.

There are different ways to do this. You can copy the contents of the ~/Git/iroha/configs/peer/ into a new directory, or, alternatively, just run all commands from that directory:

bash
$ cd ~/Git/iroha/configs/peer

The third option is to specify the full path to the configuration file in an environment variable. For simplicity, we shall do the latter:

bash
$ cd ~
+$ export IROHA2_GENESIS_PATH="$(pwd)/Git/iroha/configs/peer/genesis.json"
+$ export IROHA2_CONFIG_PATH="$(pwd)/Git/iroha/configs/peer/config.json"

For extra convenience, you could add the Iroha 2 target directory to your PATH. This means that instead of having to specify the full path to the executable iroha, you can instead type iroha directly into your command line.

bash
$ export PATH="$PATH:$(pwd)/Git/iroha/target/debug"

TIP

Don’t forget to replace debug with release when you’re ready to deploy in the real world.

This way you can run iroha from any directory without having to worry about configuration paths and/or specifying the full path to the Iroha executable.

It is a good idea to make these instructions permanent, which you can do by adding the environment variables to your startup shell.

Save the instructions to the startup shell

On older Linux systems, you copy and paste the instructions (without the cd ~) to ~/.bashrc. On Mac OS X 10.6 and later, as well as some Linux systems, you want to add the same lines to ~/.zshrc.

Copy these instructions to the specified files (replace debug with release when you are ready to deploy):

bash
$ export IROHA2_GENESIS_PATH="$(pwd)/Git/iroha/configs/peer/genesis.json"
+$ export IROHA2_CONFIG_PATH="$(pwd)/Git/iroha/configs/peer/config.json"
+$ export PATH="$PATH:$(pwd)/Git/iroha/target/debug"

TIP

This process is almost universally unreliable and messy, and it is likely that your system is special in that it breaks some of our assumptions.

If the above optional steps didn’t work for you, you can keep working in the ~/Git/iroha/configs/peer/ folder, and run Iroha via ~/Git/iroha/target/debug/iroha.

This makes the command-line a little harder to read, which is why we recommend setting up your environment first.

Note

The tutorial assumes that you’re running either Linux, Mac OS X, or Windows using WSL. It should be possible to run directly on Windows, but that is neither recommended nor easy. If you don’t want to use a Unix-like system, we suggest that you wait until we publish a detailed guide for Windows users.

Setup: Files

This is the recommended method of bringing up an Iroha peer. What we do is:

  1. Create a new directory for the configuration files:

    bash
    $ mkdir -p ~/Git/iroha/deploy
  2. Copy the peer configuration into it:

    bash
    $ cp -vfr ~/Git/iroha/configs/peer/*.json ~/Git/iroha/deploy
  3. Copy the respective Iroha binary into your binary folder:

    bash
    $ sudo cp -vfr ~/Git/iroha/target/debug/iroha /usr/bin/

    which will install Iroha 2 system wide.

TIP

You could also use the iroha peer binary locally by copying it into the same folder. The only difference would be that you’d be calling Iroha like so: ./iroha instead of iroha.

First run of Iroha on bare metal

If you’ve done everything correctly, you can now do

bash
$ iroha

to start your first peer and be greeted with

Untitled

This means that everything is working, but also that we need to do some more work.

You have just started a single peer, which can tolerate exactly 0 faults. Running two peers is also possible, but again, can tolerate 0 faults. You must run at least 4 peers in order to have the capacity to tolerate at least one fault.

In general, if you want to be resistant to f faults, you want to have 3f+1 peers: (4, 7, 10, etc.).

You cannot really start the peers in any way you want, though. When we started our original peer, in its configuration, we specified that it has to trust very specific peers, which have the given private key and listen on a specific address. In order to know how to run them appropriately, take a look at docker-compose.yml:

docker-compose.yaml
yaml
version: '3.8'
+services:
+  iroha0:
+    image: hyperledger/iroha2:dev
+    environment:
+      TORII_P2P_ADDR: iroha0:1337
+      TORII_API_URL: iroha0:8080
+      TORII_TELEMETRY_URL: iroha0:8180
+      IROHA_PUBLIC_KEY: 'ed01201c61faf8fe94e253b93114240394f79a607b7fa55f9e5a41ebec74b88055768b'
+      IROHA_PRIVATE_KEY:
+        '{"digest_function": "ed25519", "payload":
+        "282ed9f3cf92811c3818dbc4ae594ed59dc1a2f78e4241e31924e101d6b1fb831c61faf8fe94e253b93114240394f79a607b7fa55f9e5a41ebec74b88055768b"}'
+      SUMERAGI_TRUSTED_PEERS:
+        '[{"address":"iroha0:1337", "public_key":
+        "ed01201c61faf8fe94e253b93114240394f79a607b7fa55f9e5a41ebec74b88055768b"},
+        {"address":"iroha1:1338", "public_key":
+        "ed0120cc25624d62896d3a0bfd8940f928dc2abf27cc57cefeb442aa96d9081aae58a1"},
+        {"address": "iroha2:1339", "public_key":
+        "ed0120faca9e8aa83225cb4d16d67f27dd4f93fc30ffa11adc1f5c88fd5495ecc91020"},
+        {"address": "iroha3:1340", "public_key":
+        "ed01208e351a70b6a603ed285d666b8d689b680865913ba03ce29fb7d13a166c4e7f1f"}]'
+      IROHA_GENESIS_ACCOUNT_PUBLIC_KEY: 'ed01203f4e3e98571b55514edc5ccf7e53ca7509d89b2868e62921180a6f57c2f4e255'
+      IROHA_GENESIS_ACCOUNT_PRIVATE_KEY:
+        '{ "digest_function": "ed25519", "payload":
+        "038ae16b219da35aa036335ed0a43c28a2cc737150112c78a7b8034b9d99c9023f4e3e98571b55514edc5ccf7e53ca7509d89b2868e62921180a6f57c2f4e255"
+        }'
+    ports:
+      - '1337:1337'
+      - '8080:8080'
+      - '8180:8180'
+    volumes:
+      - './configs/peer:/config'
+    init: true
+    command: iroha --submit-genesis
+
+  iroha1:
+    image: hyperledger/iroha2:dev
+    environment:
+      TORII_P2P_ADDR: iroha1:1338
+      TORII_API_URL: iroha1:8081
+      TORII_TELEMETRY_URL: iroha1:8181
+      IROHA_PUBLIC_KEY: 'ed0120cc25624d62896d3a0bfd8940f928dc2abf27cc57cefeb442aa96d9081aae58a1'
+      IROHA_PRIVATE_KEY:
+        '{"digest_function": "ed25519", "payload":
+        "3bac34cda9e3763fa069c1198312d1ec73b53023b8180c822ac355435edc4a24cc25624d62896d3a0bfd8940f928dc2abf27cc57cefeb442aa96d9081aae58a1"}'
+      SUMERAGI_TRUSTED_PEERS:
+        '[{"address":"iroha0:1337", "public_key":
+        "ed01201c61faf8fe94e253b93114240394f79a607b7fa55f9e5a41ebec74b88055768b"},
+        {"address":"iroha1:1338", "public_key":
+        "ed0120cc25624d62896d3a0bfd8940f928dc2abf27cc57cefeb442aa96d9081aae58a1"},
+        {"address": "iroha2:1339", "public_key":
+        "ed0120faca9e8aa83225cb4d16d67f27dd4f93fc30ffa11adc1f5c88fd5495ecc91020"},
+        {"address": "iroha3:1340", "public_key":
+        "ed01208e351a70b6a603ed285d666b8d689b680865913ba03ce29fb7d13a166c4e7f1f"}]'
+      IROHA_GENESIS_ACCOUNT_PUBLIC_KEY: 'ed01203f4e3e98571b55514edc5ccf7e53ca7509d89b2868e62921180a6f57c2f4e255'
+    ports:
+      - '1338:1338'
+      - '8081:8081'
+      - '8181:8181'
+    volumes:
+      - './configs/peer:/config'
+    init: true
+
+  iroha2:
+    image: hyperledger/iroha2:dev
+    environment:
+      TORII_P2P_ADDR: iroha2:1339
+      TORII_API_URL: iroha2:8082
+      TORII_TELEMETRY_URL: iroha2:8182
+      IROHA_PUBLIC_KEY: 'ed0120faca9e8aa83225cb4d16d67f27dd4f93fc30ffa11adc1f5c88fd5495ecc91020'
+      IROHA_PRIVATE_KEY:
+        '{"digest_function": "ed25519", "payload":
+        "1261a436d36779223d7d6cf20e8b644510e488e6a50bafd77a7485264d27197dfaca9e8aa83225cb4d16d67f27dd4f93fc30ffa11adc1f5c88fd5495ecc91020"}'
+      SUMERAGI_TRUSTED_PEERS:
+        '[{"address":"iroha0:1337", "public_key":
+        "ed01201c61faf8fe94e253b93114240394f79a607b7fa55f9e5a41ebec74b88055768b"},
+        {"address":"iroha1:1338", "public_key":
+        "ed0120cc25624d62896d3a0bfd8940f928dc2abf27cc57cefeb442aa96d9081aae58a1"},
+        {"address": "iroha2:1339", "public_key":
+        "ed0120faca9e8aa83225cb4d16d67f27dd4f93fc30ffa11adc1f5c88fd5495ecc91020"},
+        {"address": "iroha3:1340", "public_key":
+        "ed01208e351a70b6a603ed285d666b8d689b680865913ba03ce29fb7d13a166c4e7f1f"}]'
+      IROHA_GENESIS_ACCOUNT_PUBLIC_KEY: 'ed01203f4e3e98571b55514edc5ccf7e53ca7509d89b2868e62921180a6f57c2f4e255'
+    ports:
+      - '1339:1339'
+      - '8082:8082'
+      - '8182:8182'
+    volumes:
+      - './configs/peer:/config'
+    init: true
+
+  iroha3:
+    image: hyperledger/iroha2:dev
+    environment:
+      TORII_P2P_ADDR: iroha3:1340
+      TORII_API_URL: iroha3:8083
+      TORII_TELEMETRY_URL: iroha3:8183
+      IROHA_PUBLIC_KEY: 'ed01208e351a70b6a603ed285d666b8d689b680865913ba03ce29fb7d13a166c4e7f1f'
+      IROHA_PRIVATE_KEY:
+        '{"digest_function": "ed25519", "payload":
+        "a70dab95c7482eb9f159111b65947e482108cfe67df877bd8d3b9441a781c7c98e351a70b6a603ed285d666b8d689b680865913ba03ce29fb7d13a166c4e7f1f"}'
+      SUMERAGI_TRUSTED_PEERS:
+        '[{"address":"iroha0:1337", "public_key":
+        "ed01201c61faf8fe94e253b93114240394f79a607b7fa55f9e5a41ebec74b88055768b"},
+        {"address":"iroha1:1338", "public_key":
+        "ed0120cc25624d62896d3a0bfd8940f928dc2abf27cc57cefeb442aa96d9081aae58a1"},
+        {"address": "iroha2:1339", "public_key":
+        "ed0120faca9e8aa83225cb4d16d67f27dd4f93fc30ffa11adc1f5c88fd5495ecc91020"},
+        {"address": "iroha3:1340", "public_key":
+        "ed01208e351a70b6a603ed285d666b8d689b680865913ba03ce29fb7d13a166c4e7f1f"}]'
+      IROHA_GENESIS_ACCOUNT_PUBLIC_KEY: 'ed01203f4e3e98571b55514edc5ccf7e53ca7509d89b2868e62921180a6f57c2f4e255'
+    ports:
+      - '1340:1340'
+      - '8083:8083'
+      - '8183:8183'
+    volumes:
+      - './configs/peer:/config'
+    init: true

For every peer, the environment section is a set of things that you should put in front of the iroha command, replacing colons with equals signs. All the socket addresses are also given internal to the docker network, so we should replace them with [localhost](http://localhost), which is 127.0.0.1 on most machines.

TIP

Each Iroha instance is going to listen on three ports: the Peer-to-peer communications channel (133X), the API url, where most client requests are posted (808X), and finally, a telemetry endpoint 818X. All three ports need to be adjusted so there are no collisions. See the docker-compose.yml for an example, and adjust as needed.

Deploy a minimal BFT network

Both of the following approaches could be messy and error-prone, which is why the Launch Iroha 2 tutorial suggests using the docker compose command. However, this brings you closer to the experience of actually maintaining a functional Iroha peer.

Using Environment Variables

To run the First peer, we need to write

bash
$ TORII_P2P_ADDR="127.0.0.1:1337"
+$ TORII_API_URL="127.0.0.1:8080"
+$ TORII_STATUS_URL="127.0.0.1:8180"
+$ IROHA_PUBLIC_KEY="ed01207233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0" IROHA_PRIVATE_KEY='{"digest_function": "ed25519", "payload": "9ac47abf59b356e0bd7dcbbbb4dec080e302156a48ca907e47cb6aea1d32719e7233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0"}'
+$ iroha --submit

and three other similar lines of bash code for the remaining deployments.

TIP

To copy and paste into the terminal on Linux systems, you should remember that Control + Shift + V is the appropriate paste shortcut.

Also note that we asked this peer to --submit or --submit-genesis. This means that in the initial network topology, this peer is the leader. At least one peer (usually the first) needs to be the leader in the initial topology.

Now you should do the same for the other four peers. Be mindful not to mix up which address goes where, replace irohaX with 127.0.0.1 in the addresses, and make sure that they correspond to the right public key.

Using Files

Our first peer can run off of the original configuration file. What we should do is create three more similar files and move them to three different folders e.g. peer1, peer2.

What you need to do is change the TORII:P2P_ADDR, TORII:API_URLTORII:STATUS_URL and the PUBLIC_KEY configuration options to align with their docker-compose.yml counterparts.

Be mindful not to mix up which address goes where, replace irohaX with 127.0.0.1 in the addresses, and make sure that they correspond to the right public key.

Then, in each of the new folders (with the exception of peer0) run:

bash
$ iroha

In the first folder peer0 you should run:

bash
$ iroha --submit-genesis

We effectively asked this peer to --submit or --submit-genesis in the initial, or bootstrap, network. This means that in the initial network topology, this peer is the leader.

Note

Only the leader of the genesis network needs to have access to configs/peer/genesis.json. Having the same genesis in the initial folders of the other peers could be useful, since future versions of iroha will also sanity-check the genesis blocks.

If all went well, you should be greeted with nice logs on each of the nodes, and the nodes should commit the blocks to the blocks/ directory.

Real-world deployment

Suppose now, that you have done all of the tinkering and want to deploy Iroha in the real world.

  1. Build Iroha in release mode:

    bash
    $ cargo build --release
  2. Generate a key pair for your peer and take note of that key:

    bash
    $ cargo run --bin iroha_crypto_cli
  3. Register your peer to a network, and make sure to add at least four of the peers on that network to the TRUSTED_PEERS array in your configuration file.

  4. Determine the web socket that the other peers will use to connect to you. Make sure that the port is open and use that address (P2P_ADDR) in your configs/peer/config.json file.

  5. After you have finished editing the configuration file, deploy Iroha by running

    bash
    $ ~/Git/iroha/target/release/iroha

Note

There is no need to pass the --submit flag unless you are starting the initial peer on the network.

`,63),h=[l];function p(o,d,r,k,c,u){return a(),i("div",null,h)}const y=s(t,[["render",p]]);export{E as __pageData,y as default}; diff --git a/assets/guide_advanced_running-iroha-on-bare-metal.md.B38eu74b.lean.js b/assets/guide_advanced_running-iroha-on-bare-metal.md.B38eu74b.lean.js new file mode 100644 index 00000000..e9832789 --- /dev/null +++ b/assets/guide_advanced_running-iroha-on-bare-metal.md.B38eu74b.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,V as e}from"./chunks/framework.B6c1f-8R.js";const n="/iroha-2-docs/assets/appendix_running-iroha_cli-output.CtJXTWW9.png",E=JSON.parse('{"title":"Iroha on bare metal","description":"","frontmatter":{},"headers":[],"relativePath":"guide/advanced/running-iroha-on-bare-metal.md","filePath":"guide/advanced/running-iroha-on-bare-metal.md","lastUpdated":1727242778000}'),t={name:"guide/advanced/running-iroha-on-bare-metal.md"},l=e("",63),h=[l];function p(o,d,r,k,c,u){return a(),i("div",null,h)}const y=s(t,[["render",p]]);export{E as __pageData,y as default}; diff --git a/assets/guide_blockchain_accounts.md.BXCA0c6W.js b/assets/guide_blockchain_accounts.md.BXCA0c6W.js new file mode 100644 index 00000000..08adc4f9 --- /dev/null +++ b/assets/guide_blockchain_accounts.md.BXCA0c6W.js @@ -0,0 +1 @@ +import{_ as t,c as a,o as c,m as e,a as o}from"./chunks/framework.B6c1f-8R.js";const k=JSON.parse('{"title":"Accounts","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/accounts.md","filePath":"guide/blockchain/accounts.md","lastUpdated":1727242778000}'),s={name:"guide/blockchain/accounts.md"},n=e("h1",{id:"accounts",tabindex:"-1"},[o("Accounts "),e("a",{class:"header-anchor",href:"#accounts","aria-label":'Permalink to "Accounts"'},"​")],-1),r=e("p",null,"TBD",-1),d=[n,r];function i(l,u,_,h,p,m){return c(),a("div",null,d)}const b=t(s,[["render",i]]);export{k as __pageData,b as default}; diff --git a/assets/guide_blockchain_accounts.md.BXCA0c6W.lean.js b/assets/guide_blockchain_accounts.md.BXCA0c6W.lean.js new file mode 100644 index 00000000..08adc4f9 --- /dev/null +++ b/assets/guide_blockchain_accounts.md.BXCA0c6W.lean.js @@ -0,0 +1 @@ +import{_ as t,c as a,o as c,m as e,a as o}from"./chunks/framework.B6c1f-8R.js";const k=JSON.parse('{"title":"Accounts","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/accounts.md","filePath":"guide/blockchain/accounts.md","lastUpdated":1727242778000}'),s={name:"guide/blockchain/accounts.md"},n=e("h1",{id:"accounts",tabindex:"-1"},[o("Accounts "),e("a",{class:"header-anchor",href:"#accounts","aria-label":'Permalink to "Accounts"'},"​")],-1),r=e("p",null,"TBD",-1),d=[n,r];function i(l,u,_,h,p,m){return c(),a("div",null,d)}const b=t(s,[["render",i]]);export{k as __pageData,b as default}; diff --git a/assets/guide_blockchain_assets.md.C7z8RvOt.js b/assets/guide_blockchain_assets.md.C7z8RvOt.js new file mode 100644 index 00000000..caa2f48e --- /dev/null +++ b/assets/guide_blockchain_assets.md.C7z8RvOt.js @@ -0,0 +1 @@ +import{_ as s,E as a,c as i,J as n,V as e,o as r}from"./chunks/framework.B6c1f-8R.js";const _=JSON.parse('{"title":"Assets","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/assets.md","filePath":"guide/blockchain/assets.md","lastUpdated":1727242778000}'),o={name:"guide/blockchain/assets.md"},d=e('

Assets

Iroha has been built with few underlying assumptions about what the assets need to be.

The assets can be fungible (every £1 is exactly the same as every other £1) or non-fungible (a £1 bill signed by the Queen of Hearts is not the same as a £1 bill signed by the King of Spades).

The assets can also be mintable (you can make more of them) and non-mintable (you can only specify their initial quantity in the genesis block).

Value Types

Additionally, the assets have different underlying value types. Specifically, we have AssetValueType.Quantity, which is effectively an unsigned 32-bit integer, a BigQuantity, which is an unsigned 128-bit integer, and Fixed, which is a positive (though signed) 64-bit fixed-precision number with nine significant digits after the decimal point. All three types can be registered as either mintable or non-mintable.

There is also the Store asset type, which is used for storing key-values in object's metadata. We talk in detail about Store asset in the chapter related to metadata.

Asset Structure

',8),c=e('

Instructions

Assets can be registered, minted or burned, and transferred.

Refer to one of the language-specific guides to walk you through the process of registering and minting assets in a blockchain:

',4);function l(h,u,A,g,f,m){const t=a("MermaidRenderWrap");return r(),i("div",null,[d,n(t,{id:"mermaid_a3d76a1e8c22e2a4fec3e81161936e15807e50db5c7561e99c8404dda107b2ce13905a63e504fe8025fbd017689351a498e9e84078c427fce5506985540c3a9e",text:"classDiagram%0A%0Aclass%20Asset%0Aclass%20AssetDefinition%0A%0Aclass%20Id%20%7B%0A%20%20definition_id%0A%20%20account_id%0A%7D%0A%0Aclass%20Mintable%20%7B%0A%20%20%3C%3Cenumeration%3E%3E%0A%20%20Infinitely%0A%20%20Once%0A%20%20Not%0A%7D%0A%0Aclass%20AssetValue%20%7B%0A%20%20%3C%3Cenumeration%3E%3E%0A%20%20Quantity%0A%20%20BigQuantity%0A%20%20Fixed%0A%20%20Store%0A%7D%0A%0AAsset%20--%20AssetDefinition%0AAsset%20--%20Id%0AAssetDefinition%20--%20Mintable%0AAssetDefinition%20--%20AssetValue%20%0AAssetDefinition%20--%20Id%0A%0AAsset%20%3A%20id%20%7BId%7D%0AAsset%20%3A%20value%0A%0AAssetDefinition%20%3A%20id%20%7BId%7D%0AAssetDefinition%20%3A%20value_type%20%7BAssetValueType%7D%0AAssetDefinition%20%3A%20mintable%20%7BMintable%7D%0AAssetDefinition%20%3A%20metadata"}),c])}const b=s(o,[["render",l]]);export{_ as __pageData,b as default}; diff --git a/assets/guide_blockchain_assets.md.C7z8RvOt.lean.js b/assets/guide_blockchain_assets.md.C7z8RvOt.lean.js new file mode 100644 index 00000000..86638227 --- /dev/null +++ b/assets/guide_blockchain_assets.md.C7z8RvOt.lean.js @@ -0,0 +1 @@ +import{_ as s,E as a,c as i,J as n,V as e,o as r}from"./chunks/framework.B6c1f-8R.js";const _=JSON.parse('{"title":"Assets","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/assets.md","filePath":"guide/blockchain/assets.md","lastUpdated":1727242778000}'),o={name:"guide/blockchain/assets.md"},d=e("",8),c=e("",4);function l(h,u,A,g,f,m){const t=a("MermaidRenderWrap");return r(),i("div",null,[d,n(t,{id:"mermaid_a3d76a1e8c22e2a4fec3e81161936e15807e50db5c7561e99c8404dda107b2ce13905a63e504fe8025fbd017689351a498e9e84078c427fce5506985540c3a9e",text:"classDiagram%0A%0Aclass%20Asset%0Aclass%20AssetDefinition%0A%0Aclass%20Id%20%7B%0A%20%20definition_id%0A%20%20account_id%0A%7D%0A%0Aclass%20Mintable%20%7B%0A%20%20%3C%3Cenumeration%3E%3E%0A%20%20Infinitely%0A%20%20Once%0A%20%20Not%0A%7D%0A%0Aclass%20AssetValue%20%7B%0A%20%20%3C%3Cenumeration%3E%3E%0A%20%20Quantity%0A%20%20BigQuantity%0A%20%20Fixed%0A%20%20Store%0A%7D%0A%0AAsset%20--%20AssetDefinition%0AAsset%20--%20Id%0AAssetDefinition%20--%20Mintable%0AAssetDefinition%20--%20AssetValue%20%0AAssetDefinition%20--%20Id%0A%0AAsset%20%3A%20id%20%7BId%7D%0AAsset%20%3A%20value%0A%0AAssetDefinition%20%3A%20id%20%7BId%7D%0AAssetDefinition%20%3A%20value_type%20%7BAssetValueType%7D%0AAssetDefinition%20%3A%20mintable%20%7BMintable%7D%0AAssetDefinition%20%3A%20metadata"}),c])}const b=s(o,[["render",l]]);export{_ as __pageData,b as default}; diff --git a/assets/guide_blockchain_consensus.md.C3NI_nji.js b/assets/guide_blockchain_consensus.md.C3NI_nji.js new file mode 100644 index 00000000..23ec75d3 --- /dev/null +++ b/assets/guide_blockchain_consensus.md.C3NI_nji.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as s,V as o}from"./chunks/framework.B6c1f-8R.js";const m=JSON.parse('{"title":"Consensus","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/consensus.md","filePath":"guide/blockchain/consensus.md","lastUpdated":1727242778000}'),a={name:"guide/blockchain/consensus.md"},n=o('

Consensus

Each time you send a transaction to Iroha, it gets put into a queue. When it's time to produce a new block, the queue is emptied, and the consensus process begins. This process is equal parts common sense and black magic[1].

The mundane aspect is that a special set of peers needs to take the transaction queue and reproduce the same world state. If the world state cannot be reproduced for some reason or another, none of the transactions get committed to a block.

The consensus starts over from scratch by choosing a different special set of peers. This is where the black magic comes in. There is a number of things that are fine-tuned: the number of peers in the voting process, the way in which subsequent voting peers are chosen, and the way in which the peers communicate that consensus has failed. Because this changes the view of the world, the process is called a view change. The exact reason for why the view was changed is encoded in the view change proof, but decoding that information is an advanced topic that we won't cover here.

The reasoning behind this algorithm is simple: if someone had some evil peers and connected them to the existing network, if they tried to fake data, some good™ peers would not get the same (evil™) world state. If that's the case, the evil™ peers would not be allowed to participate in consensus, and you would eventually produce a block using only good™ peers.

As a natural consequence, if any changes to the world state are made without the use of ISI, the good™ peers cannot know of them. They won't be able to reproduce the hash of the world state, and thus consensus will fail. The same thing happens if the peers have different instructions.


  1. For prospective wizards, the Iroha 2 Whitepaper is a good start. ↩︎

',8),i=[n];function r(c,h,d,p,l,u){return s(),t("div",null,i)}const g=e(a,[["render",r]]);export{m as __pageData,g as default}; diff --git a/assets/guide_blockchain_consensus.md.C3NI_nji.lean.js b/assets/guide_blockchain_consensus.md.C3NI_nji.lean.js new file mode 100644 index 00000000..f40ef533 --- /dev/null +++ b/assets/guide_blockchain_consensus.md.C3NI_nji.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as s,V as o}from"./chunks/framework.B6c1f-8R.js";const m=JSON.parse('{"title":"Consensus","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/consensus.md","filePath":"guide/blockchain/consensus.md","lastUpdated":1727242778000}'),a={name:"guide/blockchain/consensus.md"},n=o("",8),i=[n];function r(c,h,d,p,l,u){return s(),t("div",null,i)}const g=e(a,[["render",r]]);export{m as __pageData,g as default}; diff --git a/assets/guide_blockchain_data-model.md.UR0FZlta.js b/assets/guide_blockchain_data-model.md.UR0FZlta.js new file mode 100644 index 00000000..4ac085fc --- /dev/null +++ b/assets/guide_blockchain_data-model.md.UR0FZlta.js @@ -0,0 +1,19 @@ +import{_ as s,E as n,c as d,m as i,J as e,V as t,o}from"./chunks/framework.B6c1f-8R.js";const f=JSON.parse('{"title":"Data Model","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/data-model.md","filePath":"guide/blockchain/data-model.md","lastUpdated":1727242778000}'),r={name:"guide/blockchain/data-model.md"},c=t(`

Data Model

In language-specific guides we already walked you through registering domains, accounts, and assets. Here we merely wish to illustrate the relationship between various objects in the blockchain.


+   +-----------------------------------------------+
+   |                                               |
+   |     +-----------------+                       |
+   |     |Domain           |                       |
+   |     +--------------+  |                       |
+   |     ||Asset        |  |                       |
++--+--+  ||Definition(s)|  |                       |
+|World|  +--------------+  |                       |
++--+--+  |                 |                       |
+   |     +------------+    |                       |
+   |     ||Account(s)||    | has   +-----------+   |
+   |     |------------------------->Signatories|   |
+   |     +-----------------+       +-----------+   |
+   |                       |                       |
+   |                       |  has  +--------+      |
+   |                       +------->Asset(s)|      |
+   |                               +--------+      |
+   +-----------------------------------------------+

The following example shows the relationship between domains, accounts, and assets.

`,4),l={class:"domains-example-scope"},b=t('
Language-specific guides to register these objects
LanguageGuide
CLIRegister a domain, an account, an asset
RustRegister a domain, an account, an asset
Kotlin/JavaRegister a domain, an account, an asset
PythonRegister a domain, an account, an asset
JavaScript/TypeScriptRegister a domain, an account, an asset

The diagram below provides a more detailed illustration of the relationship between domains, accounts, and assets in the blockchain. You can learn more about permissions and roles and metadata in the corresponding sections. The asset structure is illustrated in a dedicated chapter.

',2);function p(A,v,g,h,m,u){const a=n("MermaidRenderWrap");return o(),d("div",null,[c,i("div",l,[e(a,{id:"mermaid_64b197bdaace931806f4329f68663c9a8c80858f31e40d2ebba2122ea46778c3d097a1942b854c14a7221d95be1bee95e77925bdcd094a656409f42a381c3bf7",text:"classDiagram%0A%0Aclass%20domain_wonderland%20%7B%0A%20%20id%20%3D%20%22wonderland%22%0A%7D%0Aclass%20account_alice%3A%3A%3Aaliceblue%20%7B%0A%20%20id%20%3D%20%22alice%40wonderland%22%0A%7D%0Aclass%20account_mad_hatter%3A%3A%3Aaliceblue%20%7B%0A%20%20id%20%3D%20%22mad_hatter%40wonderland%22%0A%7D%0A%0Aclass%20asset_rose%3A%3A%3Apink%20%7B%0A%20%20id%20%3D%20%22rose%23wonderland%22%0A%7D%0A%0Adomain_wonderland%20*--%20account_alice%20%3A%20registered%20in%0Adomain_wonderland%20*--%20asset_rose%20%3A%20registered%20in%0Aaccount_alice%20*--%20asset_rose%20%3A%20registered%20by%0Adomain_wonderland%20*--%20account_mad_hatter%20%3A%20registered%20in%0A%0Aclass%20domain_looking_glass%20%7B%0A%20%20id%20%3D%20%22looking_glass%22%0A%7D%0A%0Aclass%20account_rabbit%3A%3A%3Aaliceblue%20%7B%0A%20%20id%20%3D%20%22white_rabbit%40looking_glass%22%0A%7D%0A%0Adomain_looking_glass%20*--%20account_rabbit%20%3A%20registered%20in"})]),b,e(a,{id:"mermaid_2f20c1df6224dadf81d23a1a43dbb7e72a27090b7ef9cc03c1b0fdd9b6d843ff1140d32332b2f72dcf65fe3d4803afc3d28bbcc35e6ff26c72c8e605c8988cc0",text:"classDiagram%0A%0Aclass%20Domain%0Aclass%20Account%0Aclass%20AssetDefinition%0Aclass%20Asset%0A%0ADomain%20*--%20%22many%22%20Account%20%3A%20contains%0ADomain%20*--%20%22many%22%20AssetDefinition%20%3A%20contains%0AAccount%20*--%20%22many%22%20Asset%20%3A%20contains%0AAsset%20--%20AssetDefinition%0A%0ADomain%20%3A%20id%0ADomain%20%3A%20accounts%0ADomain%20%3A%20asset_definitions%0ADomain%20%3A%20logo%0ADomain%20%3A%20metadata%0A%0AAccount%20%3A%20id%0AAccount%20%3A%20assets%0AAccount%20%3A%20signatories%0AAccount%20%3A%20signature_check_condition%0AAccount%20%3A%20metadata%0AAccount%20%3A%20roles%0A%0A%0AAssetDefinition%20%3A%20id%0AAssetDefinition%20%3A%20value_type%0AAssetDefinition%20%3A%20mintable%0AAssetDefinition%20%3A%20metadata%0A%0AAsset%20%3A%20id%0AAsset%20%3A%20value"})])}const D=s(r,[["render",p],["__scopeId","data-v-099be746"]]);export{f as __pageData,D as default}; diff --git a/assets/guide_blockchain_data-model.md.UR0FZlta.lean.js b/assets/guide_blockchain_data-model.md.UR0FZlta.lean.js new file mode 100644 index 00000000..fc6fcc25 --- /dev/null +++ b/assets/guide_blockchain_data-model.md.UR0FZlta.lean.js @@ -0,0 +1 @@ +import{_ as s,E as n,c as d,m as i,J as e,V as t,o}from"./chunks/framework.B6c1f-8R.js";const f=JSON.parse('{"title":"Data Model","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/data-model.md","filePath":"guide/blockchain/data-model.md","lastUpdated":1727242778000}'),r={name:"guide/blockchain/data-model.md"},c=t("",4),l={class:"domains-example-scope"},b=t("",2);function p(A,v,g,h,m,u){const a=n("MermaidRenderWrap");return o(),d("div",null,[c,i("div",l,[e(a,{id:"mermaid_64b197bdaace931806f4329f68663c9a8c80858f31e40d2ebba2122ea46778c3d097a1942b854c14a7221d95be1bee95e77925bdcd094a656409f42a381c3bf7",text:"classDiagram%0A%0Aclass%20domain_wonderland%20%7B%0A%20%20id%20%3D%20%22wonderland%22%0A%7D%0Aclass%20account_alice%3A%3A%3Aaliceblue%20%7B%0A%20%20id%20%3D%20%22alice%40wonderland%22%0A%7D%0Aclass%20account_mad_hatter%3A%3A%3Aaliceblue%20%7B%0A%20%20id%20%3D%20%22mad_hatter%40wonderland%22%0A%7D%0A%0Aclass%20asset_rose%3A%3A%3Apink%20%7B%0A%20%20id%20%3D%20%22rose%23wonderland%22%0A%7D%0A%0Adomain_wonderland%20*--%20account_alice%20%3A%20registered%20in%0Adomain_wonderland%20*--%20asset_rose%20%3A%20registered%20in%0Aaccount_alice%20*--%20asset_rose%20%3A%20registered%20by%0Adomain_wonderland%20*--%20account_mad_hatter%20%3A%20registered%20in%0A%0Aclass%20domain_looking_glass%20%7B%0A%20%20id%20%3D%20%22looking_glass%22%0A%7D%0A%0Aclass%20account_rabbit%3A%3A%3Aaliceblue%20%7B%0A%20%20id%20%3D%20%22white_rabbit%40looking_glass%22%0A%7D%0A%0Adomain_looking_glass%20*--%20account_rabbit%20%3A%20registered%20in"})]),b,e(a,{id:"mermaid_2f20c1df6224dadf81d23a1a43dbb7e72a27090b7ef9cc03c1b0fdd9b6d843ff1140d32332b2f72dcf65fe3d4803afc3d28bbcc35e6ff26c72c8e605c8988cc0",text:"classDiagram%0A%0Aclass%20Domain%0Aclass%20Account%0Aclass%20AssetDefinition%0Aclass%20Asset%0A%0ADomain%20*--%20%22many%22%20Account%20%3A%20contains%0ADomain%20*--%20%22many%22%20AssetDefinition%20%3A%20contains%0AAccount%20*--%20%22many%22%20Asset%20%3A%20contains%0AAsset%20--%20AssetDefinition%0A%0ADomain%20%3A%20id%0ADomain%20%3A%20accounts%0ADomain%20%3A%20asset_definitions%0ADomain%20%3A%20logo%0ADomain%20%3A%20metadata%0A%0AAccount%20%3A%20id%0AAccount%20%3A%20assets%0AAccount%20%3A%20signatories%0AAccount%20%3A%20signature_check_condition%0AAccount%20%3A%20metadata%0AAccount%20%3A%20roles%0A%0A%0AAssetDefinition%20%3A%20id%0AAssetDefinition%20%3A%20value_type%0AAssetDefinition%20%3A%20mintable%0AAssetDefinition%20%3A%20metadata%0A%0AAsset%20%3A%20id%0AAsset%20%3A%20value"})])}const D=s(r,[["render",p],["__scopeId","data-v-099be746"]]);export{f as __pageData,D as default}; diff --git a/assets/guide_blockchain_domains.md.D61leQdc.js b/assets/guide_blockchain_domains.md.D61leQdc.js new file mode 100644 index 00000000..5d32a235 --- /dev/null +++ b/assets/guide_blockchain_domains.md.D61leQdc.js @@ -0,0 +1 @@ +import{_ as e,c as o,o as t,m as a,a as s}from"./chunks/framework.B6c1f-8R.js";const k=JSON.parse('{"title":"Domains","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/domains.md","filePath":"guide/blockchain/domains.md","lastUpdated":1727242778000}'),n={name:"guide/blockchain/domains.md"},i=a("h1",{id:"domains",tabindex:"-1"},[s("Domains "),a("a",{class:"header-anchor",href:"#domains","aria-label":'Permalink to "Domains"'},"​")],-1),d=a("p",null,"TBD",-1),c=[i,d];function r(m,l,_,h,p,f){return t(),o("div",null,c)}const b=e(n,[["render",r]]);export{k as __pageData,b as default}; diff --git a/assets/guide_blockchain_domains.md.D61leQdc.lean.js b/assets/guide_blockchain_domains.md.D61leQdc.lean.js new file mode 100644 index 00000000..5d32a235 --- /dev/null +++ b/assets/guide_blockchain_domains.md.D61leQdc.lean.js @@ -0,0 +1 @@ +import{_ as e,c as o,o as t,m as a,a as s}from"./chunks/framework.B6c1f-8R.js";const k=JSON.parse('{"title":"Domains","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/domains.md","filePath":"guide/blockchain/domains.md","lastUpdated":1727242778000}'),n={name:"guide/blockchain/domains.md"},i=a("h1",{id:"domains",tabindex:"-1"},[s("Domains "),a("a",{class:"header-anchor",href:"#domains","aria-label":'Permalink to "Domains"'},"​")],-1),d=a("p",null,"TBD",-1),c=[i,d];function r(m,l,_,h,p,f){return t(),o("div",null,c)}const b=e(n,[["render",r]]);export{k as __pageData,b as default}; diff --git a/assets/guide_blockchain_events.md.BcgNDCpt.js b/assets/guide_blockchain_events.md.BcgNDCpt.js new file mode 100644 index 00000000..710af63f --- /dev/null +++ b/assets/guide_blockchain_events.md.BcgNDCpt.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as i,V as a}from"./chunks/framework.B6c1f-8R.js";const u=JSON.parse('{"title":"Events","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/events.md","filePath":"guide/blockchain/events.md","lastUpdated":1727242778000}'),n={name:"guide/blockchain/events.md"},s=a('

Events

Events are emitted when certain things happen within the blockchain, e.g. a new account is created or a block is committed. There are different types of events:

  • pipeline events
  • data events
  • time events
  • trigger execution events

Pipeline Events

Pipeline events are emitted when transactions are submitted, executed, or committed to a block. A pipeline event contains the following information: the kind of entity that caused an event (transaction or block), its hash and status. The status can be either Validating (validation in progress), Rejected, or Committed. If an entity was rejected, the reason for the rejection is provided.

Data Events

Data events are emitted when there is a change related to one of the following entities: peers, domains, accounts, asset definitions, assets, triggers, roles, permission tokens, permission validators, or Iroha configuration. These types of events are used in entity filters.

Time Events

Time events are emitted when the world state view is ready to handle time triggers.

Trigger Execution Events

Trigger execution events are emitted when the ExecuteTrigger instruction is executed

',11),r=[s];function o(c,d,l,h,v,p){return i(),t("div",null,r)}const g=e(n,[["render",o]]);export{u as __pageData,g as default}; diff --git a/assets/guide_blockchain_events.md.BcgNDCpt.lean.js b/assets/guide_blockchain_events.md.BcgNDCpt.lean.js new file mode 100644 index 00000000..e708fc7c --- /dev/null +++ b/assets/guide_blockchain_events.md.BcgNDCpt.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as i,V as a}from"./chunks/framework.B6c1f-8R.js";const u=JSON.parse('{"title":"Events","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/events.md","filePath":"guide/blockchain/events.md","lastUpdated":1727242778000}'),n={name:"guide/blockchain/events.md"},s=a("",11),r=[s];function o(c,d,l,h,v,p){return i(),t("div",null,r)}const g=e(n,[["render",o]]);export{u as __pageData,g as default}; diff --git a/assets/guide_blockchain_expressions.md.CxFP2yxO.js b/assets/guide_blockchain_expressions.md.CxFP2yxO.js new file mode 100644 index 00000000..4be02ca1 --- /dev/null +++ b/assets/guide_blockchain_expressions.md.CxFP2yxO.js @@ -0,0 +1 @@ +import{_ as e,c as o,o as s,V as i}from"./chunks/framework.B6c1f-8R.js";const _=JSON.parse('{"title":"Expressions, Conditionals, Logic","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/expressions.md","filePath":"guide/blockchain/expressions.md","lastUpdated":1727242778000}'),t={name:"guide/blockchain/expressions.md"},a=i('

Expressions, Conditionals, Logic

All Iroha Special Instructions operate on expressions. Each expression has an EvaluatesTo, which is used in instruction execution. While you could specify the account name directly, you could also specify the account ID via some mathematical or string operation. You can check if an account is registered on the blockchain too.

Using expressions that implement EvaluatesTo<bool>, you can set up conditional logic and execute more sophisticated operations on-chain. For example, you can submit a Mint instruction only if a specific account is registered.

Recall that you can combine this with queries, and as such can program the blockchain to do some amazing stuff. This is what we refer to as smart contracts, the defining feature of the advanced usage of blockchain technology.

',4),n=[a];function c(r,l,d,h,p,u){return s(),o("div",null,n)}const f=e(t,[["render",c]]);export{_ as __pageData,f as default}; diff --git a/assets/guide_blockchain_expressions.md.CxFP2yxO.lean.js b/assets/guide_blockchain_expressions.md.CxFP2yxO.lean.js new file mode 100644 index 00000000..cd8160c3 --- /dev/null +++ b/assets/guide_blockchain_expressions.md.CxFP2yxO.lean.js @@ -0,0 +1 @@ +import{_ as e,c as o,o as s,V as i}from"./chunks/framework.B6c1f-8R.js";const _=JSON.parse('{"title":"Expressions, Conditionals, Logic","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/expressions.md","filePath":"guide/blockchain/expressions.md","lastUpdated":1727242778000}'),t={name:"guide/blockchain/expressions.md"},a=i("",4),n=[a];function c(r,l,d,h,p,u){return s(),o("div",null,n)}const f=e(t,[["render",c]]);export{_ as __pageData,f as default}; diff --git a/assets/guide_blockchain_filters.md.4e4lTrE8.js b/assets/guide_blockchain_filters.md.4e4lTrE8.js new file mode 100644 index 00000000..cae00eea --- /dev/null +++ b/assets/guide_blockchain_filters.md.4e4lTrE8.js @@ -0,0 +1 @@ +import{_ as i,E as a,c as n,J as t,V as A,o as s}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Filters","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/filters.md","filePath":"guide/blockchain/filters.md","lastUpdated":1727242778000}'),r={name:"guide/blockchain/filters.md"},d=A('

Filters

Iroha uses filter-map paradigm to monitor events. Let's look at different types of filters that can be used in Iroha.

Data Filters

A data filter is a tuple with a single variant, which is a FilterOpt of an EntityFilter:

',4),o=A("

FilterOpt stands for Optional Filter. It can either AcceptAll or accept BySome of another Filter. An EntityFilter is a filter that matches events produced by a certain type entity, e.g. by account or domain.

Here is the list of EntityFilters in Iroha:

",2);function l(c,E,m,D,v,u){const e=a("MermaidRenderWrap");return s(),n("div",null,[d,t(e,{id:"mermaid_dc1d04f60b4f5b960fd5a56516975b14aceeaba39d2a33822de629ad938f1941161b4864b3165a36ba4c243c4c8184cc4b0f28204cd375175550d0e0ddbbb2a4",text:"classDiagram%0A%0Aclass%20EntityFilter%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20ByPeer(FilterOpt~PeerFilter~)%0A%20%20%20%20ByDomain(FilterOpt~DomainFilter~)%0A%20%20%20%20ByAccount(FilterOpt~AccountFilter~)%0A%20%20%20%20ByAssetDefinition(FilterOpt~AssetDefinitionFilter~)%0A%20%20%20%20ByAsset(FilterOpt~AssetFilter~)%0A%20%20%20%20ByTrigger(FilterOpt~TriggerFilter~)%0A%20%20%20%20ByRole(FilterOpt~RoleFilter~)%0A%7D%0A%0Aclass%20FilterOpt~F%3A%20Filter~%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20AcceptAll%0A%20%20%20%20BySome(F)%0A%7D%0A%0Aclass%20EventFilter%20%7B%0A%20%20%20%20FilterOpt~EntityFilter~%0A%7D%0A%0AFilterOpt%20..%20EventFilter%0AFilterOpt%20..%20EntityFilter%0AEntityFilter%20..%20EventFilter"}),o,t(e,{id:"mermaid_c6f7dcaf44bbc0f986880725c420ae3c8e4ace31ddb708d70e3328e746856ebb2310b7adc671fa5c17d4afff9df55b5e88522ae8fe9021dabb61682f4bfc5e08",text:"classDiagram%0A%0Adirection%20LR%0A%0Aclass%20TriggerFilter%20%7B%0A%20%20%20%20type%20EventType%20%3D%20TriggerEvent%0A%20%20%20%20type%20EventFilter%20%3D%20TriggerEventFilter%0A%7D%0A%0Aclass%20TriggerEventFilter%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20ByCreated%0A%20%20%20%20ByDeleted%0A%20%20%20%20ByExtended%0A%20%20%20%20ByShortened%0A%7D%0A%0Aclass%20TriggerEvent%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20Created(TriggerId)%0A%20%20%20%20Deleted(TriggerId)%0A%20%20%20%20Extended(TriggerNumberOfExecutionsChanged)%0A%20%20%20%20Shortened(TriggerNumberOfExecutionsChanged)%0A%7D%0A%0Aclass%20TriggerNumberOfExecutionsChanged%20%7B%0A%20%20%20%20trigger_id%3A%20TriggerId%0A%20%20%20%20by%3A%20u32%0A%7D%0A%0ATriggerFilter%20..%20TriggerEvent%0ATriggerEvent%20..%20TriggerNumberOfExecutionsChanged%0ATriggerFilter%20..%20TriggerEventFilter%0A%0A%0Aclass%20RoleFilter%20%7B%0A%20%20%20%20type%20EventType%20%3D%20RoleEvent%0A%20%20%20%20type%20EventFilter%20%3D%20RoleEventFilter%0A%7D%0A%0Aclass%20RoleEventFilter%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20ByCreated%0A%20%20%20%20ByDeleted%0A%7D%0A%0Aclass%20RoleEvent%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20Created(RoleId)%0A%20%20%20%20Deleted(RoleId)%0A%20%20%20%20PermissionRemoved(PermissionRemoved)%0A%7D%0A%0Aclass%20PermissionRemoved%20%7B%0A%20%20%20%20role_id%3A%20RoleId%0A%20%20%20%20permission_definition_id%3A%20PermissionTokenDefinitionId%0A%7D%0A%0ARoleFilter%20..%20RoleEvent%0ARoleEvent%20..%20PermissionRemoved%0ARoleFilter%20..%20RoleEventFilter%0A%0A%0Aclass%20PeerFilter%20%7B%0A%20%20%20%20type%20EventType%20%3D%20PeerEvent%0A%20%20%20%20type%20EventFilter%20%3D%20PeerEventFilter%0A%7D%0A%0Aclass%20PeerEventFilter%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20ByAdded%0A%20%20%20%20ByRemoved%0A%7D%0A%0Aclass%20PeerEvent%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20Added(PeerId)%0A%20%20%20%20Removed(PeerId)%0A%7D%0A%0APeerFilter%20..%20PeerEvent%0APeerFilter%20..%20PeerEventFilter%0A%0A%0A%0A%0Aclass%20AssetDefinitionFilter%20%7B%0A%20%20%20%20type%20EventType%20%3D%20AssetDefinitionEvent%0A%20%20%20%20type%20EventFilter%20%3D%20AssetDefinitionEventFilter%0A%7D%0A%0Aclass%20AssetDefinitionEventFilter%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20ByCreated%0A%20%20%20%20ByDeleted%0A%20%20%20%20ByMintabilityChanged%0A%20%20%20%20ByMetadataInserted%0A%20%20%20%20ByMetadataRemoved%0A%7D%0A%0Aclass%20AssetDefinitionEvent%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20Created(AssetDefinitionId)%0A%20%20%20%20MintabilityChanged(AssetDefinitionId)%0A%20%20%20%20Deleted(AssetDefinitionId)%0A%20%20%20%20MetadataInserted(AssetDefinitionMetadataChanged)%0A%20%20%20%20MetadataRemoved(AssetDefinitionMetadataChanged)%0A%7D%0A%0Aclass%20AssetDefinitionMetadataChanged%20%7B%0A%20%20%20%20target_id%3A%20AssetDefinitionId%0A%20%20%20%20key%3A%20Name%0A%20%20%20%20value%3A%20Box~Value~%0A%7D%0A%0AAssetDefinitionFilter%20..%20AssetDefinitionEvent%0AAssetDefinitionEvent%20..%20AssetDefinitionMetadataChanged%0AAssetDefinitionFilter%20..%20AssetDefinitionEventFilter%0A%0A%0A%0Aclass%20AssetFilter%20%7B%0A%20%20%20%20type%20EventType%20%3D%20AssetEvent%0A%20%20%20%20type%20EventFilter%20%3D%20AssetEventFilter%0A%7D%0A%0Aclass%20AssetEventFilter%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20ByCreated%0A%20%20%20%20ByDeleted%0A%20%20%20%20ByAdded%0A%20%20%20%20ByRemoved%0A%20%20%20%20ByMetadataInserted%0A%20%20%20%20ByMetadataRemoved%0A%7D%0A%0Aclass%20AssetEvent%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20Created(AssetId)%0A%20%20%20%20Deleted(AssetId)%0A%20%20%20%20Added(AssetChanged)%0A%20%20%20%20Removed(AssetChanged)%0A%20%20%20%20MetadataInserted(AssetMetadataChanged)%0A%20%20%20%20MetadataRemoved(AssetMetadataChanged)%0A%7D%0A%0Aclass%20AssetChanged%20%7B%0A%20%20%20%20asset_id%3A%20AssetId%0A%20%20%20%20amount%3A%20AssetValue%0A%7D%0A%0Aclass%20AssetMetadataChanged%20%7B%0A%20%20%20%20target_id%3A%20AssetId%0A%20%20%20%20key%3A%20Name%0A%20%20%20%20value%3A%20Box~Value~%0A%7D%0A%0AAssetFilter%20..%20AssetEvent%0AAssetEvent%20..%20AssetChanged%0AAssetEvent%20..%20AssetMetadataChanged%0AAssetFilter%20..%20AssetEventFilter%0A%0A%0A%0Aclass%20DomainFilter%20%7B%0A%20%20%20%20type%20EventType%20%3D%20DomainEvent%0A%20%20%20%20type%20EventFilter%20%3D%20DomainEventFilter%0A%7D%0A%0Aclass%20DomainEventFilter%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20ByAccount(FilterOpt~AccountFilter~)%0A%20%20%20%20ByAssetDefinition(FilterOpt~AssetDefinitionFilter~)%0A%20%20%20%20ByCreated%0A%20%20%20%20ByDeleted%0A%20%20%20%20ByMetadataInserted%0A%20%20%20%20ByMetadataRemoved%0A%7D%0A%0Aclass%20DomainEvent%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20Account(AccountEvent)%0A%20%20%20%20AssetDefinition(AssetDefinitionEvent)%0A%20%20%20%20Created(DomainId)%0A%20%20%20%20Deleted(DomainId)%0A%20%20%20%20MetadataInserted(DomainMetadataChanged)%0A%20%20%20%20MetadataRemoved(DomainMetadataChanged)%0A%7D%0A%0Aclass%20DomainMetadataChanged%20%7B%0A%20%20%20%20target_id%3A%20DomainId%0A%20%20%20%20key%3A%20Name%0A%20%20%20%20value%3A%20Box~Value~%0A%7D%0A%0ADomainFilter%20..%20DomainEvent%0ADomainEvent%20..%20DomainMetadataChanged%0ADomainFilter%20..%20DomainEventFilter%0A%0A%0Aclass%20AccountFilter%20%7B%0A%20%20%20%20type%20EventType%20%3D%20AccountEvent%0A%20%20%20%20type%20EventFilter%20%3D%20AccountEventFilter%0A%7D%0A%0Aclass%20AccountEventFilter%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20ByAsset(FilterOpt~AssetFilter~)%0A%20%20%20%20ByCreated%0A%20%20%20%20ByDeleted%0A%20%20%20%20ByAuthenticationAdded%0A%20%20%20%20ByAuthenticationRemoved%0A%20%20%20%20ByPermissionAdded%0A%20%20%20%20ByPermissionRemoved%0A%20%20%20%20ByRoleRevoked%0A%20%20%20%20ByRoleGranted%0A%20%20%20%20ByMetadataInserted%0A%20%20%20%20ByMetadataRemoved%0A%7D%0A%0Aclass%20AccountEvent%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20Asset(AssetEvent)%0A%20%20%20%20Created(AccountId)%0A%20%20%20%20Deleted(AccountId)%0A%20%20%20%20AuthenticationAdded(AccountId)%0A%20%20%20%20AuthenticationRemoved(AccountId)%0A%20%20%20%20PermissionAdded(AccountPermissionChanged)%0A%20%20%20%20PermissionRemoved(AccountPermissionChanged)%0A%20%20%20%20RoleRevoked(AccountRoleChanged)%0A%20%20%20%20RoleGranted(AccountRoleChanged)%0A%20%20%20%20MetadataInserted(AccountMetadataChanged)%0A%20%20%20%20MetadataRemoved(AccountMetadataChanged)%0A%7D%0A%0Aclass%20AccountPermissionChanged%20%7B%0A%20%20%20%20account_id%3A%20AccountId%0A%20%20%20%20permission_id%3A%20PermissionTokenId%0A%7D%0A%0Aclass%20AccountRoleChanged%20%7B%0A%20%20%20%20account_id%3A%20AccountId%0A%20%20%20%20role_id%3A%20RoleId%0A%7D%0A%0Aclass%20AccountMetadataChanged%20%7B%0A%20%20%20%20target_id%3A%20AccountId%0A%20%20%20%20key%3A%20Name%0A%20%20%20%20value%3A%20Box~Value~%0A%7D%0A%0AAccountFilter%20..%20AccountEvent%0AAccountEvent%20..%20AccountPermissionChanged%0AAccountEvent%20..%20AccountRoleChanged%0AAccountEvent%20..%20AccountMetadataChanged%0AAccountFilter%20..%20AccountEventFilter"})])}const y=i(r,[["render",l]]);export{g as __pageData,y as default}; diff --git a/assets/guide_blockchain_filters.md.4e4lTrE8.lean.js b/assets/guide_blockchain_filters.md.4e4lTrE8.lean.js new file mode 100644 index 00000000..802cdcae --- /dev/null +++ b/assets/guide_blockchain_filters.md.4e4lTrE8.lean.js @@ -0,0 +1 @@ +import{_ as i,E as a,c as n,J as t,V as A,o as s}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Filters","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/filters.md","filePath":"guide/blockchain/filters.md","lastUpdated":1727242778000}'),r={name:"guide/blockchain/filters.md"},d=A("",4),o=A("",2);function l(c,E,m,D,v,u){const e=a("MermaidRenderWrap");return s(),n("div",null,[d,t(e,{id:"mermaid_dc1d04f60b4f5b960fd5a56516975b14aceeaba39d2a33822de629ad938f1941161b4864b3165a36ba4c243c4c8184cc4b0f28204cd375175550d0e0ddbbb2a4",text:"classDiagram%0A%0Aclass%20EntityFilter%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20ByPeer(FilterOpt~PeerFilter~)%0A%20%20%20%20ByDomain(FilterOpt~DomainFilter~)%0A%20%20%20%20ByAccount(FilterOpt~AccountFilter~)%0A%20%20%20%20ByAssetDefinition(FilterOpt~AssetDefinitionFilter~)%0A%20%20%20%20ByAsset(FilterOpt~AssetFilter~)%0A%20%20%20%20ByTrigger(FilterOpt~TriggerFilter~)%0A%20%20%20%20ByRole(FilterOpt~RoleFilter~)%0A%7D%0A%0Aclass%20FilterOpt~F%3A%20Filter~%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20AcceptAll%0A%20%20%20%20BySome(F)%0A%7D%0A%0Aclass%20EventFilter%20%7B%0A%20%20%20%20FilterOpt~EntityFilter~%0A%7D%0A%0AFilterOpt%20..%20EventFilter%0AFilterOpt%20..%20EntityFilter%0AEntityFilter%20..%20EventFilter"}),o,t(e,{id:"mermaid_c6f7dcaf44bbc0f986880725c420ae3c8e4ace31ddb708d70e3328e746856ebb2310b7adc671fa5c17d4afff9df55b5e88522ae8fe9021dabb61682f4bfc5e08",text:"classDiagram%0A%0Adirection%20LR%0A%0Aclass%20TriggerFilter%20%7B%0A%20%20%20%20type%20EventType%20%3D%20TriggerEvent%0A%20%20%20%20type%20EventFilter%20%3D%20TriggerEventFilter%0A%7D%0A%0Aclass%20TriggerEventFilter%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20ByCreated%0A%20%20%20%20ByDeleted%0A%20%20%20%20ByExtended%0A%20%20%20%20ByShortened%0A%7D%0A%0Aclass%20TriggerEvent%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20Created(TriggerId)%0A%20%20%20%20Deleted(TriggerId)%0A%20%20%20%20Extended(TriggerNumberOfExecutionsChanged)%0A%20%20%20%20Shortened(TriggerNumberOfExecutionsChanged)%0A%7D%0A%0Aclass%20TriggerNumberOfExecutionsChanged%20%7B%0A%20%20%20%20trigger_id%3A%20TriggerId%0A%20%20%20%20by%3A%20u32%0A%7D%0A%0ATriggerFilter%20..%20TriggerEvent%0ATriggerEvent%20..%20TriggerNumberOfExecutionsChanged%0ATriggerFilter%20..%20TriggerEventFilter%0A%0A%0Aclass%20RoleFilter%20%7B%0A%20%20%20%20type%20EventType%20%3D%20RoleEvent%0A%20%20%20%20type%20EventFilter%20%3D%20RoleEventFilter%0A%7D%0A%0Aclass%20RoleEventFilter%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20ByCreated%0A%20%20%20%20ByDeleted%0A%7D%0A%0Aclass%20RoleEvent%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20Created(RoleId)%0A%20%20%20%20Deleted(RoleId)%0A%20%20%20%20PermissionRemoved(PermissionRemoved)%0A%7D%0A%0Aclass%20PermissionRemoved%20%7B%0A%20%20%20%20role_id%3A%20RoleId%0A%20%20%20%20permission_definition_id%3A%20PermissionTokenDefinitionId%0A%7D%0A%0ARoleFilter%20..%20RoleEvent%0ARoleEvent%20..%20PermissionRemoved%0ARoleFilter%20..%20RoleEventFilter%0A%0A%0Aclass%20PeerFilter%20%7B%0A%20%20%20%20type%20EventType%20%3D%20PeerEvent%0A%20%20%20%20type%20EventFilter%20%3D%20PeerEventFilter%0A%7D%0A%0Aclass%20PeerEventFilter%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20ByAdded%0A%20%20%20%20ByRemoved%0A%7D%0A%0Aclass%20PeerEvent%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20Added(PeerId)%0A%20%20%20%20Removed(PeerId)%0A%7D%0A%0APeerFilter%20..%20PeerEvent%0APeerFilter%20..%20PeerEventFilter%0A%0A%0A%0A%0Aclass%20AssetDefinitionFilter%20%7B%0A%20%20%20%20type%20EventType%20%3D%20AssetDefinitionEvent%0A%20%20%20%20type%20EventFilter%20%3D%20AssetDefinitionEventFilter%0A%7D%0A%0Aclass%20AssetDefinitionEventFilter%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20ByCreated%0A%20%20%20%20ByDeleted%0A%20%20%20%20ByMintabilityChanged%0A%20%20%20%20ByMetadataInserted%0A%20%20%20%20ByMetadataRemoved%0A%7D%0A%0Aclass%20AssetDefinitionEvent%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20Created(AssetDefinitionId)%0A%20%20%20%20MintabilityChanged(AssetDefinitionId)%0A%20%20%20%20Deleted(AssetDefinitionId)%0A%20%20%20%20MetadataInserted(AssetDefinitionMetadataChanged)%0A%20%20%20%20MetadataRemoved(AssetDefinitionMetadataChanged)%0A%7D%0A%0Aclass%20AssetDefinitionMetadataChanged%20%7B%0A%20%20%20%20target_id%3A%20AssetDefinitionId%0A%20%20%20%20key%3A%20Name%0A%20%20%20%20value%3A%20Box~Value~%0A%7D%0A%0AAssetDefinitionFilter%20..%20AssetDefinitionEvent%0AAssetDefinitionEvent%20..%20AssetDefinitionMetadataChanged%0AAssetDefinitionFilter%20..%20AssetDefinitionEventFilter%0A%0A%0A%0Aclass%20AssetFilter%20%7B%0A%20%20%20%20type%20EventType%20%3D%20AssetEvent%0A%20%20%20%20type%20EventFilter%20%3D%20AssetEventFilter%0A%7D%0A%0Aclass%20AssetEventFilter%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20ByCreated%0A%20%20%20%20ByDeleted%0A%20%20%20%20ByAdded%0A%20%20%20%20ByRemoved%0A%20%20%20%20ByMetadataInserted%0A%20%20%20%20ByMetadataRemoved%0A%7D%0A%0Aclass%20AssetEvent%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20Created(AssetId)%0A%20%20%20%20Deleted(AssetId)%0A%20%20%20%20Added(AssetChanged)%0A%20%20%20%20Removed(AssetChanged)%0A%20%20%20%20MetadataInserted(AssetMetadataChanged)%0A%20%20%20%20MetadataRemoved(AssetMetadataChanged)%0A%7D%0A%0Aclass%20AssetChanged%20%7B%0A%20%20%20%20asset_id%3A%20AssetId%0A%20%20%20%20amount%3A%20AssetValue%0A%7D%0A%0Aclass%20AssetMetadataChanged%20%7B%0A%20%20%20%20target_id%3A%20AssetId%0A%20%20%20%20key%3A%20Name%0A%20%20%20%20value%3A%20Box~Value~%0A%7D%0A%0AAssetFilter%20..%20AssetEvent%0AAssetEvent%20..%20AssetChanged%0AAssetEvent%20..%20AssetMetadataChanged%0AAssetFilter%20..%20AssetEventFilter%0A%0A%0A%0Aclass%20DomainFilter%20%7B%0A%20%20%20%20type%20EventType%20%3D%20DomainEvent%0A%20%20%20%20type%20EventFilter%20%3D%20DomainEventFilter%0A%7D%0A%0Aclass%20DomainEventFilter%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20ByAccount(FilterOpt~AccountFilter~)%0A%20%20%20%20ByAssetDefinition(FilterOpt~AssetDefinitionFilter~)%0A%20%20%20%20ByCreated%0A%20%20%20%20ByDeleted%0A%20%20%20%20ByMetadataInserted%0A%20%20%20%20ByMetadataRemoved%0A%7D%0A%0Aclass%20DomainEvent%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20Account(AccountEvent)%0A%20%20%20%20AssetDefinition(AssetDefinitionEvent)%0A%20%20%20%20Created(DomainId)%0A%20%20%20%20Deleted(DomainId)%0A%20%20%20%20MetadataInserted(DomainMetadataChanged)%0A%20%20%20%20MetadataRemoved(DomainMetadataChanged)%0A%7D%0A%0Aclass%20DomainMetadataChanged%20%7B%0A%20%20%20%20target_id%3A%20DomainId%0A%20%20%20%20key%3A%20Name%0A%20%20%20%20value%3A%20Box~Value~%0A%7D%0A%0ADomainFilter%20..%20DomainEvent%0ADomainEvent%20..%20DomainMetadataChanged%0ADomainFilter%20..%20DomainEventFilter%0A%0A%0Aclass%20AccountFilter%20%7B%0A%20%20%20%20type%20EventType%20%3D%20AccountEvent%0A%20%20%20%20type%20EventFilter%20%3D%20AccountEventFilter%0A%7D%0A%0Aclass%20AccountEventFilter%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20ByAsset(FilterOpt~AssetFilter~)%0A%20%20%20%20ByCreated%0A%20%20%20%20ByDeleted%0A%20%20%20%20ByAuthenticationAdded%0A%20%20%20%20ByAuthenticationRemoved%0A%20%20%20%20ByPermissionAdded%0A%20%20%20%20ByPermissionRemoved%0A%20%20%20%20ByRoleRevoked%0A%20%20%20%20ByRoleGranted%0A%20%20%20%20ByMetadataInserted%0A%20%20%20%20ByMetadataRemoved%0A%7D%0A%0Aclass%20AccountEvent%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20Asset(AssetEvent)%0A%20%20%20%20Created(AccountId)%0A%20%20%20%20Deleted(AccountId)%0A%20%20%20%20AuthenticationAdded(AccountId)%0A%20%20%20%20AuthenticationRemoved(AccountId)%0A%20%20%20%20PermissionAdded(AccountPermissionChanged)%0A%20%20%20%20PermissionRemoved(AccountPermissionChanged)%0A%20%20%20%20RoleRevoked(AccountRoleChanged)%0A%20%20%20%20RoleGranted(AccountRoleChanged)%0A%20%20%20%20MetadataInserted(AccountMetadataChanged)%0A%20%20%20%20MetadataRemoved(AccountMetadataChanged)%0A%7D%0A%0Aclass%20AccountPermissionChanged%20%7B%0A%20%20%20%20account_id%3A%20AccountId%0A%20%20%20%20permission_id%3A%20PermissionTokenId%0A%7D%0A%0Aclass%20AccountRoleChanged%20%7B%0A%20%20%20%20account_id%3A%20AccountId%0A%20%20%20%20role_id%3A%20RoleId%0A%7D%0A%0Aclass%20AccountMetadataChanged%20%7B%0A%20%20%20%20target_id%3A%20AccountId%0A%20%20%20%20key%3A%20Name%0A%20%20%20%20value%3A%20Box~Value~%0A%7D%0A%0AAccountFilter%20..%20AccountEvent%0AAccountEvent%20..%20AccountPermissionChanged%0AAccountEvent%20..%20AccountRoleChanged%0AAccountEvent%20..%20AccountMetadataChanged%0AAccountFilter%20..%20AccountEventFilter"})])}const y=i(r,[["render",l]]);export{g as __pageData,y as default}; diff --git a/assets/guide_blockchain_how-iroha-works.md.DCXmnzDS.js b/assets/guide_blockchain_how-iroha-works.md.DCXmnzDS.js new file mode 100644 index 00000000..f7544f81 --- /dev/null +++ b/assets/guide_blockchain_how-iroha-works.md.DCXmnzDS.js @@ -0,0 +1 @@ +import{_ as e,c as o,o as t,V as a}from"./chunks/framework.B6c1f-8R.js";const w=JSON.parse('{"title":"How Iroha works","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/how-iroha-works.md","filePath":"guide/blockchain/how-iroha-works.md","lastUpdated":1727242778000}'),r={name:"guide/blockchain/how-iroha-works.md"},i=a('

How Iroha works

To understand how Iroha operates, let's draw parallels between a blockchain and a computer. If the blockchain is the computer, then in this metaphor of ours the client binary (for example: iroha) is the keyboard, the blockchain is the hard drive, and the Iroha peer software is the processor. Like a processor, Iroha accepts portable instructions that modify what's written to the blockchain, allow certain users to use the network, and lock others out.

Any operation that is run on-chain is written in terms of Iroha Special Instructions (ISI), and there is no other way of modifying the world state.

Each interaction with the blockchain is done via a transaction. A transaction is a collection of instructions, which are either glued together in sequence or compiled into what we affectionately call a WASM blob. You need these instructions to register an account, remove an account, add X amount of Y currency, and so on.

To read the information encoded in the blocks of a blockchain (the current world state), you use queries. Queries are submitted like instructions, but they're not tracked and recorded in blocks, so they're much more lightweight. If you use queries as part of complicated logic (e.g. inside WASM), they have a non-negligible impact on the size of the blocks. Queries that are only used to get information leave no trace in the blockchain.

',5),n=[i];function h(s,c,d,l,u,p){return t(),o("div",null,n)}const k=e(r,[["render",h]]);export{w as __pageData,k as default}; diff --git a/assets/guide_blockchain_how-iroha-works.md.DCXmnzDS.lean.js b/assets/guide_blockchain_how-iroha-works.md.DCXmnzDS.lean.js new file mode 100644 index 00000000..082ff47b --- /dev/null +++ b/assets/guide_blockchain_how-iroha-works.md.DCXmnzDS.lean.js @@ -0,0 +1 @@ +import{_ as e,c as o,o as t,V as a}from"./chunks/framework.B6c1f-8R.js";const w=JSON.parse('{"title":"How Iroha works","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/how-iroha-works.md","filePath":"guide/blockchain/how-iroha-works.md","lastUpdated":1727242778000}'),r={name:"guide/blockchain/how-iroha-works.md"},i=a("",5),n=[i];function h(s,c,d,l,u,p){return t(),o("div",null,n)}const k=e(r,[["render",h]]);export{w as __pageData,k as default}; diff --git a/assets/guide_blockchain_instructions.md.B0jSwXfH.js b/assets/guide_blockchain_instructions.md.B0jSwXfH.js new file mode 100644 index 00000000..088271a2 --- /dev/null +++ b/assets/guide_blockchain_instructions.md.B0jSwXfH.js @@ -0,0 +1 @@ +import{_ as r,c as i,o as s,V as a,m as e,a as t}from"./chunks/framework.B6c1f-8R.js";const v=JSON.parse('{"title":"Iroha Special Instructions","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/instructions.md","filePath":"guide/blockchain/instructions.md","lastUpdated":1727242778000}'),n={name:"guide/blockchain/instructions.md"},o=a('

Iroha Special Instructions

When we spoke about how Iroha operates, we said that Iroha Special Instructions are the only way to modify the world state. So, what kind of special instructions do we have? If you've read the language-specific guides in this tutorial, you've already seen a couple of instructions: Register<Account> and Mint<Quantity>.

Here is the full list of Iroha Special Instructions:

InstructionDescriptions
Register/UnregisterGive an ID to a new entity on the blockchain.
Mint/BurnMint/burn assets, triggers, or permission tokens.
SetKeyValue/RemoveKeyValueUpdate blockchain object metadata.
NewParameter/SetParameterCreate/set a chain-wide config parameter.
Grant/RevokeGive or remove certain permissions from accounts.
TransferTransfer assets between accounts.
ExecuteTriggerExecute triggers.
If, Pair, SequenceUse to create composite instructions.

Let's start with a summary of Iroha Special Instructions; what objects each instruction can be called for and what instructions are available for each object.

Summary

For each instruction, there is a list of objects on which this instruction can be run on. For example, only assets can be transferred, while minting can refer to assets, triggers, and permission tokens.

Some instructions require a destination to be specified. For example, if you transfer assets, you always need to specify to which account you are transferring them. On the other hand, when you are registering something, all you need is the object that you want to register.

InstructionObjectsDestination
Register/Unregisteraccounts, domains, asset definitions, triggers, roles, peers
Mint/Burnassets, triggers (trigger repetitions), permission tokensaccounts
SetKeyValue/RemoveKeyValueany objects that have metadata: accounts, domains, assets, asset definitions, triggers, transactions
NewParameter/SetParameterIroha configuration parameters
Grant/Revokeroles, permission tokensaccounts
Transferassetsaccounts
ExecuteTriggertriggers
If, Pair, Sequenceany instructions

There is also another way of looking at ISI, i.e. in terms of the target of each instruction. For example, when you register an account, you do so within a certain domain. This means that the target of the Register<Account> instruction would be the domain within which it is being registered.

TargetInstructions
Account(un)register assets, mint/burn account public key, mint/burn account signature condition check, update account metadata, grant/revoke a permission token, grant/revoke role
Domain(un)register accounts, (un)register asset definitions, update asset metadata, update domain metadata
Assetupdate metadata, mint/burn, transfer
Trigger(un)register, mint/burn trigger repetitions, execute trigger
World(un)register domains, peers, roles

(Un)Register

Registering and unregistering are the instructions used to give an ID to a new entity on the blockchain.

Everything that can be registered is both Registrable and Identifiable, but not everything that's Identifiable is Registrable. Most things are registered directly, like Peers, but in some cases the representation in the blockchain has considerably more data. For security and performance reasons, we use builders for such data structures (e.g. NewAccount). As a rule, everything that can be registered, can also be un-registered, but that is not a hard and fast rule.

You can register domains, accounts, asset definitions, peers, roles, and triggers. Check our naming conventions to learn about the restrictions put on entity names.

INFO

Note that depending on how you decide to set up your genesis block in genesis.json (specifically, whether or not you include registration of permission tokens), the process for registering an account can be very different. In general, we can summarise it like this:

  • In a public blockchain, anyone should be able to register an account.
  • In a private blockchain, there can be a unique process for registering accounts. In a typical private blockchain, i.e. a blockchain without any unique processes for registering accounts, you need an account to register another account.

We discuss these differences in great detail when we compare private and public blockchains.

INFO

Registering a peer is currently the only way of adding peers that were not part of the original TRUSTED_PEERS array to the network.

Refer to one of the language-specific guides to walk you through the process of registering objects in a blockchain:

LanguageGuide
CLIRegister a domain, an account, an asset
RustRegister a domain, an account, an asset
Kotlin/JavaRegister a domain, an account, an asset
PythonRegister a domain, an account, an asset
JavaScript/TypeScriptRegister a domain, an account, an asset

Mint/Burn

Minting and burning can refer to assets, triggers (if the trigger has a limited number of repetitions), and temporary permission tokens. Some assets can be declared as non-mintable, meaning that they can be minted only once after registration.

',21),d=e("p",null,[t("Assets and permission tokens need to be minted to a specific account, usually the one that registered the asset in the first place. All assets are assumed to be non-negative as well, so you can never have "),e("span",{class:"katex"},[e("span",{class:"katex-mathml"},[e("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[e("semantics",null,[e("mrow",null,[e("mo",null,"−"),e("mn",null,"1.0")]),e("annotation",{encoding:"application/x-tex"},"-1.0")])])]),e("span",{class:"katex-html","aria-hidden":"true"},[e("span",{class:"base"},[e("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),e("span",{class:"mord"},"−"),e("span",{class:"mord"},"1.0")])])]),t(" of "),e("code",null,"time"),t(" or "),e("code",null,"Burn"),t(" a negative amount and get a "),e("code",null,"Mint"),t(".")],-1),c=a('

Refer to one of the language-specific guides to walk you through the process of minting assets in a blockchain:

Here are examples of burning assets:

Transfer

Similar to mint and burn instructions, transferring refers to assets. You can transfer assets between different accounts.

To do this, an account have to be granted the permission to transfer assets. Refer to an example on how to transfer assets with CLI or Rust.

Grant/Revoke

Grant and revoke instructions are used for account permissions and roles.

Grant is used to permanently grant a user either a single permission, or a group of permissions (a "role"). Granted roles and permissions can only be removed via the Revoke instruction. As such, these instructions should be used carefully.

SetKeyValue/RemoveKeyValue

These instructions are used with the key/value Store asset type. This use case has not received much attention so far, because storing data in the blockchain is a rather advanced topic that we shall cover separately.

NewParameter/SetParameter

With these instructions, you can create (NewParameter) and change (SetParameter) chain-wide configuration parameters for Iroha.

ExecuteTrigger

This instruction is used to execute triggers.

Composite instructions

Iroha also offers composite instructions (If, Pair, Sequence) to execute instructions in a certain way:

  • If: execute one of the two given instructions based on a given condition
  • Sequence: execute a provided vector of instructions in a given order
  • Pair: execute both provided instructions in a specified order
',19),h=[o,d,c];function u(l,g,m,p,f,b){return s(),i("div",null,h)}const k=r(n,[["render",u]]);export{v as __pageData,k as default}; diff --git a/assets/guide_blockchain_instructions.md.B0jSwXfH.lean.js b/assets/guide_blockchain_instructions.md.B0jSwXfH.lean.js new file mode 100644 index 00000000..8673b5f0 --- /dev/null +++ b/assets/guide_blockchain_instructions.md.B0jSwXfH.lean.js @@ -0,0 +1 @@ +import{_ as r,c as i,o as s,V as a,m as e,a as t}from"./chunks/framework.B6c1f-8R.js";const v=JSON.parse('{"title":"Iroha Special Instructions","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/instructions.md","filePath":"guide/blockchain/instructions.md","lastUpdated":1727242778000}'),n={name:"guide/blockchain/instructions.md"},o=a("",21),d=e("p",null,[t("Assets and permission tokens need to be minted to a specific account, usually the one that registered the asset in the first place. All assets are assumed to be non-negative as well, so you can never have "),e("span",{class:"katex"},[e("span",{class:"katex-mathml"},[e("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[e("semantics",null,[e("mrow",null,[e("mo",null,"−"),e("mn",null,"1.0")]),e("annotation",{encoding:"application/x-tex"},"-1.0")])])]),e("span",{class:"katex-html","aria-hidden":"true"},[e("span",{class:"base"},[e("span",{class:"strut",style:{height:"0.7278em","vertical-align":"-0.0833em"}}),e("span",{class:"mord"},"−"),e("span",{class:"mord"},"1.0")])])]),t(" of "),e("code",null,"time"),t(" or "),e("code",null,"Burn"),t(" a negative amount and get a "),e("code",null,"Mint"),t(".")],-1),c=a("",19),h=[o,d,c];function u(l,g,m,p,f,b){return s(),i("div",null,h)}const k=r(n,[["render",u]]);export{v as __pageData,k as default}; diff --git a/assets/guide_blockchain_metadata.md.Cmsp_0-E.js b/assets/guide_blockchain_metadata.md.Cmsp_0-E.js new file mode 100644 index 00000000..1e2f5137 --- /dev/null +++ b/assets/guide_blockchain_metadata.md.Cmsp_0-E.js @@ -0,0 +1,60 @@ +import{_ as a,E as n,c as t,J as h,V as s,o as e}from"./chunks/framework.B6c1f-8R.js";const A=JSON.parse('{"title":"Metadata","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/metadata.md","filePath":"guide/blockchain/metadata.md","lastUpdated":1727242778000}'),l={name:"guide/blockchain/metadata.md"},k=s('

Metadata

Metadata are key-value pairs that are attached to objects in the blockchain. The following can contain metadata:

  • domains
  • accounts
  • assets
  • asset definitions
  • triggers
  • transactions

The metadata can be of very different types, such as:

  • structures with named or unnamed fields
  • enums
  • integers
  • numbers with fixed decimal precision
  • strings
  • Boolean values
  • arrays
  • associative arrays
  • vectors
  • request results

The object's metadata can be transferred one by one, or in bulk via a WASM transaction. The Store asset type is used for working with metadata. Let's take a closer look at this asset type.

MetadataChanged

MetadataInserted or MetadataRemoved events are emitted when metadata is inserted or removed from accounts, domains, assets, or asset definitions. The emitted event also contains the data that was inserted or removed from the object. This data is stored in MetadataChanged in the form of a (key, value) pair.

',8),p=s(`

Check data filters for details.

Store Asset

In Iroha 2 there is an asset called Store that was designed to be a package of data. You can use Store when you require a storage of key-value pairs. The SetKeyValue and RemoveKeyValue instructions are used with the Store asset type. Here is an example of SetKeyValue instruction:

rust
// Mouse's account
+let mouse_id: AccountId = "mouse@wonderland".parse();
+
+// Registering \`Store\` asset definition
+let hat_definition_id: AssetDefinitionId =
+    "hat#wonderland".parse();
+let new_hat_definition = AssetDefinition::store(hat_definition_id);
+let register_hat = RegisterBox::new(new_hat_definition);
+
+let mouse_hat_id = AssetId::new(hat_definition_id, mouse_id);
+
+// New Iroha Special Instruction for setting key-value pairs for Mouse's hats:
+let set_hat_color = SetKeyValueBox::new(
+    mouse_hat_id,
+    Name::from_str("color"),
+    "yellow".to_owned(),
+);

Working with metadata

The following example showcases how to register and grant a role to access another account's metadata.

Example
rust
#[test]
+fn register_and_grant_role_for_metadata_access() -> Result<()> {
+    let (_rt, _peer, test_client) = <PeerBuilder>::new().start_with_runtime();
+    wait_for_genesis_committed(&vec![test_client.clone()], 0);
+
+    let alice_id = AccountId::from_str("alice@wonderland")?;
+    let mouse_id = AccountId::from_str("mouse@wonderland")?;
+
+    // Registering Mouse
+    let mouse_key_pair = KeyPair::generate()?;
+    let register_mouse = RegisterBox::new(Account::new(
+        mouse_id.clone(),
+        [mouse_key_pair.public_key().clone()],
+    ));
+    test_client.submit_blocking(register_mouse)?;
+
+    // Registering role
+    let role_id = <Role as Identifiable>::Id::from_str("ACCESS_TO_MOUSE_METADATA")?;
+    let role = iroha_data_model::role::Role::new(role_id.clone())
+        .add_permission(CanSetKeyValueInUserMetadata::new(mouse_id.clone()))
+        .add_permission(CanRemoveKeyValueInUserMetadata::new(mouse_id.clone()));
+    let register_role = RegisterBox::new(role);
+    test_client.submit_blocking(register_role)?;
+
+    // Mouse grants role to Alice
+    let grant_role = GrantBox::new(role_id.clone(), alice_id.clone());
+    let grant_role_tx = Transaction::new(mouse_id.clone(), vec![grant_role.into()].into(), 100_000)
+        .sign(mouse_key_pair)?;
+    test_client.submit_transaction_blocking(grant_role_tx)?;
+
+    // Alice modifies Mouse's metadata
+    let set_key_value = SetKeyValueBox::new(
+        mouse_id,
+        Name::from_str("key").expect("Valid"),
+        Value::String("value".to_owned()),
+    );
+    test_client.submit_blocking(set_key_value)?;
+
+    // Making request to find Alice's roles
+    let found_role_ids = test_client.request(client::role::by_account_id(alice_id))?;
+    assert!(found_role_ids.contains(&role_id));
+
+    Ok(())
+}

Queries

You can get the key value of an object metadata using queries:

Permissions

Pre-configured tokens in Iroha 2 that allow to set or remove key-values in accounts, assets, asset definitions, and so on are described in Permissions.

`,12);function d(r,E,g,o,y,F){const i=n("MermaidRenderWrap");return e(),t("div",null,[k,h(i,{id:"mermaid_2d3f0b7624b6a36380f036629a9452425dc05d6c4a61988862ccf28002cdef5ae656eb9b068819f89cb73fb8fd390d7e0965c8b8866f9ed83002216af5c6db75",text:"classDiagram%0A%0Adirection%20LR%0A%0Aclass%20MetadataChanged~ID~%20%7B%0A%20%20%20%20target_id%3A%20ID%0A%20%20%20%20key%3A%20Name%0A%20%20%20%20value%3A%20Box~Value~%0A%7D%0A%0Aclass%20AccountMetadataChanged~AccountId~%0Aclass%20AssetMetadataChanged~AssetId~%0Aclass%20AssetDefinitionMetadataChanged~AssetDefinitionId~%0Aclass%20DomainMetadataChanged~DomainId~%0A%0AMetadataChanged%20--%3E%20AccountMetadataChanged%0AMetadataChanged%20--%3E%20AssetMetadataChanged%0AMetadataChanged%20--%3E%20AssetDefinitionMetadataChanged%0AMetadataChanged%20--%3E%20DomainMetadataChanged"}),p])}const u=a(l,[["render",d]]);export{A as __pageData,u as default}; diff --git a/assets/guide_blockchain_metadata.md.Cmsp_0-E.lean.js b/assets/guide_blockchain_metadata.md.Cmsp_0-E.lean.js new file mode 100644 index 00000000..6a1a10ec --- /dev/null +++ b/assets/guide_blockchain_metadata.md.Cmsp_0-E.lean.js @@ -0,0 +1 @@ +import{_ as a,E as n,c as t,J as h,V as s,o as e}from"./chunks/framework.B6c1f-8R.js";const A=JSON.parse('{"title":"Metadata","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/metadata.md","filePath":"guide/blockchain/metadata.md","lastUpdated":1727242778000}'),l={name:"guide/blockchain/metadata.md"},k=s("",8),p=s("",12);function d(r,E,g,o,y,F){const i=n("MermaidRenderWrap");return e(),t("div",null,[k,h(i,{id:"mermaid_2d3f0b7624b6a36380f036629a9452425dc05d6c4a61988862ccf28002cdef5ae656eb9b068819f89cb73fb8fd390d7e0965c8b8866f9ed83002216af5c6db75",text:"classDiagram%0A%0Adirection%20LR%0A%0Aclass%20MetadataChanged~ID~%20%7B%0A%20%20%20%20target_id%3A%20ID%0A%20%20%20%20key%3A%20Name%0A%20%20%20%20value%3A%20Box~Value~%0A%7D%0A%0Aclass%20AccountMetadataChanged~AccountId~%0Aclass%20AssetMetadataChanged~AssetId~%0Aclass%20AssetDefinitionMetadataChanged~AssetDefinitionId~%0Aclass%20DomainMetadataChanged~DomainId~%0A%0AMetadataChanged%20--%3E%20AccountMetadataChanged%0AMetadataChanged%20--%3E%20AssetMetadataChanged%0AMetadataChanged%20--%3E%20AssetDefinitionMetadataChanged%0AMetadataChanged%20--%3E%20DomainMetadataChanged"}),p])}const u=a(l,[["render",d]]);export{A as __pageData,u as default}; diff --git a/assets/guide_blockchain_permissions.md.B5iiNWDU.js b/assets/guide_blockchain_permissions.md.B5iiNWDU.js new file mode 100644 index 00000000..84b823c9 --- /dev/null +++ b/assets/guide_blockchain_permissions.md.B5iiNWDU.js @@ -0,0 +1,15 @@ +import{_ as s,c as i,o as e,V as a}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Permissions","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/permissions.md","filePath":"guide/blockchain/permissions.md","lastUpdated":1727242778000}'),t={name:"guide/blockchain/permissions.md"},n=a(`

Permissions

Accounts need permission tokens for various actions on a blockchain, e.g. to mint or burn assets.

There is a difference between a public and a private blockchain in terms of permissions granted to users. In a public blockchain, most accounts have the same set of permissions. In a private blockchain, most accounts are assumed not to be able to do anything outside of their own account or domain unless explicitly granted said permission.

Having a permission to do something means having a PermissionToken to do so. There are two ways for users to receive permission tokens: they can be granted directly or as a part of a Role (a set of permission tokens). Permissions are granted via Grant special instruction. Permission tokens and roles do not expire, they can only be removed using Revoke instruction.

Permission Tokens

Permission token definitions have parameters. When a new permission token is registered, the names of the parameters and their types are checked against their names and types in the token definition. The token registration fails if there are too few parameters, if the parameter types don't match the definition, or parameters with unrecognised names.

Here are some examples of parameters used for various permission tokens:

  • A token that grants permission to change the values associated to keys in a Store asset needs the asset_definition_id parameter of type Id:

    json
      "params": {
    +     "asset_definition_id": "Id"
    +}
  • By contrast, the permission token that grants the permission to set keys to values in user metadata needs the account_id parameter of type Id:

    json
    "params": {
    +  "account_id": "Id"
    +}
  • The permission token that grants the permission to transfer assets only a fixed number of times per some time period, needs these two parameters:

    json
    "params": {
    +  "count": "U32",
    +  "period": "U128"
    +}

    Where the period is specified as a standard Duration since the UNIX epoch in milliseconds (more details about time in Rust).

Pre-configured Permission Tokens

You can find the list of pre-configured permission tokens in the Reference chapter.

Permission Groups (Roles)

A set of permissions is called a role. Similarly to permission tokens, roles can be granted using the Grant instruction and revoked using the Revoke instruction.

Before granting a role to an account, the role should be registered first.

Register a new role

Let's register a new role that, when granted, will allow another account access to the metadata in Mouse's account:

rust
let role_id = RoleId::from_str("ACCESS_TO_MOUSE_METADATA")?;
+let role = iroha_data_model::role::Role::new(role_id)
+    .add_permission(CanSetKeyValueInUserMetadata::new(mouse_id))
+    .add_permission(CanRemoveKeyValueInUserMetadata::new(mouse_id));
+let register_role = RegisterBox::new(role);

Grant a role

After the role is registered, Mouse can grant it to Alice:

rust
let grant_role = GrantBox::new(role_id, alice_id);
+let grant_role_tx =
+    Transaction::new(mouse_id, vec![grant_role.into()].into(), 100_000)
+    .sign(mouse_key_pair)?;

Permission Validators

Permissions exist so that only those accounts that have a required permission token to perform a certain action could do so.

The Judge trait is used to check permissions. The Judge decides whether a certain operation (instruction, query, or expression) could be performed based on the verdicts of multiple validators.

Each validator returns one of the following verdicts: Deny (with the exact reason to deny an operation), Skip (if an operation is not supported or has no meaning in a given context), or Allow.

There are several implementations of the Judge trait in Iroha 2, such as:

JudgeDescription
AtLeastOneAllowThe judge that succeeds only if there is at least one Allow verdict. The execution is stopped once there is a first Allow verdict.
NoDeniesThe judge that succeeds only if there is no Deny verdict. All validators are checked.
NoDeniesAndAtLeastOneAllowThe judge that succeeds only if there is no Deny verdict and at least one Allow verdict. The execution is stopped once there is a Deny verdict or all validators were checked.
AllowAllFor tests and simple cases. All operations are allowed to be executed for all possible values.
DenyAllFor tests and simple cases. All operations are disallowed to be executed for all possible for all possible values.

You can also build a custom permission validator by combining multiple validators, all of which should be of the same type (for checking instructions, queries, or expressions).

Runtime Validators

Currently Iroha 2 has only built-in validators. In the future, built-in validators will be completely replaced with runtime validators that use WASM.

The chain of runtime validators is used to validate operations that require permissions. It works similarly to the Chain of responsibility.

All runtime validators return validation verdict. By default, all operations are considered valid unless proven otherwise. Validators check whether or not an operation is not allowed: each validator either allows an operation and passes it to the following validator, or denies the operation. The validation stops at the first Deny verdict.

Supported Queries

Permission tokens and roles can be queried.

Queries for roles:

Queries for permission tokens:

`,36),o=[n];function r(l,h,d,p,k,c){return e(),i("div",null,o)}const m=s(t,[["render",r]]);export{g as __pageData,m as default}; diff --git a/assets/guide_blockchain_permissions.md.B5iiNWDU.lean.js b/assets/guide_blockchain_permissions.md.B5iiNWDU.lean.js new file mode 100644 index 00000000..247e37d0 --- /dev/null +++ b/assets/guide_blockchain_permissions.md.B5iiNWDU.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as e,V as a}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Permissions","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/permissions.md","filePath":"guide/blockchain/permissions.md","lastUpdated":1727242778000}'),t={name:"guide/blockchain/permissions.md"},n=a("",36),o=[n];function r(l,h,d,p,k,c){return e(),i("div",null,o)}const m=s(t,[["render",r]]);export{g as __pageData,m as default}; diff --git a/assets/guide_blockchain_queries.md.CKZBqEyL.js b/assets/guide_blockchain_queries.md.CKZBqEyL.js new file mode 100644 index 00000000..1f88e627 --- /dev/null +++ b/assets/guide_blockchain_queries.md.CKZBqEyL.js @@ -0,0 +1,7 @@ +import{c as i,o as s,V as a}from"./chunks/framework.B6c1f-8R.js";const e=a(`

Queries

Although much of the information about the state of the blockchain can be obtained, as we've shown before, using an event subscriber and a filter to narrow the scope of the events to those of interest, sometimes you need to take a more direct approach. Enter queries.

Queries are small instruction-like objects that, when sent to an Iroha peer, prompt a response with details from the current world state view.

This is not necessarily the only kind of information that is available on the network, but it's the only kind of information that is guaranteed to be accessible on all networks.

For each deployment of Iroha, there might be other available information. For example, the availability of telemetry data is up to the network administrators. It's entirely their decision whether or not they want to allocate processing power to track the work instead of using it to do the actual work. By contrast, some functions are always required, e.g. having access to your account balance.

The results of queries can be sorted, paginated and filtered peer-side all at once. Sorting is done lexicographically on metadata keys. Filtering can be done on a variety of principles, from domain-specific (individual IP address filter masks) to sub-string methods like begins_with combined using logical operations.

Create a query

Use QueryBox to construct a query. For example, a query to find all accounts would be created like this:

rust
let query = QueryBox::FindAllAccounts(FindAllAccounts {});

Here is an example of a query that finds Alice's assets:

rust
let alice_id =
+    AccountId::from_str("alice@wonderland")?;
+let query = QueryBox::FindAssetsByAccountId(
+    FindAssetsByAccountId::new(alice_id)
+  );

Pagination

For both a Vec<Z> and just Z as the return type, you can use client.request(query) to submit a query and get the full result in one go.

However, some queries, particularly the ones with "All" in their names, can return exorbitant amounts of data. As such, we highly recommend you consider pagination to reduce the load on the system.

To construct a Pagination, you need to call client.request_with_pagination(query, pagination), where the pagination is constructed as follows:

rust
let starting_result: u32 = _;
+let limit: u32 = _;
+let pagination = Pagination::new(Some(starting_result), Some(limit));

Filters

When you create a query, you can use a filter to only return the results that match the specified filter.

Sorting

Iroha 2 can sort items with metadata lexicographically if you provide a key to sort by during the construction of the query. A typical use case is for accounts to have a registered-on metadata entry, which, when sorted, allows you to view the account registration history.

Sorting only applies to entities that have metadata, as the metadata key is used to sort query results.

You can combine sorting with pagination and filters. Note that sorting is an optional feature, most queries with pagination won't need it.

Reference

Check the list of existing queries for detailed information about them.

`,24),t=[e],p=JSON.parse('{"title":"Queries","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/queries.md","filePath":"guide/blockchain/queries.md","lastUpdated":1727242778000}'),n={name:"guide/blockchain/queries.md"},d=Object.assign(n,{setup(h){return(r,l)=>(s(),i("div",null,t))}});export{p as __pageData,d as default}; diff --git a/assets/guide_blockchain_queries.md.CKZBqEyL.lean.js b/assets/guide_blockchain_queries.md.CKZBqEyL.lean.js new file mode 100644 index 00000000..df162e23 --- /dev/null +++ b/assets/guide_blockchain_queries.md.CKZBqEyL.lean.js @@ -0,0 +1 @@ +import{c as i,o as s,V as a}from"./chunks/framework.B6c1f-8R.js";const e=a("",24),t=[e],p=JSON.parse('{"title":"Queries","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/queries.md","filePath":"guide/blockchain/queries.md","lastUpdated":1727242778000}'),n={name:"guide/blockchain/queries.md"},d=Object.assign(n,{setup(h){return(r,l)=>(s(),i("div",null,t))}});export{p as __pageData,d as default}; diff --git a/assets/guide_blockchain_transactions.md.BW0UeSYo.js b/assets/guide_blockchain_transactions.md.BW0UeSYo.js new file mode 100644 index 00000000..47458c0e --- /dev/null +++ b/assets/guide_blockchain_transactions.md.BW0UeSYo.js @@ -0,0 +1,4 @@ +import{_ as s,c as i,o as a,V as t}from"./chunks/framework.B6c1f-8R.js";const E=JSON.parse('{"title":"Transactions","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/transactions.md","filePath":"guide/blockchain/transactions.md","lastUpdated":1727242778000}'),n={name:"guide/blockchain/transactions.md"},e=t(`

Transactions

A transaction is a collection of instructions. The instructions within a transaction can be executed in a sequence or compiled into a WASM blob.

All interactions in the blockchain are done via transactions.

All transactions, including rejected transactions, are stored in blocks.

Here is an example of creating a new transaction with the Grant instruction. In this transaction, Mouse is granting Alice the specified role (role_id). Check the full example.

rust
let grant_role = GrantBox::new(role_id, alice_id);
+let grant_role_tx =
+    Transaction::new(mouse_id, vec![grant_role.into()].into(), 100_000)
+    .sign(mouse_key_pair)?;
`,6),h=[e];function l(r,p,k,o,c,d){return a(),i("div",null,h)}const _=s(n,[["render",l]]);export{E as __pageData,_ as default}; diff --git a/assets/guide_blockchain_transactions.md.BW0UeSYo.lean.js b/assets/guide_blockchain_transactions.md.BW0UeSYo.lean.js new file mode 100644 index 00000000..556b9568 --- /dev/null +++ b/assets/guide_blockchain_transactions.md.BW0UeSYo.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,V as t}from"./chunks/framework.B6c1f-8R.js";const E=JSON.parse('{"title":"Transactions","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/transactions.md","filePath":"guide/blockchain/transactions.md","lastUpdated":1727242778000}'),n={name:"guide/blockchain/transactions.md"},e=t("",6),h=[e];function l(r,p,k,o,c,d){return a(),i("div",null,h)}const _=s(n,[["render",l]]);export{E as __pageData,_ as default}; diff --git a/assets/guide_blockchain_triggers.md.BTamJcLJ.js b/assets/guide_blockchain_triggers.md.BTamJcLJ.js new file mode 100644 index 00000000..2f1af86d --- /dev/null +++ b/assets/guide_blockchain_triggers.md.BTamJcLJ.js @@ -0,0 +1,34 @@ +import{_ as e,E as a,c as t,J as n,V as i,o as h}from"./chunks/framework.B6c1f-8R.js";const F=JSON.parse('{"title":"Triggers","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/triggers.md","filePath":"guide/blockchain/triggers.md","lastUpdated":1727242778000}'),l={name:"guide/blockchain/triggers.md"},r=i('

Triggers

Certain things, such as changing the state of an entity, committing a block or executing an Iroha Special Instruction (ISI), can emit events, and you can attach triggers to these events.

A trigger is a fairly basic entity that can be registered. Just like with Accounts, to register a trigger, you submit a RegisterBox::Trigger, which contains the necessary information:

  • an account ID, which should ideally be a brand new account that you register in the same transaction
  • an executable, which itself is either a Vec<Instruction> or a WASM blob
  • an EventFilter[1], which is something that combs through all[2] events and returns true when it finds the matching event to start the execution

Let's take a closer look at how triggers work.

The Anatomy of a Trigger

A trigger has roughly the following form:

rust
struct Trigger {\n  id: TriggerId,\n  action: Action,\n}

Trigger.id

The TriggerId is a simple wrapper around a single Name, a string with no whitespaces and no reserved characters (@, #, $).

A typical domain-scoped trigger looks like trigger_id$domain_name, while a bare trigger looks like @@trigger_id, which makes these names easy to parse.

Trigger.action

An Action is the heart of the trigger. It is defined like this:

rust
struct Action {\n  executable: Executable,\n  repeats: Repeats,\n  technical_account: AccountId,\n  filter: EventFilter,\n  metadata: Metadata,\n}

Action.executable

The executable linked to this action, either a Vec<Instruction> or a WASM binary.

Action.repeats

The Repeats is a universal enumeration of all possible repetition schemes.

rust
enum Repeats {\n  Indefinitely,\n  Exactly(u32),\n}

Action.technical_account

A technical account is the account that would (in theory) be responsible for the execution environment and be the authority for Instruction execution.

For now, you can leave this as the account that registered the trigger. If you have been following the tutorial, this is alice@wonderland. However, later on we will show you why you'd want to create a brand new account for those purposes.

INFO

Note that you can only use the account that already exists in order to be able to register a new trigger.

Action.filter

A filter is what determines what kind of trigger you're dealing with. All triggers respond to events, but the precise type of event that activates a trigger depends on which EventFilter was used.

The reason why we chose this architecture is simple; front end code has an abundance of event filters, and so, your knowledge of filters is transferable to writing smart contracts.

Action.metadata

This Metadata is the same kind of Metadata that can be attached to accounts, domains, assets, or transactions. This is the storage for trigger data.

You can learn more about metadata in a dedicated section.

How Triggers Work

As we already said, the filter that is used to register a trigger determines what kind of trigger this is. It is, of course, also determines how the trigger works, e.g. when it is executed. We will go into more details about the types of triggers in just a moment.

First, we shall point out that there two other characteristics of a trigger that determine how this trigger works: its scope and repetition schema.

Scope

Triggers can be scoped and un-scoped. Iroha supports both un-scoped system-wide triggers as well as domain-scoped triggers. Since system-wide triggers scan all events, and domain-scoped triggers only scan events emitted in a certain domain, it is highly recommended to use domain-scoped triggers where possible.

INFO

Be mindful of the limitations. Currently triggers don't check for permissions , so they can do things your account wouldn't be allowed to. Un-scoped triggers process every event, and the amount of work grows quadratically.

Domain-scoped Triggers

While un-scoped triggers check all events of a specified type, domain-scoped triggers only look for events in a given domain. These triggers are more optimised compared to un-scoped triggers.

You can use FindTriggersByDomainId query to find triggers for the given domain.

When you register a domain-scoped trigger, you need to add the domain id to the trigger id using $ symbol: my_trigger$my_domain.

Repetition Schema

Each such trigger can be set to repeat either Indefinitely or Exactly(n) times, where n is a 32-bit integer. Once the number of repetitions reaches zero, the trigger is gone. That means that if your trigger got repeated exactly n times, you can't Mint new repetitions, you have to Register it again, with the same name.

After a trigger is repeated for the last time, i.e. the execution count reaches 0, the trigger should be un-registered.

Types of Triggers

We shall cover the following basic types of triggers and provide you with the detailed information on how to use each of them:

All triggers are essentially event triggers. The type of a trigger is determined by the type of an event that trigger is associated with. This, in turn, is determined by the filter used to register a trigger.

',46),p=i(`

Data Triggers

This category includes the largest variety of triggers. The events that are associated with this trigger type account for the vast majority of events in Ethereum. These are data-related events, such as: an account got registered, an asset got transferred, the Queen of Hearts decided to burn all of her assets.

Time Triggers

Time triggers behave slightly differently compared to data triggers. There are two sub-types of this type: scheduled triggers and pre-commit triggers.

Instead of processing all the events generated by normal transactions, all time triggers process one event: the block formation event.

The filters of scheduled triggers are only interested in the timestamp provided in that event, but not the block height, and not the current time. They are executed according to a certain schedule. Pre-commit triggers, on the other hand, are executed right before a block is committed.

Scheduled Triggers

When going through consensus, all peers must agree on which triggers got executed. Scheduled triggers can't use real time, because then you can easily create a situation when they would never agree: e.g. by giving the Repeats::Indefinitely trigger a period that is smaller than the time it takes to pass consensus. It's really that simple.

So instead of using the actual current time at each peer, we use the time when the block got started plus a small offset. All triggers before that point in time get executed. All triggers that would be executed after that time wait for the next block.

Why we use the offset

The reason why we add this offset has to do with Iroha being best effort.

Imagine if we didn't have the offset... Normally, triggers would be set to nice round numbers; e.g. 12:00, 12:05, 11:55, etc. (as opposed to e.g. 11:59). However, the consensus can start at any point in time and could last a while.

Suppose that the block started to form at 11:56 and consensus finished at 12:03 (which is optimistically quick). Let's consider different scenarios:

  • If your trigger was supposed to run at 11:55, you'd be happy, since your trigger got executed just 1 minute late.
  • If your trigger was supposed to run at 12:05, it will run in the next block, not the one that was formed at 11:56. If you're the author and you're looking at the time stamp of 12:03, it makes sense, your trigger wasn't supposed to run yet.
  • For the trigger scheduled for 12:00, the situation is different. You look at the clock, you see 12:03, which is when the blockchain explorer shows you the block data was committed, but you don't see your trigger. It was supposed to run, but didn't.

So, the offset is meant to anticipate when the block would get added to the chain, so that people who were just 4 minutes early don't have to be potentially several hours late.

Because more triggers get executed sooner, your throughput is also infinitesimally smaller.

We could also say "you should aim to execute your trigger slightly earlier than consensus starts", but people writing smart contracts already have too much to worry about.

Pre-commit Triggers

This is a variant of timed triggers that gets run before blocks with transactions get committed. It leaves a special event to be triggered in the next block. Effectively, it's a delayed pre-commit that can track the behaviour of transactions in the pipeline.

INFO

These triggers are not meant for restricting the execution of transactions.

If you want to stop your users from transferring more than X amount of Y to user Z, you really want a permission. While you could hack the pre-commit triggers to emulate the desired behaviour, this is not economical neither in terms of gas fees nor computation.

Until Iroha 2 supports WASM-based permissions validators, however, your only choice is pre-commit triggers.

By-call Triggers

These triggers only get executed once the CallTrigger(trigger_name) instruction is executed. They can be useful if you want to achieve dynamic linkage between different smart contract modules.

Space is precious, so you want to use as little of it as you can. Thus, you follow the UNIX design philosophy, and instead of creating one large smart contract, you create many smaller ones, and re-use as much logic as you can.

INFO

Of course, this is a rather exotic use case, so it shall be implemented last.

Event Triggers by Example

Now that we've gotten the theory out of the way, we want to sit down with the Mad Hatter, the March Hare, and the Dormouse and see if we can spin. Let's start with an event trigger that shows the basics.

1. Register accounts

We have mad_hatter@wonderland, dormouse@wonderland, march_hare@wonderland all of which share the fixed-point asset of tea#wonderland. The Mad Hatter has the tea pot, while the rest have a single cup of tea. When alice@wonderland had arrived, she got a nice cup of tea as well.

The way we get them in Rust code looks like this:

rust
let tea = AssetDefinitionId::new("tea", "wonderland")?;
+let mad_hatter = AccountId::new("mad_hatter", "wonderland")?;
+let dormouse = AccountId::new("dormouse", "wonderland")?;
+let march_hare = AccountId::new("march_hare", "wonderland")?;
+vec![
+  RegisterBox::new(IdentifiableBox::from(NewAccount::new(mad_hatter.clone()))),
+  RegisterBox::new(IdentifiableBox::from(NewAccount::new(march_hare.clone()))),
+  RegisterBox::new(IdentifiableBox::from(NewAccount::new(dormouse.clone()))),
+  RegisterBox::new(IdentifiableBox::from(AssetDefinition::new_fixed(tea.clone()))),
+  MintBox::new(Value::Fixed(100.0_f64.try_into()?), IdBox::AssetId(AssetId::new(tea.clone(), mad_hatter.clone())))
+  MintBox::new(Value::Fixed(1.0_f64.try_into()?), IdBox::AssetId(AssetId::new(tea.clone(), march_hare.clone())))
+  MintBox::new(Value::Fixed(1.0_f64.try_into()?), IdBox::AssetId(AssetId::new(tea.clone(), dormouse.clone())))
+  MintBox::new(Value::Fixed(1.0_f64.try_into()?), IdBox::AssetId(AssetId::new(tea.clone(), alice.clone())))
+]

2. Register a trigger

We want a smart contract that transfers some tea from mad_hatter@wonderland to alice@wonderland when her tea reduces by a single cup.

For that we need to register a trigger. The boilerplate is straightforward:

rust
let id = TriggerId::new(Name::new("refresh_tea"));
+
+let metadata = Metadata::new();
+
+let executable = vec![
+    TransferBox::new(
+      IdBox::AssetId(AssetId::new(tea.clone(), mad_hatter.clone())),
+      Value::Fixed(1_f64.try_into()?),
+      IdBox::AssetId(AssetId::new(alice.clone(), mad_hatter.clone())),
+    )
+];
+
+let repeats = Repeats::Indefinitely;
+
+let technical_account = mad_hatter.clone();
+
+let filter = _ // ...

3. Define an event filter

The event filter is where we need to spend some time and think. So far we've seen the Pipeline variety of filters. This time around, the filter is a Data kind. This type of filter is a tuple with a single variant, which is a FilterOpt of an EntityFilter:

  • FilterOpt stands for Optional Filter. It can either AcceptAll or accept BySome of another Filter.
  • An EntityFilter is a filter that matches ByAccount in our case, but can match by many other means. It wraps an AccountFilter, which matches various events produced on accounts.

What we want to do is create an event filter for when alice@wonderland drinks some of her tea, or, in other words, reduces the tea asset by any amount. To do this with the current API, we need to work bottom up.

An IdFilter is a filter that .matches(event) == true if and only if the identities are exactly the same. Everything that has an Id has a corresponding IdFilter.

INFO

An IdFilter is a parametric structure, an IdFilter that works on Peers has the type IdFilter<PeerId> and is not the same type as an IdFilter that works with AccountId; IdFilter<AccountId.

Now if we wanted a filter that will match whenever tea gets reduced, either through a Transfer or a Burn instruction, we need an AssetFilter. It needs to look at what the Id of the asset is, hence IdFilter<AssetDefinitionId> and ByRemoved.

rust
use FilterOpt::{BySome, AcceptAll};
+
+let asset_filter = AssetFilter::new(BySome(IdFilter(tea.clone())), BySome(AssetEventFilter::ByRemoved));

So far so good?

Next, we want a filter that looks for changes in an asset for an account. Specifically:

rust
let account_filter = AccountFilter::new(BySome(IdFilter(alice.clone())), BySome(asset_filter));

Now, because of the way that parity_scale_codec works, we need to wrap this in various boxes.

rust
let filter = EventFilter::Data(BySome(EntityFilter::ByAccount(account_filter)));

4. Create a Trigger instance

After this somewhat laborious filter combination, we can create an Action

rust
let action = Action {
+    executable, repeats, technical_account, filter, metadata
+}

Which allows us to create an instance of a Trigger.

rust
let trigger = Trigger::new(id, action);

5. Create a transaction

Finally, in order to get said trigger onto the blockchain, we create a transaction with the following single instruction:

rust
Instruction::Register(RegisterBox::new(IdentifiableBox::Trigger(Box::new(trigger))));

How it works

The technical details of the created transaction are summarised as follows:

  • The (normal) instructions that either got submitted from WASM or directly from the client get executed. If there were any triggers that should have been registered, they get registered.
  • Using the total set of events that got generated during the execution of instructions, the triggers (including some that got registered just this round) get executed.
  • The events produced in the previous step get scheduled for execution in the next block.

INFO

The reason why the events caused by the execution of triggers get processed in the next block is that we don't want two triggers to inadvertently cause an infinite loop of instruction execution and break consensus.

Now each time Alice drinks some tea, the Mad Hatter pours in a whole new cup. The keen eyed among you will have noticed that the amount that Alice drinks is irrelevant to how much tea will be transferred. Alice may take a tiny sip and still be poured a whole new cup's worth.

INFO

We intend to address this issue in the future so that an emitted event also has an attached Value. We also intend to provide more event filter types. For example, we will have filters that match when the asset:

  • Decreases by any amount (current behaviour)
  • Decreases by more than (or exactly) the specific amount in one instruction
  • Decreases to below a certain threshold

Only the first type of event filter is implemented now, and the other two can be emulated using a WASM smart contract as the Executable.

Why not WASM

The above observation can be generalised. WASM can do any logic that a Turing complete machine could, using the data available via queries. So in theory for event-based triggers, you could create an AcceptAll event filter and do all of the processing using the key-value store as persistent storage, and then, determining if you want to execute using easy-to-understand Rust code, and not our admittedly cumbersome, EventFilters.

We don't want that. WASM takes up significantly more space, and takes longer to execute compared to plain ISI, which are slower than EventFilters. We want you to want to use the EventFilters because they would make the process much more efficient, and we are working tirelessly to make the experience of using event filters much less gruelling.

However, as was mentioned previously on several occasions, implementing a feature properly takes time and effort. Ergonomics must be balanced against safety and reliability, so we cannot just make things easier to use. We want them to retain many of the advantages of strong typing.

This is all a work in progress. Our code is in flux. We need time to play around with a particular implementation to optimise it.

Supported ISI

All Iroha Special Instructions work with triggers, specifically:

  • Register<Trigger>: Create a trigger object and subscribe it to global events.

  • Unregister<Trigger>: Remove a trigger from the World State View and stop passing events through it.

  • Mint<Trigger, u32>: For triggers that repeat a certain number of times, increase the number of times that the trigger gets executed. Can be done from inside the executable of the trigger.

  • Burn<Trigger, u32>: For triggers that repeat a certain number of times, decrease the number of times that the trigger gets executed.

    WARNING

    If the number provided is greater than the remaining number of repetitions, the instruction will fail to execute, and the transaction that it is part of will be rejected.

You can learn more about Iroha Special Instructions in the dedicated section.

Supported Queries

We list supported queries for triggers when we talk in more detail about queries in the next chapter.


  1. The documentation on the EventFilter types is under construction, as we are likely to make major changes to that particular architecture. For now, suffice it to say that you can look at the source code in iroha_data_model and see a few particularly interesting applications. ↩︎

  2. This behaviour is likely to change in future releases.

    ↩︎
`,63);function o(k,d,c,g,y,E){const s=a("MermaidRenderWrap");return h(),t("div",null,[r,n(s,{id:"mermaid_79eaa517dfee336607034fec2fd701367be409be118356c9efd26a71dab658d37df3c8bb95a16a92b1cabc6118ec2e6ba2fda13bc753c4dd54aeaee6076b6256",text:"classDiagram%0A%0Aclass%20Trigger~F%3A%20Filter~%0A%0Aclass%20time_trigger~TimeEventFilter~%0Aclass%20data_trigger~DataEventFilter~%0Aclass%20by_call_trigger~ExecuteTriggerEventFilter~%0Aclass%20pipeline_trigger~PipelineEventFilter~%0A%0Aclass%20precommit_trigger~TimeEventFilter(ExecutionTime%3A%3APreCommit)~%0Aclass%20scheduled_trigger~TimeEventFilter(ExecutionTime%3A%3ASchedule(schedule))~%0A%0ATrigger%20--%3E%20time_trigger%0ATrigger%20--%3E%20by_call_trigger%0ATrigger%20--%3E%20data_trigger%0ATrigger%20--%3E%20pipeline_trigger%0A%0Atime_trigger%20--%3E%20precommit_trigger%20%0Atime_trigger%20--%3E%20scheduled_trigger"}),p])}const m=e(l,[["render",o]]);export{F as __pageData,m as default}; diff --git a/assets/guide_blockchain_triggers.md.BTamJcLJ.lean.js b/assets/guide_blockchain_triggers.md.BTamJcLJ.lean.js new file mode 100644 index 00000000..e177d89a --- /dev/null +++ b/assets/guide_blockchain_triggers.md.BTamJcLJ.lean.js @@ -0,0 +1 @@ +import{_ as e,E as a,c as t,J as n,V as i,o as h}from"./chunks/framework.B6c1f-8R.js";const F=JSON.parse('{"title":"Triggers","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/triggers.md","filePath":"guide/blockchain/triggers.md","lastUpdated":1727242778000}'),l={name:"guide/blockchain/triggers.md"},r=i("",46),p=i("",63);function o(k,d,c,g,y,E){const s=a("MermaidRenderWrap");return h(),t("div",null,[r,n(s,{id:"mermaid_79eaa517dfee336607034fec2fd701367be409be118356c9efd26a71dab658d37df3c8bb95a16a92b1cabc6118ec2e6ba2fda13bc753c4dd54aeaee6076b6256",text:"classDiagram%0A%0Aclass%20Trigger~F%3A%20Filter~%0A%0Aclass%20time_trigger~TimeEventFilter~%0Aclass%20data_trigger~DataEventFilter~%0Aclass%20by_call_trigger~ExecuteTriggerEventFilter~%0Aclass%20pipeline_trigger~PipelineEventFilter~%0A%0Aclass%20precommit_trigger~TimeEventFilter(ExecutionTime%3A%3APreCommit)~%0Aclass%20scheduled_trigger~TimeEventFilter(ExecutionTime%3A%3ASchedule(schedule))~%0A%0ATrigger%20--%3E%20time_trigger%0ATrigger%20--%3E%20by_call_trigger%0ATrigger%20--%3E%20data_trigger%0ATrigger%20--%3E%20pipeline_trigger%0A%0Atime_trigger%20--%3E%20precommit_trigger%20%0Atime_trigger%20--%3E%20scheduled_trigger"}),p])}const m=e(l,[["render",o]]);export{F as __pageData,m as default}; diff --git a/assets/guide_blockchain_wasm.md.qnYECiWT.js b/assets/guide_blockchain_wasm.md.qnYECiWT.js new file mode 100644 index 00000000..270aa51a --- /dev/null +++ b/assets/guide_blockchain_wasm.md.qnYECiWT.js @@ -0,0 +1,37 @@ +import{_ as s,c as i,o as a,V as e}from"./chunks/framework.B6c1f-8R.js";const u=JSON.parse('{"title":"WASM","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/wasm.md","filePath":"guide/blockchain/wasm.md","lastUpdated":1727242778000}'),t={name:"guide/blockchain/wasm.md"},n=e(`

WASM

While we had initially assumed that all operations within Iroha will be handled with instructions and conditionals, however, there are a few problems with this approach.

  • The ISI syntax is verbose and ugly.
  • The ISI syntax is not familiar for most programmers.
  • While simple ISI smart contracts are compact (usually a few bytes), they need different kinds of manual optimisations.

In the long run, all of these problems are taken care of by using a domain-specific language, which gets optimised and compiled into a sequence of instructions that executes fast and takes very little space in the blocks, but is also easy to understand. Something that looks like your traditional if statements and for loops.

However, in the interim, we have decided to use another portable binary standard called Web assembly, or WASM.

Working with WASM

The main advantage of using the WASM format is that you can use any language you like (as long as it links statically against our helper library), and produce a 32-bit portable executable. The compilers take care of the optimisation, and you don't have to learn a new language (ahem... solidity... ahem), just to operate on the blockchain.

You'd still need to use ISI from inside your WASM binary to do anything on-chain, as we explained earlier.

In theory, you can do anything you want just using ISI as it is a Turing-complete language. However, it'll be less convenient and efficient since you'd need to use metadata as memory and write complex conditionals using just the tools that we've provided in the Expression and ISI infrastructure. We highly recommend choosing a well-known programming language, such as Rust, to build the necessary logic out of simple instructions. This is much easier than trying to reinvent the wheel using ISI.

Moreover, as long as you fit within the limits of WASM runtime and the provided libraries, you can do anything (and everything) you want. The drawback is that this process is a tad more involved than just writing the ISI using the client libraries.

Simple Rust Smart Contract Example

WASM projects, just like any other binary in Rust, need to be separate crates. Don't worry, it doesn't have to be big.

1. Create a new project

To get started, create a new project:

bash
$ cargo new --lib

Yes! We need the lib type; more on that later.

The Cargo.toml of your project should look something like this:

toml
[package]
+name  = "smartcontract"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+crate-type = ['cdylib']
+
+[dependencies]
+iroha_wasm = { git = "https://github.com/hyperledger/iroha/"}

Note that the crate type is cdylib. Most Rust code is linked in a non-portable architecture and OS-specific static manner, but WASM is a portable format. Since C ABI is the lingua franca of the programming world and there is no other stable Rust ABI (yet), Iroha relies on the C-linkage to generate WASM bindings. Thankfully, iroha_wasm takes care of everything related to foreign function interfaces (FFI), so you don't have to worry about things like unsafe, repr(C), padding, alignment, and others.

The iroha_wasm crate contains all of the bindings, macros, and trait implementations that you'd need to write the program, most notably the iroha_wasm attribute macro. The crate also exposes our data_model, which contains all of the basic ISI and types. The chosen serialisation format is parity-scale-codec, though there is a strong possibility it'll get replaced with a different (custom) serialisation format in the near future, as it seems to dominate the binary size[1].

2. Write a smart contract

Now that we have the preliminaries nailed down, we get to write some code for our smart contract. In the src/lib.rs you should write the following:

rust
#![no_std]
+#![no_main]
+
+extern crate alloc;
+
+use alloc::vec::Vec;
+
+use iroha_wasm::data_model::prelude::*;
+
+#[iroha_wasm::iroha_wasm]
+fn smartcontract_entry_point(_account_id: AccountId) {
+    let query = QueryBox::FindAllDomains(FindAllDomains {});
+    let domains: Vec<Domain> = query.execute().try_into().unwrap();
+
+    for domain in domains {
+        let new_account_id = AccountId {
+            name: Name::new("mad_hatter").unwrap(),
+            domain_id: domain.id,
+        };
+
+        Instruction::Register(RegisterBox::new(NewAccount::new(new_account_id))).execute();
+    }
+}

To submit the instruction and run it, execute the following command (be sure to have a peer up):

cargo run --release

What does this smart contract do? Let's see. It queries all of the currently existing domains and puts the results into a std::vec::Vec. In this case, std::vec::Vec has to be imported from alloc, as we use no_std (more on that later). It is then used to add the user named mad_hatter to all of the existing domains.

Building the same logic out of Expression and If and Sequence would be significantly harder. Moreover, the actual low-level instructions that would run are very likely not going to be as well-optimised as what the compiler produces.

Advanced Smart Contracts: Optimising for Size

WASM smart contracts can get big. So big, in fact, that we might not let you store them in the blockchain. So how do you reduce the size? The most important modifications are done in Cargo.toml:

toml
[profile.release]
+strip = "debuginfo" # Remove debugging info from the binary
+panic = "abort"     # Abort panics as they are transcribed to Traps when compiling for WASM anyways
+lto = true          # Use link-time-optimisation (it produces a notable decrease in binary size)
+opt-level = "z"     # Optimise for size vs speed with "s"/"z"(removes vectorization)
+codegen-units = 1   # Use one code generation unit (it further reduces the binary size but increases compilation time)

Let's take a closer look at what you can do to reduce the size of the WASM binary.

Remove debugging info

Rust stores a lot of debug information (even when compiled in release mode), which is (as the name suggests) used for debugging a panic in your Rust application. As you would expect, this information increases the size of the compiled WASM significantly.

Normally, this would be a worthwhile trade-off, but not in our case. Firstly, since the WASM is stored on-chain, it will be permanently recorded in some block and take space on every full node of an Iroha network. Iroha stores a lot of its information in RAM, so storage space for WASM is at a premium.

Secondly, once the WASM smart contract is stored on-chain, the debug information is no longer accessible. Indeed, you shouldn't debug on a peer. Instead, you should replicate the conditions that caused the panic locally and debug on your personal machine.

Work under a no_std environment

Another step that we've already taken involves working under a no_std environment. All of our size-related woes stem from Rust being predominantly statically linked. As such, breaking the standard library into more manageable crates, like using alloc::vec instead of std::vec, can help us reduce the size and compilation time[2].

Re-compile libcore

Next, you're advised to re-compile libcore and any other standard library crate (e.g. alloc) to exclude the leftover panic-related code that comes with the prebuilt core library[3]:

bash
$ cargo +nightly build -Z build-std -Z build-std-features=panic_immediate_abort --target wasm32-unknown-unknown

Unfortunately, this is an unstable feature. In other words, the developers of the Rust programming language can decide to change how this works, or remove this option entirely.

Use tools to optimise WASM size

Finally, you can use an automated tool to optimise the size of the WASM binary. You could use wasm-opt or twiggy to guide your manual optimisation efforts.

We highly advise using wasm-opt because it will often significantly reduce your binary size:

bash
$ wasm-opt -Os -o output.wasm input.wasm

Conclusion

At some point, unfortunately, the smallest size of your WASM blob is going to be determined by the libraries that you need to use. Using all of the above steps on the provided smart contract can reduce it down to a manageable (for the blockchain) size.


  1. Size is an important metric. We shall cover size-optimisation strategies as we go. ↩︎

  2. It should be noted that excluding the standard library is necessary for compiling to the wasm32 target, and is thus mandatory. ↩︎

  3. wasm-opt can also be used to remove the debug sections. ↩︎

`,49),o=[n];function l(h,r,p,d,k,c){return a(),i("div",null,o)}const y=s(t,[["render",l]]);export{u as __pageData,y as default}; diff --git a/assets/guide_blockchain_wasm.md.qnYECiWT.lean.js b/assets/guide_blockchain_wasm.md.qnYECiWT.lean.js new file mode 100644 index 00000000..4c8011f4 --- /dev/null +++ b/assets/guide_blockchain_wasm.md.qnYECiWT.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,V as e}from"./chunks/framework.B6c1f-8R.js";const u=JSON.parse('{"title":"WASM","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/wasm.md","filePath":"guide/blockchain/wasm.md","lastUpdated":1727242778000}'),t={name:"guide/blockchain/wasm.md"},n=e("",49),o=[n];function l(h,r,p,d,k,c){return a(),i("div",null,o)}const y=s(t,[["render",l]]);export{u as __pageData,y as default}; diff --git a/assets/guide_blockchain_world.md.1jfOivt1.js b/assets/guide_blockchain_world.md.1jfOivt1.js new file mode 100644 index 00000000..098895fc --- /dev/null +++ b/assets/guide_blockchain_world.md.1jfOivt1.js @@ -0,0 +1 @@ +import{_ as e,c as i,o as r,V as o}from"./chunks/framework.B6c1f-8R.js";const f=JSON.parse('{"title":"World","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/world.md","filePath":"guide/blockchain/world.md","lastUpdated":1727242778000}'),t={name:"guide/blockchain/world.md"},a=o('

World

World is the global entity that contains other entities. The World consists of:

When domains, peers, or roles are registered or unregistered, the World is the target of the (un)register instruction.

World State View (WSV)

World State View is the in-memory representation of the current blockchain state. This includes all currently loaded blocks, with all of their contents, as well as peers elected for the current epoch.

',6),s=[a];function l(n,d,c,h,u,p){return r(),i("div",null,s)}const g=e(t,[["render",l]]);export{f as __pageData,g as default}; diff --git a/assets/guide_blockchain_world.md.1jfOivt1.lean.js b/assets/guide_blockchain_world.md.1jfOivt1.lean.js new file mode 100644 index 00000000..8dddfa7c --- /dev/null +++ b/assets/guide_blockchain_world.md.1jfOivt1.lean.js @@ -0,0 +1 @@ +import{_ as e,c as i,o as r,V as o}from"./chunks/framework.B6c1f-8R.js";const f=JSON.parse('{"title":"World","description":"","frontmatter":{},"headers":[],"relativePath":"guide/blockchain/world.md","filePath":"guide/blockchain/world.md","lastUpdated":1727242778000}'),t={name:"guide/blockchain/world.md"},a=o("",6),s=[a];function l(n,d,c,h,u,p){return r(),i("div",null,s)}const g=e(t,[["render",l]]);export{f as __pageData,g as default}; diff --git a/assets/guide_configure_client-configuration.md.22mv4OvP.js b/assets/guide_configure_client-configuration.md.22mv4OvP.js new file mode 100644 index 00000000..8e5df7cc --- /dev/null +++ b/assets/guide_configure_client-configuration.md.22mv4OvP.js @@ -0,0 +1,26 @@ +import{_ as s,c as a,o as i,V as e}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Client Configuration","description":"","frontmatter":{},"headers":[],"relativePath":"guide/configure/client-configuration.md","filePath":"guide/configure/client-configuration.md","lastUpdated":1727242778000}'),t={name:"guide/configure/client-configuration.md"},n=e(`

Client Configuration

Let's look at the client configuration options.

Client configuration template
toml
# chain_id =
+
+## Might be set via \`TORII_URL\` env var
+# torii_url =
+
+[basic_auth]
+# login =
+# password =
+
+[account]
+# id =
+# public_key =
+# private_key =
+
+[transaction]
+# time_to_live = "100s"
+# status_timeout = "100s"
+## Nonce is TODO describe what it is
+# nonce = false

Generation

You can use kagami to generate the default client configuration:

bash
$ kagami config client > client-config.json

Public and Private Keys

The defaults/client.toml client configuration file should contain the user's domain and a pair of their cryptographic keys: public_key and private_key.

For details on cryptographic keys, see Public Key Cryptography.

User account

The ACCOUNT_ID should be self-explanatory. The only thing you need to worry about is that the account must already exist in the blockchain. In other words, the account you provide here should already be registered.

Note

Iroha is case-sensitive, meaning that Alice@wonderland is different from alice@wonderland. It should go without saying that alice@wonderland is not the same as alice@looking_glass either, since these accounts belong to different domains, wonderland and looking_glass.

Basic Authentication Credentials

The idea of basic authentication credentials is to provide the access control using a web server with a reverse proxy like Nginx while these credentials are ignored by the Iroha peers.

The login and password will be filled by the client and used for the Authorization HTTP header.

Use this style of configuration to provide the basic authentication credentials (login and password):

json
  "BASIC_AUTH": {
+    "web_login": "mad_hatter",
+    "password": "ilovetea"
+  },

Iroha Public Addresses

TORII is the module in charge of handling incoming and outgoing connections. For client configuration, you can set up two addresses: TORII_API_URL and TORII_TELEMETRY_URL.

TORII_API_URL

First, the TORII_API_URL is the same as TORII API_URL in the peer configuration. This is the module responsible for handling incoming and outgoing connections. You should also add the prefix http:// or (preferably) https:// to the address. For example:

json
"TORII_API_URL": "http://127.0.0.1:8080"

TORII_TELEMETRY_URL

The TORII_TELEMETRY_URL is used to specify the prometheus endpoint address. You can set TORII_TELEMETRY_URL like this:

json
"TORII_TELEMETRY_URL": "http://127.0.0.1:8180"

A GET request to the 127.0.0.1:8180/status will give you a JSON-encoded representation of the top-level metrics, while a GET request to 127.0.0.1:8180/metrics will give you a (somewhat verbose) list of all available metrics gathered in Iroha. You might want to change this if you're having trouble gathering metrics using prometheus.

INFO

Learn how to monitor Iroha performance using prometheus.

Transaction Limits

You can specify the transaction limits that each transaction must adhere to: the maximum number of instructions and the maximum size of a WASM blob (in bytes). For example:

json
{
+  "max_instruction_number": 4096,
+  "max_wasm_size_bytes": 4194304
+}

Transaction TTL and Timeout

Configure the time-to-live (TTL) for transactions and the timeout to wait for the status. Both values have to be provided in milliseconds. For example:

json
"TRANSACTION_TIME_TO_LIVE_MS": 100000,
+"TRANSACTION_STATUS_TIMEOUT_MS": 15000,

Transaction Nonce

If you set ADD_TRANSACTION_NONCE to true, Iroha will create different hashes for transactions that occur repeatedly and simultaneously.

`,35),o=[n];function l(h,r,c,p,d,k){return i(),a("div",null,o)}const E=s(t,[["render",l]]);export{g as __pageData,E as default}; diff --git a/assets/guide_configure_client-configuration.md.22mv4OvP.lean.js b/assets/guide_configure_client-configuration.md.22mv4OvP.lean.js new file mode 100644 index 00000000..90b5eebf --- /dev/null +++ b/assets/guide_configure_client-configuration.md.22mv4OvP.lean.js @@ -0,0 +1 @@ +import{_ as s,c as a,o as i,V as e}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Client Configuration","description":"","frontmatter":{},"headers":[],"relativePath":"guide/configure/client-configuration.md","filePath":"guide/configure/client-configuration.md","lastUpdated":1727242778000}'),t={name:"guide/configure/client-configuration.md"},n=e("",35),o=[n];function l(h,r,c,p,d,k){return i(),a("div",null,o)}const E=s(t,[["render",l]]);export{g as __pageData,E as default}; diff --git a/assets/guide_configure_configuration-types.md.D9Ifeq5f.js b/assets/guide_configure_configuration-types.md.D9Ifeq5f.js new file mode 100644 index 00000000..4ea7e08f --- /dev/null +++ b/assets/guide_configure_configuration-types.md.D9Ifeq5f.js @@ -0,0 +1 @@ +import{_ as e,c as t,o,V as i}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Configuration Types","description":"","frontmatter":{},"headers":[],"relativePath":"guide/configure/configuration-types.md","filePath":"guide/configure/configuration-types.md","lastUpdated":1727242778000}'),a={name:"guide/configure/configuration-types.md"},n=i('

Configuration Types

Configuration options have different underlying types and default values, which are denoted in code as types wrapped in a single Option<..> or in a double Option<Option<..>>.

In this section we explain the difference between Option<..> and Option<Option<..>> used for configuration types. You can find more about available configuration options in the Peer Configuration topic.

Option<..>

A type wrapped in a single Option<..> signifies that in the corresponding json block there is a fallback value for this type, and that it only serves as a reference.

If a default for such a type has a null value, it means that

there is no meaningful fallback available for this particular value. It doesn't mean that you can omit the value. Quite the opposite, it must be set manually, either in the configuration file, or via the environment variables.

All the default values can be freely obtained from a provided sample configuration file, but it is only a starting point. **If left unchanged, the sample configuration file will not work. All null values in place of public and private keys as well as endpoint URLs should be provided either by modifying the sample config file or as environment variables. No other overloading of configuration values happens besides reading them from a file and capturing the environment variables, and environment variables take precedence.

For both types of configuration options wrapped in a single Option<..> (i.e. both those that have meaningful defaults and those that have null), failure to provide them in any of the above two ways results in an error.

Option<Option<..>>

Option<Option<..>> types should be distinguished from types wrapped in a single Option<..>. Only the double option ones are allowed to stay null, meaning that not providing them in an environment variable or a file will not cause an error.

Thus, only these types are truly optional in the common sense of the word. An example of this distinction is genesis public and private keys. While the first one is a single Option<..> wrapped type, the latter is wrapped in Option<Option<..>>. This means that the genesis public key should always be provided by the user, be it via a file config or an environment variable, whereas the private key is only needed for the peer that submits the genesis block, and can be omitted for all others. The same logic goes for other double option fields such as logger file path.

Sumeragi: default null values

A special note about Sumeragi fields with null as default: only the trusted_peers field out of the three can be initialized via a provided file or an environment variable.

The other two fields, namely key_pair and peer_id, go through a process of finalization where their values are derived from the corresponding ones in the uppermost Iroha config (using its public_key and private_key fields) or the Torii config (via its p2p_addr). This ensures that these linked fields stay in sync, and prevents the programmer error when different values are provided to these field pairs. Providing either sumeragi.key_pair or sumeragi.peer_id by hand will result in an error, as it should never be done directly. In later versions these configuration options shall be hidden completely.

',14),r=[n];function l(s,d,p,c,h,u){return o(),t("div",null,r)}const m=e(a,[["render",l]]);export{g as __pageData,m as default}; diff --git a/assets/guide_configure_configuration-types.md.D9Ifeq5f.lean.js b/assets/guide_configure_configuration-types.md.D9Ifeq5f.lean.js new file mode 100644 index 00000000..e0762a2e --- /dev/null +++ b/assets/guide_configure_configuration-types.md.D9Ifeq5f.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o,V as i}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Configuration Types","description":"","frontmatter":{},"headers":[],"relativePath":"guide/configure/configuration-types.md","filePath":"guide/configure/configuration-types.md","lastUpdated":1727242778000}'),a={name:"guide/configure/configuration-types.md"},n=i("",14),r=[n];function l(s,d,p,c,h,u){return o(),t("div",null,r)}const m=e(a,[["render",l]]);export{g as __pageData,m as default}; diff --git a/assets/guide_configure_genesis.md.CufogGXy.js b/assets/guide_configure_genesis.md.CufogGXy.js new file mode 100644 index 00000000..02d280ab --- /dev/null +++ b/assets/guide_configure_genesis.md.CufogGXy.js @@ -0,0 +1,191 @@ +import{_ as s,c as i,o as a,V as n}from"./chunks/framework.B6c1f-8R.js";const c=JSON.parse('{"title":"Genesis Block","description":"","frontmatter":{},"headers":[],"relativePath":"guide/configure/genesis.md","filePath":"guide/configure/genesis.md","lastUpdated":1727242778000}'),t={name:"guide/configure/genesis.md"},l=n(`

Genesis Block

The genesis block is the first block in your blockchain. It's never empty, even if configs/peer/genesis.json is. Here's an example:

Genesis Block Example: alice@wonderland
json
{
+  "transactions": [
+    [
+      {
+        "Register": {
+          "Domain": {
+            "id": "wonderland",
+            "logo": null,
+            "metadata": {
+              "key": {
+                "String": "value"
+              }
+            }
+          }
+        }
+      },
+      {
+        "Register": {
+          "Account": {
+            "id": "alice@wonderland",
+            "signatories": [
+              "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0"
+            ],
+            "metadata": {
+              "key": {
+                "String": "value"
+              }
+            }
+          }
+        }
+      },
+      {
+        "Register": {
+          "Account": {
+            "id": "bob@wonderland",
+            "signatories": [
+              "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0"
+            ],
+            "metadata": {
+              "key": {
+                "String": "value"
+              }
+            }
+          }
+        }
+      },
+      {
+        "Register": {
+          "AssetDefinition": {
+            "id": "rose#wonderland",
+            "value_type": "Numeric",
+            "mintable": "Infinitely",
+            "logo": null,
+            "metadata": {}
+          }
+        }
+      },
+      {
+        "Register": {
+          "Domain": {
+            "id": "garden_of_live_flowers",
+            "logo": null,
+            "metadata": {}
+          }
+        }
+      },
+      {
+        "Register": {
+          "Account": {
+            "id": "carpenter@garden_of_live_flowers",
+            "signatories": [
+              "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0"
+            ],
+            "metadata": {}
+          }
+        }
+      },
+      {
+        "Register": {
+          "AssetDefinition": {
+            "id": "cabbage#garden_of_live_flowers",
+            "value_type": "Numeric",
+            "mintable": "Infinitely",
+            "logo": null,
+            "metadata": {}
+          }
+        }
+      },
+      {
+        "Mint": {
+          "Asset": {
+            "object": "13",
+            "destination_id": "rose##alice@wonderland"
+          }
+        }
+      },
+      {
+        "Mint": {
+          "Asset": {
+            "object": "44",
+            "destination_id": "cabbage#garden_of_live_flowers#alice@wonderland"
+          }
+        }
+      },
+      {
+        "Transfer": {
+          "Domain": {
+            "source_id": "genesis@genesis",
+            "object": "wonderland",
+            "destination_id": "alice@wonderland"
+          }
+        }
+      },
+      {
+        "Grant": {
+          "PermissionToken": {
+            "object": {
+              "definition_id": "CanSetParameters",
+              "payload": null
+            },
+            "destination_id": "alice@wonderland"
+          }
+        }
+      },
+      {
+        "NewParameter": "?MaxTransactionsInBlock=512"
+      },
+      {
+        "NewParameter": "?BlockTime=2000"
+      },
+      {
+        "NewParameter": "?CommitTimeLimit=4000"
+      },
+      {
+        "NewParameter": "?TransactionLimits=4096,4194304_TL"
+      },
+      {
+        "NewParameter": "?WSVDomainMetadataLimits=1048576,4096_ML"
+      },
+      {
+        "NewParameter": "?WSVAssetDefinitionMetadataLimits=1048576,4096_ML"
+      },
+      {
+        "NewParameter": "?WSVAccountMetadataLimits=1048576,4096_ML"
+      },
+      {
+        "NewParameter": "?WSVAssetMetadataLimits=1048576,4096_ML"
+      },
+      {
+        "NewParameter": "?WSVTriggerMetadataLimits=1048576,4096_ML"
+      },
+      {
+        "NewParameter": "?WSVIdentLengthLimits=1,128_LL"
+      },
+      {
+        "NewParameter": "?ExecutorFuelLimit=55000000"
+      },
+      {
+        "NewParameter": "?ExecutorMaxMemory=524288000"
+      },
+      {
+        "NewParameter": "?WASMFuelLimit=55000000"
+      },
+      {
+        "NewParameter": "?WASMMaxMemory=524288000"
+      },
+      {
+        "Register": {
+          "Role": {
+            "id": "ALICE_METADATA_ACCESS",
+            "permissions": [
+              {
+                "definition_id": "CanRemoveKeyValueInAccount",
+                "payload": {
+                  "account_id": "alice@wonderland"
+                }
+              },
+              {
+                "definition_id": "CanSetKeyValueInAccount",
+                "payload": {
+                  "account_id": "alice@wonderland"
+                }
+              }
+            ]
+          }
+        }
+      }
+    ]
+  ],
+  "executor_file": "./executor.wasm"
+}

The genesis account is specified in the peer configuration file, configs/peer/config.json. This is the account that will submit the genesis block. The genesis account is like a super user account that has elevated privileges, but only during the genesis round. The genesis account should be signed by one of the peers, or, in other words, it should have the public key of this peer.

If you look at the example of a genesis block above, you will see that it contains instructions for registering a new domain (wonderland), two new accounts (alice@wonderland and bob@wonderland), a new asset (rose#wonderland) and a Mint instruction for this asset, as well as several permission tokens and roles. Both new accounts are signed with the ed01207233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0 public key.

Note

Iroha is case-sensitive, meaning that Alice@wonderland is different from alice@wonderland. It should go without saying that alice@wonderland is not the same as alice@looking_glass either, since these accounts belong to different domains, wonderland and looking_glass.

The accounts registered in the genesis block are just new accounts. As we said above, the genesis account is determined in the peer configuration. However, you can use the matching signature for the genesis account and for a new account in the genesis block. Since the genesis account only has privileges during the genesis round, it won't be a security issue.

You can generate the default genesis block or create a custom one.

If you need to recommit a genesis block, remove the previously stored blocks, then restart the Docker container. The new genesis block will be automatically recommited upon container restart.

Generation

You can add various instructions to the genesis block, such as registering new accounts or assets, as well as minting assets. You can also register permission tokens and roles, as well as grant them to the registered accounts.

Generate default genesis block

You can use kagami to generate the default genesis block:

  • Generate a genesis block in JSON format:

    bash
    $ kagami genesis
  • Generate a genesis block in JSON format and write the output to the specified file:

    bash
    $ kagami genesis > genesis.json
  • Generate a synthetic genesis block in JSON format and write the n domains, m accounts per domain and p assets per domain:

    bash
    $ kagami genesis --synthetic --domains n --accounts-per-domain m --assets-per-domain p

The genesis block should be located in configs/peer/genesis.json.

Configuration

As we already explained, genesis account is specified in the peer configuration file, configs/peer/config.json. You can use the same configuration file to fine-tune other genesis block configurations.

`,17),e=[l];function p(h,k,E,o,r,d){return a(),i("div",null,e)}const u=s(t,[["render",p]]);export{c as __pageData,u as default}; diff --git a/assets/guide_configure_genesis.md.CufogGXy.lean.js b/assets/guide_configure_genesis.md.CufogGXy.lean.js new file mode 100644 index 00000000..f3f2cdb5 --- /dev/null +++ b/assets/guide_configure_genesis.md.CufogGXy.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,V as n}from"./chunks/framework.B6c1f-8R.js";const c=JSON.parse('{"title":"Genesis Block","description":"","frontmatter":{},"headers":[],"relativePath":"guide/configure/genesis.md","filePath":"guide/configure/genesis.md","lastUpdated":1727242778000}'),t={name:"guide/configure/genesis.md"},l=n("",17),e=[l];function p(h,k,E,o,r,d){return a(),i("div",null,e)}const u=s(t,[["render",p]]);export{c as __pageData,u as default}; diff --git a/assets/guide_configure_keys-for-network-deployment.md.Du4srmTx.js b/assets/guide_configure_keys-for-network-deployment.md.Du4srmTx.js new file mode 100644 index 00000000..f3d64aec --- /dev/null +++ b/assets/guide_configure_keys-for-network-deployment.md.Du4srmTx.js @@ -0,0 +1 @@ +import{_ as e,c as o,o as t,V as a}from"./chunks/framework.B6c1f-8R.js";const f=JSON.parse('{"title":"Keys for Network Deployment","description":"","frontmatter":{},"headers":[],"relativePath":"guide/configure/keys-for-network-deployment.md","filePath":"guide/configure/keys-for-network-deployment.md","lastUpdated":1727242778000}'),r={name:"guide/configure/keys-for-network-deployment.md"},i=a('

Keys for Network Deployment

If you're deploying your own Iroha 2 network, your unique cryptographic keys must be specified in all configuration files:

  1. Client configuration file: defaults/client.toml
  2. Genesis block file: defaults/genesis.json

To learn more about cryptographic keys and their role, see Security > Public Key Cryptography.

Setting Keys For a New Network

1. Generate New Key Pairs

To generate new key pairs for the peers, a wide variety of methods can be used. However, within the Iroha 2 framework, you can conveniently use the built-in kagami tool for generating cryptographic keys.

To generate a new key pair run the following command from the project's root directory:

bash
$ cargo run --bin kagami --release -- crypto --json

Note

The output cryptographic keys generated by kagami are customizable by using preferences. Note that in the example above the --json parameter is specified to generate a key pair in the JSON format.

To learn more about generating cryptographic keys with kagami, available algorithms, and other parameters, see Generating Cryptographic Keys with Kagami.

If you plan to use the generated private_key with one of our SDKs, note that even though cryptographic keys are commonly encoded using ASCII characters, both the payload value of the private_key and the string representation of the public_key are encoded as Hex.

2. Update Keys For Peers

If you want to set up your own network, you should change the keys for all your peers: in peer/config.json change PUBLIC_KEY and PRIVATE_KEY to the fresh pair. When you've done that, you should add the keys to the TRUSTED_PEERS array in the same configuration file. Every peer that wants to connect to the given peer from the outside must know its PRIVATE_KEY specified in the TRUSTED_PEERS section.

To create a minimum BFT network one needs four peers, which means four different private keys split across four different configuration files (or environment variables).

Each peer must have their own PUBLIC_KEY and PRIVATE_KEY variables specified. All four of the public keys—including the peer that is being configured—must be added to the TRUSTED_PEERS array. The same TRUSTED_PEERS array must be copied across all four of the configuration files. If either one of the peers is missing, or there's an extraneous peer or one of the peers has the incorrect key, the network will fail to start.

After that, make sure that the peers agree on the GENESIS_ACCOUNT key pairs. Failure to do so will result in a network which cannot accept any transactions.

Note

Even though the private key for the genesis account is known to all peers, the account itself loses all privileges after the first block is committed.

3. Register a Non-Genesis Account

Finally, while the first client could use the genesis account to register new users, it's not a great idea for most networks. You should, instead, register a non-genesis account (for example, alice@wonderland).

WARNING

iroha binary currently processes all of its instructions in the JSON format, it also provides a dedicated instruction to unregister accounts.

If you plan on creating a private blockchain, you should consider writing your own client based on the client Rust crate, or any of the provided client libraries:

',20),n=[i];function s(c,l,h,d,p,u){return t(),o("div",null,n)}const g=e(r,[["render",s]]);export{f as __pageData,g as default}; diff --git a/assets/guide_configure_keys-for-network-deployment.md.Du4srmTx.lean.js b/assets/guide_configure_keys-for-network-deployment.md.Du4srmTx.lean.js new file mode 100644 index 00000000..b7b23e90 --- /dev/null +++ b/assets/guide_configure_keys-for-network-deployment.md.Du4srmTx.lean.js @@ -0,0 +1 @@ +import{_ as e,c as o,o as t,V as a}from"./chunks/framework.B6c1f-8R.js";const f=JSON.parse('{"title":"Keys for Network Deployment","description":"","frontmatter":{},"headers":[],"relativePath":"guide/configure/keys-for-network-deployment.md","filePath":"guide/configure/keys-for-network-deployment.md","lastUpdated":1727242778000}'),r={name:"guide/configure/keys-for-network-deployment.md"},i=a("",20),n=[i];function s(c,l,h,d,p,u){return t(),o("div",null,n)}const g=e(r,[["render",s]]);export{f as __pageData,g as default}; diff --git a/assets/guide_configure_metadata-and-store-assets.md.D9AcB5Vs.js b/assets/guide_configure_metadata-and-store-assets.md.D9AcB5Vs.js new file mode 100644 index 00000000..9d72084c --- /dev/null +++ b/assets/guide_configure_metadata-and-store-assets.md.D9AcB5Vs.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as a,V as s}from"./chunks/framework.B6c1f-8R.js";const f=JSON.parse('{"title":"Choosing Between the Store and Metadata Assets","description":"","frontmatter":{},"headers":[],"relativePath":"guide/configure/metadata-and-store-assets.md","filePath":"guide/configure/metadata-and-store-assets.md","lastUpdated":1727242778000}'),o={name:"guide/configure/metadata-and-store-assets.md"},n=s('

Choosing Between the Store and Metadata Assets

The Store and metadata assets allow for the storage of several parameters with different types and string keys. Despite the similarity, their use cases differ.

In most cases, you should only use metadata if you want something to use specific quantities and not be editable by other users. There are a few other practical considerations we'll discuss below.

You must use a Store asset if the data exists in the blockchain and a default number type is not applicable. It lets you record data sequences and works as a dictionary, where the keys are strings, while the values are Value type instances that assume many types from String to Ipv6Addr.

Let’s discuss some use cases to make it more clear.

Let’s say, for example, you have a clinic. Here, generic user data, such as birthdays, can be added to metadata. The Store asset instances record the appointments, treatments suggested by the doctors, and medical test results.

Suppose you’re using Iroha for a large-scale IoT network to monitor the machines in your factory. In this case, you want to use the Store asset instances to record each manufacturing process on each manufacturing device so you can analyze the factors involved in the manufacturing process to understand the “health” of your machines and reduce the possibility of downtime by making repairs when needed.

Finally, imagine a network of organizations that trade specific goods or resources. Here, the Store assets would record every trade agreement, including the trade cost and a signature. This approach applies to many cases, starting with someone’s services and ending with NFTs.

There are also some pitfalls in choosing between metadata and Store assets.

Let's look at what happens when we define something in the metadata at the system level, such as the number of queries users can perform at a given time. Theoretically, this is correct since metadata is a key-value store. However, the default settings allow users to edit their metadata. In the development phase, this isn't a significant problem. However, once deployed, users could change the number of queries they can perform in this configuration, rendering any imposed restrictions ineffective.

With a new account schema, the user's metadata becomes global information: you cannot restrict access to it and say that this is related to a domain. On the other hand, the storage asset can belong to a single user. Some optimizations prevent domain-specific triggers from acting only on domain-specific data. Using metadata would cause these optimizations not to work. Instead, each user within a domain can get a copy of the metadata. This approach works like metadata, except that you'd give them memory access but not necessarily allow them to create new key-value pairs. They can see how many queries they have left, but they can't easily change that number with a simple statement.

Instead of thinking about data ownership, think about the location of the data and the function that data serves and the flow of information. So instead of storing in the user's metadata the number of queries they're allowed to make, the number of tokens they have created, or their NFTs, you should put each category in its own Store asset.

Think about what the smartcontract is supposed to do and how much extra data you must load and ignore. If your service participates using the metadata and another one does, and so on, the metadata size becomes enormous. Whenever you have queries related to it, you'll copy a lot of excess information and slow your code down. There's another catch: when the metadata belongs to an account, it essentially depends on another entity. When the said entity is removed or replaced, it requires glue code to handle the metadata transfer.

',13),i=[n];function r(d,c,h,u,m,l){return a(),t("div",null,i)}const y=e(o,[["render",r]]);export{f as __pageData,y as default}; diff --git a/assets/guide_configure_metadata-and-store-assets.md.D9AcB5Vs.lean.js b/assets/guide_configure_metadata-and-store-assets.md.D9AcB5Vs.lean.js new file mode 100644 index 00000000..2dc4ac3c --- /dev/null +++ b/assets/guide_configure_metadata-and-store-assets.md.D9AcB5Vs.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as a,V as s}from"./chunks/framework.B6c1f-8R.js";const f=JSON.parse('{"title":"Choosing Between the Store and Metadata Assets","description":"","frontmatter":{},"headers":[],"relativePath":"guide/configure/metadata-and-store-assets.md","filePath":"guide/configure/metadata-and-store-assets.md","lastUpdated":1727242778000}'),o={name:"guide/configure/metadata-and-store-assets.md"},n=s("",13),i=[n];function r(d,c,h,u,m,l){return a(),t("div",null,i)}const y=e(o,[["render",r]]);export{f as __pageData,y as default}; diff --git a/assets/guide_configure_modes.md.DEYMQiV1.js b/assets/guide_configure_modes.md.DEYMQiV1.js new file mode 100644 index 00000000..9ad40225 --- /dev/null +++ b/assets/guide_configure_modes.md.DEYMQiV1.js @@ -0,0 +1 @@ +import{_ as e,c as o,o as t,V as i}from"./chunks/framework.B6c1f-8R.js";const f=JSON.parse('{"title":"Public and Private Blockchains","description":"","frontmatter":{},"headers":[],"relativePath":"guide/configure/modes.md","filePath":"guide/configure/modes.md","lastUpdated":1727242778000}'),a={name:"guide/configure/modes.md"},s=i('

Public and Private Blockchains

Iroha can be ran in a variety of configurations. As the administrator of your own network, you can use different permission sets to decide what criteria must be met in order for some transaction to be accepted.

We provide two major sets of permissions: called a private and public permission sets. These need to be added into the genesis.json before you start an Iroha peer.

Below we outline the major differences in these two use cases.

Permissions

In a public blockchain, most accounts have the same set of permissions. In a private blockchain, most accounts are assumed not to be able to do anything outside of their own account or domain unless explicitly granted said permission.

INFO

Refer to the dedicated section on permissions for more details.

Peers

Any peer can join a public blockchain. For a private blockchain, automatic discovery of peers is turned off.

INFO

Refer to peer management for more details.

Registering accounts

Depending on how you decide to set up your genesis block (genesis.json), the process for registering an account might go one of two ways. To understand why, let's talk about permission first.

By default, Iroha allows all instructions to go through, until a permission validator that can restrict instruction execution has been registered. You can add permission validators to your genesis block by registering built-in permission tokens that we thought would be useful for private and public blockchain use-cases. However, in that case, the process of registering accounts is different.

When it comes to registering accounts, public and private blockchain have the following differences:

  • In a public blockchain, anyone should be able to register an account[1]. So, in theory, all that you need is a suitable client, a way to generate a private key of a suitable type (ED25519), and that's it.

  • In a private blockchain, you can have any process for setting up an account: it could be that the registering instruction has to be submitted by a specific account, or by a smart contract that asks for other details. It could be that in a private blockchain registering new accounts is only possible on specific dates, or limited by a non-mintable (finite) token.

  • In a typical private blockchain, i.e. a blockchain without any unique processes for registering accounts, you need an account to register another account.

Built-in permission validators for private blockchains cover the `typical private blockchain use-case.

INFO

As of writing, the set of public blockchain permissions is incomplete, and as such Iroha source code needs to be modified to run it in the public mode.

Refer to the section on instructions for more details about Register<Account> instructions.


  1. In fact, once we have finished with our key-centric address scheme for accounts, you don't register an account as much as claim it. ↩︎

',20),n=[s];function c(r,l,d,u,h,p){return t(),o("div",null,n)}const b=e(a,[["render",c]]);export{f as __pageData,b as default}; diff --git a/assets/guide_configure_modes.md.DEYMQiV1.lean.js b/assets/guide_configure_modes.md.DEYMQiV1.lean.js new file mode 100644 index 00000000..4aa5c448 --- /dev/null +++ b/assets/guide_configure_modes.md.DEYMQiV1.lean.js @@ -0,0 +1 @@ +import{_ as e,c as o,o as t,V as i}from"./chunks/framework.B6c1f-8R.js";const f=JSON.parse('{"title":"Public and Private Blockchains","description":"","frontmatter":{},"headers":[],"relativePath":"guide/configure/modes.md","filePath":"guide/configure/modes.md","lastUpdated":1727242778000}'),a={name:"guide/configure/modes.md"},s=i("",20),n=[s];function c(r,l,d,u,h,p){return t(),o("div",null,n)}const b=e(a,[["render",c]]);export{f as __pageData,b as default}; diff --git a/assets/guide_configure_overview.md.D6DO6mJ9.js b/assets/guide_configure_overview.md.D6DO6mJ9.js new file mode 100644 index 00000000..eb0bbf1e --- /dev/null +++ b/assets/guide_configure_overview.md.D6DO6mJ9.js @@ -0,0 +1 @@ +import{_ as a,c as n,o as t,m as e,a as o}from"./chunks/framework.B6c1f-8R.js";const p=JSON.parse('{"title":"Configuration and Management","description":"","frontmatter":{},"headers":[],"relativePath":"guide/configure/overview.md","filePath":"guide/configure/overview.md","lastUpdated":1727242778000}'),r={name:"guide/configure/overview.md"},i=e("h1",{id:"configuration-and-management",tabindex:"-1"},[o("Configuration and Management "),e("a",{class:"header-anchor",href:"#configuration-and-management","aria-label":'Permalink to "Configuration and Management"'},"​")],-1),d=[i];function c(s,m,f,g,u,_){return t(),n("div",null,d)}const h=a(r,[["render",c]]);export{p as __pageData,h as default}; diff --git a/assets/guide_configure_overview.md.D6DO6mJ9.lean.js b/assets/guide_configure_overview.md.D6DO6mJ9.lean.js new file mode 100644 index 00000000..eb0bbf1e --- /dev/null +++ b/assets/guide_configure_overview.md.D6DO6mJ9.lean.js @@ -0,0 +1 @@ +import{_ as a,c as n,o as t,m as e,a as o}from"./chunks/framework.B6c1f-8R.js";const p=JSON.parse('{"title":"Configuration and Management","description":"","frontmatter":{},"headers":[],"relativePath":"guide/configure/overview.md","filePath":"guide/configure/overview.md","lastUpdated":1727242778000}'),r={name:"guide/configure/overview.md"},i=e("h1",{id:"configuration-and-management",tabindex:"-1"},[o("Configuration and Management "),e("a",{class:"header-anchor",href:"#configuration-and-management","aria-label":'Permalink to "Configuration and Management"'},"​")],-1),d=[i];function c(s,m,f,g,u,_){return t(),n("div",null,d)}const h=a(r,[["render",c]]);export{p as __pageData,h as default}; diff --git a/assets/guide_configure_peer-configuration.md.PLGB4drn.js b/assets/guide_configure_peer-configuration.md.PLGB4drn.js new file mode 100644 index 00000000..7a6d2cc7 --- /dev/null +++ b/assets/guide_configure_peer-configuration.md.PLGB4drn.js @@ -0,0 +1,67 @@ +import{_ as e,c as s,o as a,V as i}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Peer Configuration","description":"","frontmatter":{},"headers":[],"relativePath":"guide/configure/peer-configuration.md","filePath":"guide/configure/peer-configuration.md","lastUpdated":1727242778000}'),n={name:"guide/configure/peer-configuration.md"},t=i(`

Peer Configuration

The peer configuration file (configs/peer/config.json) determines how your blockchain operates.

Here's an example of how peer configuration file looks like:

Peer configuration template
toml
## For the full reference, go to (TODO put link)
+
+## You can use another TOML file to extend from.
+## For a single file extension:
+# extends = "./base.toml"
+## Or, for a chain of extensions:
+# extends = ["base-1.toml", "base-2.toml"]
+
+# chain_id =
+# public_key =
+# private_key = {
+#   algorithm = ,
+#   payload =
+# }
+
+[genesis]
+# file =
+# public_key =
+# private_key =
+
+[network]
+# address =
+# block_gossip_period = "10s"
+# block_gossip_max_size = 4
+# transaction_gossip_period = "1s"
+# transaction_gossip_max_size = 500
+# idle_timeout = "60s"
+
+[torii]
+# address =
+# max_content_len = "16mb"
+# query_idle_time = "30s"
+
+[kura]
+# init_mode = "strict"
+# store_dir = "./storage"
+
+## Add more of this section for each trusted peer
+# [[sumeragi.trusted_peers]]
+# address =
+# public_key =
+
+[logger]
+# level = "INFO"
+# format = "full"
+
+## Transactions Queue
+[queue]
+# capacity = 65536
+# capacity_per_user = 65536
+# transaction_time_to_live = "1day"
+# future_threshold = "1s"
+
+[snapshot]
+# mode = "read_write"
+# create_every = "1min"
+# store_dir = "./storage/snapshot"
+
+[telemetry]
+# name =
+# url =
+# min_retry_period = "1s"
+# max_retry_delay_exponent = 4
+
+[dev_telemetry]
+## A path to a file with JSON logs
+# out_file = "./dev_telemetry.json"

INFO

Note that for convenient container deployment, configuration options specified via environment variables always override the corresponding values in the configuration file. This way, you can have a basic configuration file and also configure some options in a docker-compose.yml or in your shell's environment file (.bashrc, .zshrc, etc.).

Some of the configuration options are required, while others are used for fine-tuning. When you create a new peer, you are required to provide the following:

INFO

Configuration options have different underlying types and default values, which are denoted in code as types wrapped in a single Option<..> or in a double Option<Option<..>>. Refer to configuration types for details.

Generation

You can use kagami to generate the default peer configuration:

bash
$ kagami config peer > peer-config.json

Public and private keys

The configs/peer/config.json peer configuration file should contain a pair of the user's public PUBLIC_KEY and private PRIVATE_KEY cryptographic keys for their account's ACCOUNT_ID.

For details on cryptographic keys, see Public Key Cryptography.

Trusted Peers

Iroha is a blockchain ledger. In order for it to work optimally and be Byzantine-fault tolerant with the maximum number of faults allowed, it needs to be started with a set number of peers: 4, 7, 10, ... 3f+1, where f is the allowed number of faults.

So usually, when you want to start an Iroha deployment, you should already know a number of peers that you can trust and join their blockchain. The way it works in the examples is that you just specify in four config.json files four peers with their public keys and API addresses.

Since Iroha has no automatic peer discovery, the only other way to make peers known to each other is to use the iroha binary to register new peers). This is not too difficult with the provided client libraries. With Python's Beautiful Soup, the curated list of peers can be updated, registered, and un-registered on its own.

The list of trusted peers is a part of SUMERAGI configuration. Here's an example of SUMERAGI_TRUSTED_PEERS environment variable to configure trusted peers:

'[{"address":"iroha0:1337", "public_key": "ed01201c61faf8fe94e253b93114240394f79a607b7fa55f9e5a41ebec74b88055768b"}, {"address":"iroha1:1338", "public_key": "ed0120cc25624d62896d3a0bfd8940f928dc2abf27cc57cefeb442aa96d9081aae58a1"}, {"address": "iroha2:1339", "public_key": "ed0120faca9e8aa83225cb4d16d67f27dd4f93fc30ffa11adc1f5c88fd5495ecc91020"}, {"address": "iroha3:1340", "public_key": "ed01208e351a70b6a603ed285d666b8d689b680865913ba03ce29fb7d13a166c4e7f1f"}]'

Iroha Public Addresses

TORII is the module in charge of handling incoming and outgoing connections.

API_URL

The API_URL is the location to which the client(s) make their requests. You can also use it to change some peer-specific configuration options.

Most of the time, the only reason to change the API_URL is to change the port, in case 8080 is either closed, or if you want to randomise ports to avoid certain kinds of attacks.

P2P_ADDR

The P2P_ADDR is the internal address used for communication between peers. This address should be included in the TRUSTED_PEERS section of the configuration file.

TELEMETRY_URL

The TELEMETRY_URL is used to specify the prometheus endpoint address. It's set by adding "TELEMETRY_URL": "127.0.0.1:8180" to the TORII section of the configuration file.

It's not meant to be human-readable. However, a GET request to the 127.0.0.1:8180/status will give you a JSON-encoded representation of the top-level metrics, while a GET request to 127.0.0.1:8180/metrics will give you a (somewhat verbose) list of all available metrics gathered in Iroha. You might want to change this if you're having trouble gathering metrics using prometheus.

INFO

Learn how to monitor Iroha performance using prometheus.

Genesis

When you configure a peer, you have to provide private and public keys for the genesis account.

You can do this via the configuration file (ACCOUNT_PUBLIC_KEY, ACCOUNT_PRIVATE_KEY) or environment variables (IROHA_GENESIS_ACCOUNT_PUBLIC_KEY, IROHA_GENESIS_ACCOUNT_PRIVATE_KEY).

To learn more about genesis block, genesis account, and cryptographic keys, see the following:

Aside from the public and private keys for the genesis account, which are required configuration options, you can also fine-tune other genesis block configurations, such as:

  • WAIT_FOR_PEERS_RETRY_COUNT_LIMIT: the number of attempts to connect to peers before genesis block is submitted
  • WAIT_FOR_PEERS_RETRY_PERIOD_MS: how long to wait before retrying a connection to peers
  • GENESIS_SUBMISSION_DELAY_MS: the delay before the genesis block submission after the minimum number of peers were discovered.

Logger

Let's cover the most useful LOGGER configurations, MAX_LOG_LEVEL and LOG_FILE_PATH.

MAX_LOG_LEVEL

The MAX_LOG_LEVEL is used to determine which messages are logged.

With "MAX_LOG_LEVEL": "WARN" you won't get any messages unless they are either a warning or an error. Beside WARN, other available options are:

  • TRACE (log every time you enter a function)
  • DEBUG (use when you know something went wrong)
  • INFO (the default)
  • WARN (log everything that could be an error)
  • ERROR (to silence any logging except for error messages)

LOG_FILE_PATH

Another useful option is "LOG_FILE_PATH": bunyan.json. It creates (if it didn't already exist) a file called bunyan.json that contains the message log in a structured format.

This is extremely useful for two reasons. Firstly, you can use the bunyan log viewer to filter information more precisely than Iroha would allow you to do. Do you only want messages from a specific module or package? You can do that with bunyan. Secondly, while copying logs is not too big of a problem if your instance is just a small setup, for bigger setups the log will be larger. Having it saved to a file makes much more sense in that case.

INFO

You can also set LOG_FILE_PATH to /dev/stdout if you want to use bunyan's logging facilities directly without saving the output.

Kura

Kura is the persistent storage engine of Iroha (Japanese for warehouse). The BLOCK_STORE_PATH specifies where the blocks are stored. You can change it to a custom location if for some reason the default location (./storage) is not available or desirable.

`,50),o=[t];function l(r,p,c,h,d,u){return a(),s("div",null,o)}const f=e(n,[["render",l]]);export{g as __pageData,f as default}; diff --git a/assets/guide_configure_peer-configuration.md.PLGB4drn.lean.js b/assets/guide_configure_peer-configuration.md.PLGB4drn.lean.js new file mode 100644 index 00000000..13b5353d --- /dev/null +++ b/assets/guide_configure_peer-configuration.md.PLGB4drn.lean.js @@ -0,0 +1 @@ +import{_ as e,c as s,o as a,V as i}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Peer Configuration","description":"","frontmatter":{},"headers":[],"relativePath":"guide/configure/peer-configuration.md","filePath":"guide/configure/peer-configuration.md","lastUpdated":1727242778000}'),n={name:"guide/configure/peer-configuration.md"},t=i("",50),o=[t];function l(r,p,c,h,d,u){return a(),s("div",null,o)}const f=e(n,[["render",l]]);export{g as __pageData,f as default}; diff --git a/assets/guide_configure_peer-management.md.DhMQe9u_.js b/assets/guide_configure_peer-management.md.DhMQe9u_.js new file mode 100644 index 00000000..209619e8 --- /dev/null +++ b/assets/guide_configure_peer-management.md.DhMQe9u_.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as a,V as r}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Peer Management","description":"","frontmatter":{},"headers":[],"relativePath":"guide/configure/peer-management.md","filePath":"guide/configure/peer-management.md","lastUpdated":1727242778000}'),i={name:"guide/configure/peer-management.md"},o=r('

Peer Management

If you followed any of the language-specific guides, you now have a well-functioning network that people will want to join.

Public Blockchain

Naturally, in a public blockchain, joining is a matter of installing the correct software and waiting until your node gets discovered.

INFO

Peer discovery is under construction.

Private Blockchain

In a bank setting, allowing everyone to join at their leisure is a security nightmare. For safety, automatic discovery of peers is turned off for Iroha 2 in the private blockchain configuration.

Registering peers

To add a peer to the network, it must be manually registered. Let's discuss the steps that should be taken in order to complete this process.

1. Grant the user permissions

The user that registers the peer must have the appropriate PermissionToken. This could be granted as part of a role, or as part of a one-time allowance.

How to decide if you need to grant a role? Granting roles makes sense if a user is to serve as an administrator of sorts, where it's their responsibility to maintain the peers in the network long-term. A one-time permission grant is useful when the party registering the peer isn't responsible for registering peers in general, but the network administrator doesn't need to (or want to) spend time setting up a new peer.

INFO

Permissions for registering a peer are under construction.

We discuss permissions and roles with more detail in a separate chapter.

2. Set up a peer

After a new peer was granted permissions, it must be set up.

It's a good idea to request information about the peers' configuration in the network. Your best friend is the configuration endpoint of the API socket. Thus far querying is done manually. Until the bootstrapping procedure is implemented, you'll have to manually check that the timeouts and batch sizes match.

To simplify the process, you can ask the network administrator for a redacted version of config.json, which excludes privileged information, such as PRIVATE_KEYs.

3. Submit the instruction

After your peer is running, you should submit the register peer instruction. The peer will go through the handshake process and start chatting with the network.

TIP

Submitting a Register<Peer> instruction does not (and cannot) instantiate a new peer process.

Unregistering peers

What about unregistering peers? For security reasons this process is one-sided. The network reaches consensus that it wants to remove a peer, but the peer itself doesn't know much about why nobody's talking to it.

In most circumstances, if you want to unregister a peer, you want to do so because it is a Byzantine fault. Just "ghosting" this peer makes the life of the malicious actor on the network harder.

',24),s=[o];function n(c,h,p,l,u,d){return a(),t("div",null,s)}const f=e(i,[["render",n]]);export{g as __pageData,f as default}; diff --git a/assets/guide_configure_peer-management.md.DhMQe9u_.lean.js b/assets/guide_configure_peer-management.md.DhMQe9u_.lean.js new file mode 100644 index 00000000..04330695 --- /dev/null +++ b/assets/guide_configure_peer-management.md.DhMQe9u_.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as a,V as r}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Peer Management","description":"","frontmatter":{},"headers":[],"relativePath":"guide/configure/peer-management.md","filePath":"guide/configure/peer-management.md","lastUpdated":1727242778000}'),i={name:"guide/configure/peer-management.md"},o=r("",24),s=[o];function n(c,h,p,l,u,d){return a(),t("div",null,s)}const f=e(i,[["render",n]]);export{g as __pageData,f as default}; diff --git a/assets/guide_configure_sample-configuration.md.B3LcukXt.js b/assets/guide_configure_sample-configuration.md.B3LcukXt.js new file mode 100644 index 00000000..4d40207f --- /dev/null +++ b/assets/guide_configure_sample-configuration.md.B3LcukXt.js @@ -0,0 +1,209 @@ +import{_ as s,c as i,o as a,V as n}from"./chunks/framework.B6c1f-8R.js";const y=JSON.parse('{"title":"Sample Configuration Files","description":"","frontmatter":{},"headers":[],"relativePath":"guide/configure/sample-configuration.md","filePath":"guide/configure/sample-configuration.md","lastUpdated":1727242778000}'),l={name:"guide/configure/sample-configuration.md"},t=n(`

Sample Configuration Files

Here you can find sample configuration files for Iroha 2:

json
{
+  "transactions": [
+    [
+      {
+        "Register": {
+          "Domain": {
+            "id": "wonderland",
+            "logo": null,
+            "metadata": {
+              "key": {
+                "String": "value"
+              }
+            }
+          }
+        }
+      },
+      {
+        "Register": {
+          "Account": {
+            "id": "alice@wonderland",
+            "signatories": [
+              "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0"
+            ],
+            "metadata": {
+              "key": {
+                "String": "value"
+              }
+            }
+          }
+        }
+      },
+      {
+        "Register": {
+          "Account": {
+            "id": "bob@wonderland",
+            "signatories": [
+              "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0"
+            ],
+            "metadata": {
+              "key": {
+                "String": "value"
+              }
+            }
+          }
+        }
+      },
+      {
+        "Register": {
+          "AssetDefinition": {
+            "id": "rose#wonderland",
+            "value_type": "Numeric",
+            "mintable": "Infinitely",
+            "logo": null,
+            "metadata": {}
+          }
+        }
+      },
+      {
+        "Register": {
+          "Domain": {
+            "id": "garden_of_live_flowers",
+            "logo": null,
+            "metadata": {}
+          }
+        }
+      },
+      {
+        "Register": {
+          "Account": {
+            "id": "carpenter@garden_of_live_flowers",
+            "signatories": [
+              "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0"
+            ],
+            "metadata": {}
+          }
+        }
+      },
+      {
+        "Register": {
+          "AssetDefinition": {
+            "id": "cabbage#garden_of_live_flowers",
+            "value_type": "Numeric",
+            "mintable": "Infinitely",
+            "logo": null,
+            "metadata": {}
+          }
+        }
+      },
+      {
+        "Mint": {
+          "Asset": {
+            "object": "13",
+            "destination_id": "rose##alice@wonderland"
+          }
+        }
+      },
+      {
+        "Mint": {
+          "Asset": {
+            "object": "44",
+            "destination_id": "cabbage#garden_of_live_flowers#alice@wonderland"
+          }
+        }
+      },
+      {
+        "Transfer": {
+          "Domain": {
+            "source_id": "genesis@genesis",
+            "object": "wonderland",
+            "destination_id": "alice@wonderland"
+          }
+        }
+      },
+      {
+        "Grant": {
+          "PermissionToken": {
+            "object": {
+              "definition_id": "CanSetParameters",
+              "payload": null
+            },
+            "destination_id": "alice@wonderland"
+          }
+        }
+      },
+      {
+        "NewParameter": "?MaxTransactionsInBlock=512"
+      },
+      {
+        "NewParameter": "?BlockTime=2000"
+      },
+      {
+        "NewParameter": "?CommitTimeLimit=4000"
+      },
+      {
+        "NewParameter": "?TransactionLimits=4096,4194304_TL"
+      },
+      {
+        "NewParameter": "?WSVDomainMetadataLimits=1048576,4096_ML"
+      },
+      {
+        "NewParameter": "?WSVAssetDefinitionMetadataLimits=1048576,4096_ML"
+      },
+      {
+        "NewParameter": "?WSVAccountMetadataLimits=1048576,4096_ML"
+      },
+      {
+        "NewParameter": "?WSVAssetMetadataLimits=1048576,4096_ML"
+      },
+      {
+        "NewParameter": "?WSVTriggerMetadataLimits=1048576,4096_ML"
+      },
+      {
+        "NewParameter": "?WSVIdentLengthLimits=1,128_LL"
+      },
+      {
+        "NewParameter": "?ExecutorFuelLimit=55000000"
+      },
+      {
+        "NewParameter": "?ExecutorMaxMemory=524288000"
+      },
+      {
+        "NewParameter": "?WASMFuelLimit=55000000"
+      },
+      {
+        "NewParameter": "?WASMMaxMemory=524288000"
+      },
+      {
+        "Register": {
+          "Role": {
+            "id": "ALICE_METADATA_ACCESS",
+            "permissions": [
+              {
+                "definition_id": "CanRemoveKeyValueInAccount",
+                "payload": {
+                  "account_id": "alice@wonderland"
+                }
+              },
+              {
+                "definition_id": "CanSetKeyValueInAccount",
+                "payload": {
+                  "account_id": "alice@wonderland"
+                }
+              }
+            ]
+          }
+        }
+      }
+    ]
+  ],
+  "executor_file": "./executor.wasm"
+}
toml
# chain_id =
+
+## Might be set via \`TORII_URL\` env var
+# torii_url =
+
+[basic_auth]
+# login =
+# password =
+
+[account]
+# id =
+# public_key =
+# private_key =
+
+[transaction]
+# time_to_live = "100s"
+# status_timeout = "100s"
+## Nonce is TODO describe what it is
+# nonce = false
`,4),p=[t];function h(k,e,E,r,d,o){return a(),i("div",null,p)}const u=s(l,[["render",h]]);export{y as __pageData,u as default}; diff --git a/assets/guide_configure_sample-configuration.md.B3LcukXt.lean.js b/assets/guide_configure_sample-configuration.md.B3LcukXt.lean.js new file mode 100644 index 00000000..198d3871 --- /dev/null +++ b/assets/guide_configure_sample-configuration.md.B3LcukXt.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,V as n}from"./chunks/framework.B6c1f-8R.js";const y=JSON.parse('{"title":"Sample Configuration Files","description":"","frontmatter":{},"headers":[],"relativePath":"guide/configure/sample-configuration.md","filePath":"guide/configure/sample-configuration.md","lastUpdated":1727242778000}'),l={name:"guide/configure/sample-configuration.md"},t=n("",4),p=[t];function h(k,e,E,r,d,o){return a(),i("div",null,p)}const u=s(l,[["render",h]]);export{y as __pageData,u as default}; diff --git a/assets/guide_get-started_index.md.CX985dei.js b/assets/guide_get-started_index.md.CX985dei.js new file mode 100644 index 00000000..99d024e2 --- /dev/null +++ b/assets/guide_get-started_index.md.CX985dei.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as r,V as t}from"./chunks/framework.B6c1f-8R.js";const f=JSON.parse('{"title":"Iroha 2","description":"","frontmatter":{},"headers":[],"relativePath":"guide/get-started/index.md","filePath":"guide/get-started/index.md","lastUpdated":1727242778000}'),i={name:"guide/get-started/index.md"},o=t('

Iroha 2

Iroha 2 is a fully-featured blockchain ledger. With Iroha 2 you can:

  • Create and manage custom fungible assets, such as currencies, gold, etc.
  • Create and manage non-fungible assets, such as digital art, intellectual property, etc.
  • Manage user accounts with a domain hierarchy and multi-signature transactions.
  • Use efficient portable smart contracts implemented with WebAssembly and Iroha Special Instructions.
  • Use both permissioned and permissionless blockchain deployments.

Get Started

If you are just starting with Iroha 2, begin with the following step-by-step tutorials:

  1. Install Iroha 2: install prerequisites and clone the GitHub repository.
  2. Launch Iroha 2: install prerequisites and establish an instance of Iroha network.
  3. Operate Iroha 2 via CLI: learn how to setup and configure Iroha Client, and perform necessary basic operations on the network (e.g., registering domains and accounts, registering and minting assets, etc.).

If you would like to operate Iroha 2 using a different programming language, Iroha provides SDKs and language-specific tutorials for the following languages:

TIP

The current version of Iroha covered in this documentation is Iroha 2. If you have previously worked with Iroha 1, you may want to start with the Iroha 2 vs. Iroha 1 comparison that will help you understand the improvements and new features of Iroha 2.

Explore In-Depth

Once you have learned the basics, we suggest exploring the following sections:

Learn More

For more information on Iroha, see the following:

For more information on Iroha 1, see the official Hyperledger Iroha documentation.

TIP

If you want to contribute to Hyperledger Iroha, see the Contributing Guide.

',17),s=[o];function h(n,l,c,d,u,g){return r(),a("div",null,s)}const m=e(i,[["render",h]]);export{f as __pageData,m as default}; diff --git a/assets/guide_get-started_index.md.CX985dei.lean.js b/assets/guide_get-started_index.md.CX985dei.lean.js new file mode 100644 index 00000000..3d0e6f7e --- /dev/null +++ b/assets/guide_get-started_index.md.CX985dei.lean.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as r,V as t}from"./chunks/framework.B6c1f-8R.js";const f=JSON.parse('{"title":"Iroha 2","description":"","frontmatter":{},"headers":[],"relativePath":"guide/get-started/index.md","filePath":"guide/get-started/index.md","lastUpdated":1727242778000}'),i={name:"guide/get-started/index.md"},o=t("",17),s=[o];function h(n,l,c,d,u,g){return r(),a("div",null,s)}const m=e(i,[["render",h]]);export{f as __pageData,m as default}; diff --git a/assets/guide_get-started_install-iroha-2.md.BAHP3axq.js b/assets/guide_get-started_install-iroha-2.md.BAHP3axq.js new file mode 100644 index 00000000..bff4d621 --- /dev/null +++ b/assets/guide_get-started_install-iroha-2.md.BAHP3axq.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as s,V as t}from"./chunks/framework.B6c1f-8R.js";const k=JSON.parse('{"title":"Install Iroha 2","description":"","frontmatter":{},"headers":[],"relativePath":"guide/get-started/install-iroha-2.md","filePath":"guide/get-started/install-iroha-2.md","lastUpdated":1727242778000}'),i={name:"guide/get-started/install-iroha-2.md"},l=t('

Install Iroha 2

This tutorial guides you through the steps to install Iroha 2 and its necessary binaries on your machine.

1. Prerequisites

To install Iroha 2, you need to set up the following first:

TIP: How to Install OpenSSL

Note that in most Linux setups OpenSSL is already available to you.

  • Install OpenSSL on Ubuntu:

    bash
    $ sudo apt-get install libssl-dev
  • Install OpenSSL on macOS using brew:

    bash
    $ brew install openssl

Check the OpenSSL installation guide for details.

2. Clone Iroha from GitHub

  1. Create a new directory for Iroha. In this tutorial we use Git as an example, but you can name it anything else:

    bash
    $ mkdir -p ~/Git

    TIP

    On macOS, if you get the fatal: could not create work tree dir 'iroha': Read-only file system error, that is because the home directory is not a real file system.

    To fix this, create a directory named Git.

  2. Enter the directory that you created:

    bash
    $ cd ~/Git
  3. Clone the iroha GitHub repository:

    bash
    $ git clone https://github.com/hyperledger/iroha.git

3. Install Iroha Binaries

To get started you need two of the binaries shipped with Iroha:

  • iroha, the main command line tool for accessing the Iroha network as a user. It allows you to manage domains, accounts, and assets, and to query network status and events. To install iroha system-wide, use the following command:
bash
$ cargo install --git https://github.com/hyperledger/iroha.git iroha_cli
  • kagami, the tool that generates cryotpgraphic keys, configuration files and other necessary data. To install kagami system-wide, use the following command:
bash
$ cargo install --git https://github.com/hyperledger/iroha.git iroha_kagami
',14),o=[l];function r(n,h,p,d,c,g){return s(),e("div",null,o)}const b=a(i,[["render",r]]);export{k as __pageData,b as default}; diff --git a/assets/guide_get-started_install-iroha-2.md.BAHP3axq.lean.js b/assets/guide_get-started_install-iroha-2.md.BAHP3axq.lean.js new file mode 100644 index 00000000..3c409e99 --- /dev/null +++ b/assets/guide_get-started_install-iroha-2.md.BAHP3axq.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as s,V as t}from"./chunks/framework.B6c1f-8R.js";const k=JSON.parse('{"title":"Install Iroha 2","description":"","frontmatter":{},"headers":[],"relativePath":"guide/get-started/install-iroha-2.md","filePath":"guide/get-started/install-iroha-2.md","lastUpdated":1727242778000}'),i={name:"guide/get-started/install-iroha-2.md"},l=t("",14),o=[l];function r(n,h,p,d,c,g){return s(),e("div",null,o)}const b=a(i,[["render",r]]);export{k as __pageData,b as default}; diff --git a/assets/guide_get-started_javascript.md.yo9AwBf0.js b/assets/guide_get-started_javascript.md.yo9AwBf0.js new file mode 100644 index 00000000..54c127d1 --- /dev/null +++ b/assets/guide_get-started_javascript.md.yo9AwBf0.js @@ -0,0 +1,682 @@ +import{_ as s,c as i,o as a,V as n}from"./chunks/framework.B6c1f-8R.js";const t="/iroha-2-docs/assets/sample-vue-app.DgCFT7gr.gif",c=JSON.parse('{"title":"JavaScript/TypeScript Guide","description":"","frontmatter":{},"headers":[],"relativePath":"guide/get-started/javascript.md","filePath":"guide/get-started/javascript.md","lastUpdated":1727242778000}'),h={name:"guide/get-started/javascript.md"},l=n(`

JavaScript/TypeScript Guide

INFO

This guide targets @iroha2/client and @iroha/data-model version ^5.0, which targets Iroha 2 stable (2.0.0-pre-rc.13, c4af68c4f7959b154eb5380aa93c894e2e63fe4e).

INFO

This guide assumes you are familiar with Node.js and NPM ecosystem.

1. Client Installation

The Iroha 2 JavaScript library consists of multiple packages:

PackageDescription
clientSubmits requests to Iroha Peer
data-modelProvides SCALE (Simple Concatenated Aggregate Little-Endian)-codecs for the Iroha 2 Data Model
crypto-coreContains cryptography types
crypto-target-nodeProvides compiled crypto WASM (Web Assembly) for the Node.js environment
crypto-target-webProvides compiled crypto WASM for native Web (ESM)
crypto-target-bundlerProvides compiled crypto WASM to use with bundlers such as Webpack

All of these are published under the @iroha2 scope into Iroha Nexus Registry. In the future, they will be published in the main NPM Registry.

INFO

You can also work with the sources in Iroha Javascript repository, where the active development is happening. Clone the repository and check out the iroha2 branch:

bash
$ git clone https://github.com/hyperledger/iroha-javascript.git --branch iroha2

Please note that this guide does not cover the details of this workflow.

While we've taken great care to decouple the packages, so you could minimise their footprint, for the purposes of this tutorial, it's better to install everything.

The installation consists of two steps: setting up a registry and then installing the packages you need.

  1. Set up a registry. In shell, run:

    bash
    $ echo "@iroha2:registry=https://nexus.iroha.tech/repository/npm-group/" > .npmrc
  2. Install Iroha 2 packages as any other NPM package. If you are following the tutorial, we recommend installing all of the following:

    bash
    $ npm i @iroha2/client
    +$ npm i @iroha2/data-model
    +$ npm i @iroha2/crypto-core
    +$ npm i @iroha2/crypto-target-node
    +$ npm i @iroha2/crypto-target-web
    +$ npm i @iroha2/crypto-target-bundler

    INFO

    Note that you can use other package managers, such as yarn or pnpm, for a faster installation. For example:

    bash
    $ yarn add @iroha2/data-model
    +$ pnpm add @iroha2/crypto-target-web

    The set of packages that you need to install depends on what you are trying to achieve. If you only need to play with the Data Model to perform (de-)serialisation, the data-model package is sufficient. If you need to check on a peer in terms of its status or health, then you only need the client library.

  3. Install the following packages as well:

    bash
    $ npm i hada
    +$ npm i tsx -g
  4. If you are planning to use the Transaction or Query API, you'll also need to inject an appropriate crypto instance into the client at runtime. This has to be adjusted according to your particular environment.

    For example, Node.js users need the following:

    ts
    import { crypto } from '@iroha2/crypto-target-node'
    +import { setCrypto } from '@iroha2/client'
    +
    +setCrypto(crypto)

    INFO

    Please refer to the documentation of the respective @iroha2/crypto-target-* package, because each case has specific configuration steps. For example, the web target needs to be initialised (via asynchronous init()) before you can use any cryptographic methods.

NOTE

When you are creating files in the following steps, you must place them in the same directory that contains node_modules, like so:

╭───┬───────────────────┬──────╮
+│ # │       name        │ type │
+├───┼───────────────────┼──────┤
+│ 0 │ node_modules      │ dir  │
+│ 1 │ addClient.ts      │ file │
+│ 2 │ example.ts        │ file │
+│ 3 │ package.json      │ file │
+│ 4 │ pnpm-lock.yaml    │ file │
+│ 5 │ registerDomain.ts │ file │
+╰───┴───────────────────┴──────╯

We recommend using tsx to run the scripts you've created. For example:

bash
$ tsx example.ts

2. Client Configuration

The JavaScript Client is fairly low-level in a sense that it doesn't expose any convenience features like a TransactionBuilder or a ConfigBuilder.

INFO

The work on implementing those is underway, and these features will very likely be available in the second round of this tutorial's release.

Thus, on the plus side, configuration of the client is simple. On the downside, you have to prepare a lot manually.

You may need to use transactions or queries, so before we initialize the client, let's set up this part. Let's assume that you have stringified public & private keys (more on that later). Thus, a key-pair generation could look like this:

ts
import { crypto } from '@iroha2/crypto-target-node'
+
+const keyPair = crypto.KeyPair.fromJSON({
+  public_key: 'ed0120e555d194e8822da35ac541ce9eec8b45058f4d294d9426ef97ba92698766f7d3',
+  private_key: {
+    digest_function: 'ed25519',
+    payload:
+      'de757bcb79f4c63e8fa0795edc26f86dfdba189b846e903d0b732bb644607720e555d194e8822da35ac541ce9eec8b45058f4d294d9426ef97ba92698766f7d3',
+  },
+})

When you have a key pair, you might create a Signer using the key pair:

ts
import { cryptoTypes } from '@iroha2/crypto-core'
+import { Signer } from '@iroha2/client'
+import { AccountId, DomainId } from '@iroha2/data-model'
+
+// Key pair from previous step
+declare const keyPair: cryptoTypes.KeyPair
+
+const accountId = AccountId({
+  // Account name
+  name: 'alice',
+  // The domain where this account is registered
+  domain_id: DomainId({
+    name: 'wonderland',
+  }),
+})
+
+const signer = new Signer(accountId, keyPair)

Now we're able to make signatures with signer.sign(binary)! However, to interact with Iroha, we need to be able to do more than just sign. We would need to send something to Iroha, like transactions or queries. Torii will help us with that.

Torii handles HTTP / WebSocket communications with Iroha. We will use it to communicate with Iroha endpoints. With the help of Torii we can:

  • Submit transactions with Torii.submit()
  • Send queries with Torii.request()
  • Listen for events with Torii.listenForEvents()
  • Listen for blocks stream with Torii.listenForBlocksStream()
  • and so on

Torii is a stateless object, a compendium of methods. You can look at it as if it is a class with only static methods. Each method has its own requirements to be passed in — some of them only need an HTTP transport and Iroha Torii Telemetry URL, others — a WebSocket transport and Iroha Torii API URL. To better understand how Torii is used, look at this example:

ts
import { Torii } from '@iroha2/client'
+import { VersionedSignedQueryRequest } from '@iroha2/data-model'
+
+// --snip--
+declare const query: VersionedSignedQueryRequest
+
+const result = await Torii.request(
+  {
+    fetch,
+    apiURL: 'http://127.0.0.1:8080',
+  },
+  query,
+)

In this example, we pass fetch (the HTTP transport) and apiURL as the first parameter, and the query itself as the second.

To work with Torii, we need to know Iroha Torii URLs. Our Iroha Peer is configured to listen for API endpoints at http://127.0.0.1:8080 and for telemetry endpoints at http://127.0.0.1:8081. Then, we need to provide appropriate HTTP / WebSocket adapters which Torii will use[1]. These adapters depend on the environment in which you are going to use @iroha2/client.

In Node.js, the full list of Torii requirements (i.e. covering all its methods) will look like this:

ts
import {
+  ToriiRequirementsForApiHttp,
+  ToriiRequirementsForApiWebSocket,
+  ToriiRequirementsForTelemetry,
+} from '@iroha2/client'
+import { adapter as WS } from '@iroha2/client/web-socket/node'
+
+import nodeFetch from 'node-fetch'
+// another alternative
+import { fetch as undiciFetch } from 'undici'
+
+const toriiRequirements: ToriiRequirementsForApiHttp &
+  ToriiRequirementsForApiWebSocket &
+  ToriiRequirementsForTelemetry = {
+  apiURL: 'http://127.0.0.1:8080',
+  telemetryURL: 'http://127.0.0.1:8081',
+  ws: WS,
+  // type assertion is acceptable here
+  // you can pass \`undiciFetch\` here as well
+  fetch: nodeFetch as typeof fetch,
+}

TIP

In the example above, we use node-fetch package which implements Fetch API in Node.js. However, you can use undici as well.

INFO

fetch: nodeFetch as typeof fetch type assertion is acceptable here for a reason. Torii expects the "classic", native fetch function, which is available natively in Browser. However, both node-fetch and undici don't provide fetch that is 100% compatible with the native one. Since Torii doesn't rely on those corner-features that are partially provided by node-fetch and undici, it's fine to ignore the TypeScript error here.

And here is a sample of full Torii in-Browser requirements:

ts
import {
+  ToriiRequirementsForApiHttp,
+  ToriiRequirementsForApiWebSocket,
+  ToriiRequirementsForTelemetry,
+} from '@iroha2/client'
+import { adapter as WS } from '@iroha2/client/web-socket/native'
+
+const toriiRequirements: ToriiRequirementsForApiHttp &
+  ToriiRequirementsForApiWebSocket &
+  ToriiRequirementsForTelemetry = {
+  apiURL: 'http://127.0.0.1:8080',
+  telemetryURL: 'http://127.0.0.1:8081',
+  ws: WS,
+  fetch:
+    // passing globally available \`fetch\`, but binding it to \`window\`
+    // to avoid \`TypeError: "'fetch' called on an
+    //           object that does not implement interface Window."\`
+    fetch.bind(window),
+}

NOTE

We make fetch.bind(window) to avoid TypeError: "'fetch' called on an object that does not implement interface Window.".

Great! Now we have signer and Torii requirements to work with. Finally, we can create a Client:

ts
import { Client, Signer, ToriiRequirementsForApiHttp } from '@iroha2/client'
+import { Executable } from '@iroha2/data-model'
+
+// --snip--
+declare const signer: Signer
+declare const toriiRequirements: ToriiRequirementsForApiHttp
+
+const client = new Client({ signer })
+
+// \`Client\` will sign & wrap \`Executable\` into \`VersionedSignedTransaction\`
+declare const exec: Executable
+await client.submitExecutable(toriiRequirements, exec)

Client provides useful utilities for transactions and queries. You can also use Torii to communicate with the endpoints directly. Signer is accessible with client.signer.

3. Registering a Domain

Here we see how similar the JavaScript code is to the Rust counterpart. It should be emphasised that the JavaScript library is a thin wrapper: It doesn't provide any special builder structures, meaning you have to work with bare-bones compiled Data Model structures and define all internal fields explicitly.

Doubly so, since JavaScript employs many implicit conversions, we highly recommend that you employ TypeScript. This makes many errors far easier to debug, but, unfortunately, results in more boilerplates.

Let's register a new domain named looking_glass using our current account, alice@wondeland.

First, we need to import necessary models and a pre-configured client instance:

ts
import { Client, ToriiRequirementsForApiHttp } from '@iroha2/client'
+import {
+  DomainId,
+  EvaluatesToRegistrableBox,
+  Executable,
+  Expression,
+  IdentifiableBox,
+  Instruction,
+  MapNameValue,
+  Metadata,
+  NewDomain,
+  OptionIpfsPath,
+  QueryBox,
+  RegisterBox,
+  Value,
+  VecInstruction,
+} from '@iroha2/data-model'
+
+// --snip--
+declare const client: Client
+declare const toriiRequirements: ToriiRequirementsForApiHttp

To register a new domain, we need to submit a transaction with a single instruction: to register a new domain. Let's wrap it all in an async function:

ts
async function registerDomain(domainName: string) {
+  const registerBox = RegisterBox({
+    object: EvaluatesToRegistrableBox({
+      expression: Expression(
+        'Raw',
+        Value(
+          'Identifiable',
+          IdentifiableBox(
+            'NewDomain',
+            NewDomain({
+              id: DomainId({
+                name: domainName, 
+              }),
+              metadata: Metadata({ map: MapNameValue(new Map()) }),
+              logo: OptionIpfsPath('None'),
+            }),
+          ),
+        ),
+      ),
+    }),
+  })
+
+  await client.submitExecutable(
+    toriiRequirements,
+    Executable('Instructions', VecInstruction([Instruction('Register', registerBox)])),
+  )
+}

Which we use to register the domain like so:

ts
await registerDomain('looking_glass')

We can also use Query API to ensure that the new domain is created. Let's create another function that wraps that functionality:

ts
async function ensureDomainExistence(domainName: string) {
+  // Query all domains
+  const result = await client.requestWithQueryBox(
+    toriiRequirements,
+    QueryBox('FindAllDomains', null),
+  )
+
+  // Display the request status
+  console.log('%o', result)
+
+  // Obtain the domain
+  const domain = result
+    .as('Ok')
+    .result.enum.as('Vec')
+    .map((x) => x.enum.as('Identifiable').enum.as('Domain'))
+    .find((x) => x.id.name === domainName) 
+
+  // Throw an error if the domain is unavailable
+  if (!domain) throw new Error('Not found')
+}

Now you can ensure that domain is created by calling:

ts
await ensureDomainExistence('looking_glass')

4. Registering an Account

Registering an account is a bit more involved than registering a domain. With a domain, the only concern is the domain name. However, with an account, there are a few more things to worry about.

First of all, we need to create an AccountId. Note that we can only register an account to an existing domain. The best UX design practices dictate that you should check if the requested domain exists now, and if it doesn't, suggest a fix to the user. After that, we can create a new account named white_rabbit.

Imports we need:

ts
import {
+  AccountId,
+  DomainId,
+  EvaluatesToRegistrableBox,
+  Expression,
+  IdentifiableBox,
+  Instruction,
+  MapNameValue,
+  Metadata,
+  NewAccount,
+  PublicKey,
+  RegisterBox,
+  Value,
+  VecPublicKey,
+} from '@iroha2/data-model'

The AccountId structure:

ts
const accountId = AccountId({
+  name: 'white_rabbit',
+  domain_id: DomainId({
+    name: 'looking_glass',
+  }),
+})

Second, you should provide the account with a public key. It is tempting to generate both it and the private key at this time, but it isn't the brightest idea. Remember that the white_rabbit trusts you, alice@wonderland, to create an account for them in the domain looking_glass, but doesn't want you to have access to that account after creation.

If you gave white_rabbit a key that you generated yourself, how would they know if you don't have a copy of their private key? Instead, the best way is to ask white_rabbit to generate a new key-pair, and give you the public half of it.

ts
const pubKey = PublicKey({
+  payload: new Uint8Array([
+    /* put bytes here */
+  ]),
+  digest_function: 'some_digest',
+})

Only then do we build an instruction from it:

ts
const registerAccountInstruction = Instruction(
+  'Register',
+  RegisterBox({
+    object: EvaluatesToRegistrableBox({
+      expression: Expression(
+        'Raw',
+        Value(
+          'Identifiable',
+          IdentifiableBox(
+            'NewAccount',
+            NewAccount({
+              id: accountId, 
+              signatories: VecPublicKey([pubKey]),
+              metadata: Metadata({ map: MapNameValue(new Map()) }),
+            }),
+          ),
+        ),
+      ),
+    }),
+  }),
+)

Which is then wrapped in a transaction and submitted to the peer the same way as in the previous section when we registered a domain.

5. Registering and minting assets

Iroha has been built with few underlying assumptions about what the assets need to be in terms of their value type and characteristics (fungible or non-fungible, mintable or non-mintable).

In JS, you can create a new asset with the following construction:

ts
import {
+  AssetDefinition,
+  AssetDefinitionId,
+  AssetValueType,
+  DomainId,
+  EvaluatesToRegistrableBox,
+  Expression,
+  IdentifiableBox,
+  Instruction,
+  MapNameValue,
+  Metadata,
+  Mintable,
+  RegisterBox,
+  Value,
+} from '@iroha2/data-model'
+
+const time = AssetDefinition({
+  value_type: AssetValueType('Quantity'),
+  id: AssetDefinitionId({
+    name: 'time',
+    domain_id: DomainId({ name: 'looking_glass' }),
+  }),
+  metadata: Metadata({ map: MapNameValue(new Map()) }),
+  mintable: Mintable('Infinitely'), // If only we could mint more time.
+})
+
+const register = Instruction(
+  'Register',
+  RegisterBox({
+    object: EvaluatesToRegistrableBox({
+      expression: Expression(
+        'Raw',
+        Value('Identifiable', IdentifiableBox('AssetDefinition', time)), 
+      ),
+    }),
+  }),
+)

Pay attention to the fact that we have defined the asset as Mintable('Not'). What this means is that we cannot create more of time. The late bunny will always be late, because even the super-user of the blockchain cannot mint more of time than already exists in the genesis block.

This means that no matter how hard the white_rabbit tries, the time that he has is the time that was given to him at genesis. And since we haven't defined any time in the domain looking_glass at genesis and defined time in a non-mintable fashion afterwards, the white_rabbit is doomed to always be late.

If we had set mintable: Mintable('Infinitely') on our time asset, we could mint it:

ts
import {
+  AccountId,
+  AssetDefinitionId,
+  AssetId,
+  DomainId,
+  EvaluatesToIdBox,
+  EvaluatesToValue,
+  Expression,
+  IdBox,
+  Instruction,
+  MintBox,
+  NumericValue,
+  Value,
+} from '@iroha2/data-model'
+
+const mint = Instruction(
+  'Mint',
+  MintBox({
+    object: EvaluatesToValue({
+      expression: Expression('Raw', Value('Numeric', NumericValue('U32', 42))),
+    }),
+    destination_id: EvaluatesToIdBox({
+      expression: Expression(
+        'Raw',
+        Value(
+          'Id',
+          IdBox(
+            'AssetId',
+            AssetId({
+              account_id: AccountId({
+                name: 'alice',
+                domain_id: DomainId({
+                  name: 'wonderland',
+                }),
+              }),
+              definition_id: AssetDefinitionId({
+                name: 'time',
+                domain_id: DomainId({ name: 'looking_glass' }),
+              }),
+            }),
+          ),
+        ),
+      ),
+    }),
+  }),
+)

Again it should be emphasised that an Iroha 2 network is strongly typed. You need to take special care to make sure that only unsigned integers are passed to the Value('U32', ...) factory method. Fixed precision values also need to be taken into consideration. Any attempt to add to or subtract from a negative Fixed-precision value will result in an error.

6. Transferring assets

After minting the assets, you can transfer them to another account. In the example below, Alice transfers to Mouse 100 units of time asset:

ts
import {
+  AccountId,
+  AssetDefinitionId,
+  AssetId,
+  DomainId,
+  EvaluatesToIdBox,
+  EvaluatesToValue,
+  Expression,
+  IdBox,
+  Instruction,
+  NumericValue,
+  TransferBox,
+  Value,
+} from '@iroha2/data-model'
+
+const domainId = DomainId({
+  name: 'wonderland',
+})
+
+const assetDefinitionId = AssetDefinitionId({
+  name: 'time',
+  domain_id: domainId,
+})
+
+const amountToTransfer = Value('Numeric', NumericValue('U32', 100))
+
+const fromAccount = AccountId({
+  name: 'alice',
+  domain_id: domainId,
+})
+
+const toAccount = AccountId({
+  name: 'mouse',
+  domain_id: domainId,
+})
+
+const evaluatesToAssetId = (assetId: AssetId): EvaluatesToIdBox =>
+  EvaluatesToIdBox({
+    expression: Expression('Raw', Value('Id', IdBox('AssetId', assetId))),
+  })
+
+const transferAssetInstruction = Instruction(
+  'Transfer',
+  TransferBox({
+    source_id: evaluatesToAssetId(
+      AssetId({
+        definition_id: assetDefinitionId,
+        account_id: fromAccount,
+      }),
+    ),
+    destination_id: evaluatesToAssetId(
+      AssetId({
+        definition_id: assetDefinitionId,
+        account_id: toAccount,
+      }),
+    ),
+    object: EvaluatesToValue({
+      expression: Expression('Raw', amountToTransfer),
+    }),
+  }),
+)

7. Querying for Domains, Accounts and Assets

TODO

ts
import { Client, ToriiRequirementsForApiHttp } from '@iroha2/client'
+import { QueryBox } from '@iroha2/data-model'
+
+declare const client: Client
+declare const toriiRequirements: ToriiRequirementsForApiHttp
ts
const result = await client.requestWithQueryBox(
+  toriiRequirements,
+  QueryBox('FindAllDomains', null),
+)
+
+const domains = result
+  .as('Ok')
+  .result.enum.as('Vec')
+  .map((x) => x.enum.as('Identifiable').enum.as('Domain'))
+
+for (const domain of domains) {
+  console.log(
+    \`Domain "\${domain.id.name}" has \${domain.accounts.size} accounts\` +
+      \` and \${domain.asset_definitions.size} asset definitions\`,
+  )
+  // => Domain "wonderland" has 5 accounts and 3 asset definitions
+}
ts
const result = await client.requestWithQueryBox(
+  toriiRequirements,
+  QueryBox('FindAllAccounts', null),
+)
+
+const accounts = result
+  .as('Ok')
+  .result.enum.as('Vec')
+  .map((x) => x.enum.as('Identifiable').enum.as('Account'))
+
+for (const account of accounts) {
+  console.log(
+    \`Account "\${account.id.name}@\${account.id.domain_id.name}" \` +
+      \`has \${account.assets.size} assets\`,
+  )
+  // => Account "alice@wonderland" has 3 assets
+}
ts
const result = await client.requestWithQueryBox(
+  toriiRequirements,
+  QueryBox('FindAllAssets', null),
+)
+
+const assets = result
+  .as('Ok')
+  .result.enum.as('Vec')
+  .map((x) => x.enum.as('Identifiable').enum.as('Asset'))
+
+for (const asset of assets) {
+  console.log(
+    \`Asset "\${asset.id.definition_id.name}#\${asset.id.definition_id.domain_id.name}" \` +
+      \`at account "\${asset.id.account_id.name}@\${asset.id.account_id.domain_id.name}" \` +
+      \`has type "\${asset.value.enum.tag}"\`,
+  )
+  // => Asset "rose#wonderland" at account "alice@wonderland" has type "Quantity"
+}

8. Visualizing outputs in Web UI

Finally, we should talk about visualising data. The Rust API is currently the most complete in terms of available queries and instructions. After all, this is the language in which Iroha 2 was built.

Let's build a small Vue 3 application that uses each API we've discovered in this guide!

TIP

In this guide, we are roughly recreating the project that is a part of iroha-javascript integration tests. If you want to see the full project, please refer to the @iroha2/client-test-web sources.

Our app will consist of 3 main views:

  • Status checker that periodically requests peer status (e.g. current blocks height) and shows it;
  • Domain creator, which is a form to create a new domain with specified name;
  • Listener with a toggle to setup listening for events.

You can use this folder structure as a reference:

╭───┬──────────────────────────────╮
+│ # │             name             │
+├───┼──────────────────────────────┤
+│ 0 │ App.vue                      │
+│ 1 │ client.ts                    │
+│ 2 │ components/CreateDomain.vue  │
+│ 3 │ components/Listener.vue      │
+│ 4 │ components/StatusChecker.vue │
+│ 5 │ config.json                  │
+│ 6 │ crypto.ts                    │
+│ 7 │ main.ts                      │
+╰───┴──────────────────────────────╯
json
{
+  "torii": {
+    "apiURL": "http://127.0.0.1:8080",
+    "telemetryURL": "http://127.0.0.1:8081"
+  },
+  "account": {
+    "name": "alice",
+    "domain_id": {
+      "name": "wonderland"
+    }
+  },
+  "public_key": "ed01207233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0",
+  "private_key": {
+    "digest_function": "ed25519",
+    "payload": "9ac47abf59b356e0bd7dcbbbb4dec080e302156a48ca907e47cb6aea1d32719e7233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0"
+  }
+}
ts
import { crypto, init } from '@iroha2/crypto-target-web'
+
+await init()
+
+export { crypto }
ts
import { Client, Signer } from '@iroha2/client'
+import { adapter as WS } from '@iroha2/client/web-socket/native'
+import { crypto } from './crypto'
+import { client_config } from '../../config'
+import { AccountId } from '@iroha2/data-model'
+
+const HOST = window.location.host
+
+export const toriiPre = {
+  // proxified with vite
+  apiURL: \`http://\${HOST}/torii/api\`,
+  telemetryURL: \`http://\${HOST}/torii/telemetry\`,
+  ws: WS,
+  fetch: fetch.bind(window),
+}
+
+const signer = new Signer(client_config.account as AccountId, crypto.KeyPair.fromJSON(client_config))
+
+export const client = new Client({ signer })
vue
<script setup lang="ts">
+import { useIntervalFn } from '@vueuse/core'
+import { useStaleState, useTask } from '@vue-kakuyaku/core'
+import { toriiPre } from '../client'
+import { Torii } from '@iroha2/client'
+
+const { state, run } = useTask(() => Torii.getStatus(toriiPre), { immediate: true })
+const stale = useStaleState(state)
+useIntervalFn(run, 1000)
+</script>
+
+<template>
+  <div>
+    <h3>Status</h3>
+
+    <ul v-if="stale.fulfilled">
+      <li>Blocks: {{ stale.fulfilled.value.blocks }}</li>
+      <li>Uptime (sec): {{ stale.fulfilled.value.uptime.secs }}</li>
+    </ul>
+  </div>
+</template>
vue
<script setup lang="ts">
+import {
+  DomainId,
+  EvaluatesToRegistrableBox,
+  Executable,
+  Expression,
+  IdentifiableBox,
+  Instruction,
+  MapNameValue,
+  Metadata,
+  NewDomain,
+  OptionIpfsPath,
+  RegisterBox,
+  Value,
+  VecInstruction,
+} from '@iroha2/data-model'
+import { ref } from 'vue'
+import { client, toriiPre } from '../client'
+import { useTask } from '@vue-kakuyaku/core'
+
+const domainName = ref('')
+
+const { state, run: registerDomain } = useTask(async () => {
+  await client.submitExecutable(
+    toriiPre,
+    Executable(
+      'Instructions',
+      VecInstruction([
+        Instruction(
+          'Register',
+          RegisterBox({
+            object: EvaluatesToRegistrableBox({
+              expression: Expression(
+                'Raw',
+                Value(
+                  'Identifiable',
+                  IdentifiableBox(
+                    'NewDomain',
+                    NewDomain({
+                      id: DomainId({
+                        name: domainName.value,
+                      }),
+                      metadata: Metadata({ map: MapNameValue(new Map()) }),
+                      logo: OptionIpfsPath('None'),
+                    }),
+                  ),
+                ),
+              ),
+            }),
+          }),
+        ),
+      ]),
+    ),
+  )
+})
+</script>
+
+<template>
+  <div>
+    <h3>Create Domain</h3>
+    <p>
+      <label for="domain">New domain name:</label> <input
+        id="domain"
+        v-model="domainName"
+      >
+    </p>
+    <p>
+      <button @click="registerDomain()">
+        Register domain{{ state.pending ? '...' : '' }}
+      </button>
+    </p>
+  </div>
+</template>
vue
<script setup lang="ts">
+import { SetupEventsReturn, Torii } from '@iroha2/client'
+import {
+  FilterBox,
+  OptionHash,
+  OptionPipelineEntityKind,
+  OptionPipelineStatusKind,
+  PipelineEntityKind,
+  PipelineEventFilter,
+  PipelineStatus,
+  PipelineStatusKind,
+} from '@iroha2/data-model'
+import { computed, onBeforeUnmount, shallowReactive, shallowRef } from 'vue'
+import { toriiPre } from '../client'
+
+function bytesToHex(bytes: number[]): string {
+  return bytes.map((byte) => byte.toString(16).padStart(2, '0')).join('')
+}
+
+interface EventData {
+  hash: string
+  status: string
+}
+
+const events = shallowReactive<EventData[]>([])
+
+const currentListener = shallowRef<null | SetupEventsReturn>(null)
+
+const isListening = computed(() => !!currentListener.value)
+
+function displayStatus(status: PipelineStatus): string {
+  switch (status.enum.tag) {
+    case 'Validating':
+      return 'validating'
+    case 'Committed':
+      return 'committed'
+    case 'Rejected':
+      return 'rejected with some reason'
+  }
+}
+
+async function startListening() {
+  currentListener.value = await Torii.listenForEvents(toriiPre, {
+    filter: FilterBox(
+      'Pipeline',
+      PipelineEventFilter({
+        entity_kind: OptionPipelineEntityKind('Some', PipelineEntityKind('Transaction')),
+        status_kind: OptionPipelineStatusKind('Some', PipelineStatusKind('Committed')),
+        hash: OptionHash('None'),
+      }),
+    ),
+  })
+
+  currentListener.value.ee.on('event', (event) => {
+    const { hash, status } = event.enum.as('Pipeline')
+    events.push({
+      hash: bytesToHex([...hash]),
+      status: displayStatus(status),
+    })
+  })
+}
+
+async function stopListening() {
+  await currentListener.value?.stop()
+  currentListener.value = null
+}
+
+onBeforeUnmount(stopListening)
+</script>
+
+<template>
+  <div>
+    <h3>Listening</h3>
+
+    <p>
+      <button @click="isListening ? stopListening() : startListening()">
+        {{ isListening ? 'Stop' : 'Listen' }}
+      </button>
+    </p>
+
+    <p>Events:</p>
+
+    <ul class="events-list">
+      <li
+        v-for="{ hash, status } in events"
+        :key="hash"
+      >
+        Transaction <code>{{ hash }}</code> status:
+        {{ status }}
+      </li>
+    </ul>
+  </div>
+</template>
vue
<script setup lang="ts">
+import CreateDomain from './components/CreateDomain.vue'
+import EventListener from './components/EventListener.vue'
+import StatusChecker from './components/StatusChecker.vue'
+</script>
+
+<template>
+  <StatusChecker />
+  <hr>
+  <CreateDomain />
+  <hr>
+  <EventListener />
+</template>
+
+<style lang="scss">
+#app {
+  padding: 16px;
+  font-family: sans-serif;
+}
+</style>
ts
import { createApp } from 'vue'
+import App from './App.vue'
+import { Logger } from '@iroha2/data-model'
+import { crypto } from './crypto'
+import { setCrypto } from '@iroha2/client'
+
+setCrypto(crypto)
+new Logger().mount()
+localStorage.debug = '*'
+
+createApp(App).mount('#app')

INFO

In client.ts, we import the configuration file like this:

ts
import { client_config } from '../../config'

Note that you need to import the config in this way because this is how the source code of this application works. You can interpret this line as import client_config from 'config.json'.

Demo

Here is a small demo with the usage of this component:

Demo of the sample Vue application

9. Subscribing to Block Stream

You can use /block/stream endpoint to send a subscription request for block streaming.

Via this endpoint, the client first provides the starting block number (i.e. height) in the subscription request. After sending the confirmation message, the server starts streaming all the blocks from the given block number up to the current block, and continues to stream blocks as they are added to the blockchain.

Here is an example of how to listen to the block stream:

ts
import { Torii, ToriiRequirementsForApiWebSocket } from '@iroha2/client'
+
+declare const requirements: ToriiRequirementsForApiWebSocket
+
+const stream = await Torii.listenForBlocksStream(requirements, {
+  height: 0n,
+})
+
+stream.ee.on('block', (block) => {
+  const height = block.enum.as('V1').header.height
+  console.log('Got block with height', height)
+})

  1. We have to pass environment-specific ws and fetch, because there is no way for Iroha Client to communicate with a peer in an environment-agnostic way. ↩︎

`,100),p=[l];function k(e,E,r,d,g,y){return a(),i("div",null,p)}const F=s(h,[["render",k]]);export{c as __pageData,F as default}; diff --git a/assets/guide_get-started_javascript.md.yo9AwBf0.lean.js b/assets/guide_get-started_javascript.md.yo9AwBf0.lean.js new file mode 100644 index 00000000..216b7b84 --- /dev/null +++ b/assets/guide_get-started_javascript.md.yo9AwBf0.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,V as n}from"./chunks/framework.B6c1f-8R.js";const t="/iroha-2-docs/assets/sample-vue-app.DgCFT7gr.gif",c=JSON.parse('{"title":"JavaScript/TypeScript Guide","description":"","frontmatter":{},"headers":[],"relativePath":"guide/get-started/javascript.md","filePath":"guide/get-started/javascript.md","lastUpdated":1727242778000}'),h={name:"guide/get-started/javascript.md"},l=n("",100),p=[l];function k(e,E,r,d,g,y){return a(),i("div",null,p)}const F=s(h,[["render",k]]);export{c as __pageData,F as default}; diff --git a/assets/guide_get-started_kotlin-java.md.BJnusMRj.js b/assets/guide_get-started_kotlin-java.md.BJnusMRj.js new file mode 100644 index 00000000..abe07149 --- /dev/null +++ b/assets/guide_get-started_kotlin-java.md.BJnusMRj.js @@ -0,0 +1,485 @@ +import{_ as s,c as i,o as a,V as n}from"./chunks/framework.B6c1f-8R.js";const t="/iroha-2-docs/assets/iroha_java_hash.CWG7jGmi.png",h="/iroha-2-docs/assets/iroha_java_commits.DtyotM0c.png",c=JSON.parse('{"title":"Kotlin/Java Guide","description":"","frontmatter":{},"headers":[],"relativePath":"guide/get-started/kotlin-java.md","filePath":"guide/get-started/kotlin-java.md","lastUpdated":1727242778000}'),l={name:"guide/get-started/kotlin-java.md"},k=n(`

Kotlin/Java Guide

1. Iroha 2 Client Setup

In this part we shall cover the main things to look out for if you want to use Iroha 2 in your Kotlin application. Instead of providing the complete basics, we shall assume knowledge of the most widely used concepts, explain the unusual, and provide some instructions for creating your own Iroha 2-compatible client.

We assume that you know how to create a new package and have basic understanding of the fundamental Kotlin code. Specifically, we shall assume that you know how to build and deploy your program on the target platforms. To clone Iroha 2 JVM compatible SDKs, you can use Iroha Java.

Without further ado, here's a part of an example build.gradle.kts file, specifically, the plugins, repositories and dependencies sections:

kotlin
plugins {
+    kotlin("jvm") version "1.6.10"
+    application
+}
+
+group = "jp.co.soramitsu"
+version = "1.0-SNAPSHOT"
+
+repositories {
+    mavenCentral()
+    maven(url = "https://jitpack.io")
+}
+
+dependencies {
+    val iroha2Ver by System.getProperties()
+
+    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0")
+    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.0")
+
+    api("com.github.hyperledger.iroha-java:admin-client:SNAPSHOT")
+    implementation("com.github.hyperledger.iroha-java:model:SNAPSHOT")
+    implementation("com.github.hyperledger.iroha-java:block:SNAPSHOT")
+
+    implementation("net.i2p.crypto:eddsa:0.3.0")
+    implementation("org.bouncycastle:bcprov-jdk15on:1.65")
+    implementation("com.github.multiformats:java-multihash:1.3.0")
+}

You should replace the SNAPSHOT in the above configuration with the latest iroha-java snapshot.

Snapshot versions match the Git commits. To get the latest snapshot, simply visit the iroha-java repository on the iroha-2-dev branch and copy the short hash of the last commit on the main page.

You can also check the commit history and copy the commit hash of a previous commit.

This will give you the latest development release of Iroha 2.

2. Configuring Iroha 2

At present, the Kotlin SDK doesn't have any classes to interact with the configuration. Instead, you are provided with a ready-made Iroha2Client that reads the configuration from the environment variables and/or the resident config.json in the working directory.

If you are so inclined, you can have a look at the testcontainers module, and see how the Iroha2Config is implemented.

kotlin
package jp.co.soramitsu.iroha2.testengine
+
+import jp.co.soramitsu.iroha2.DEFAULT_API_PORT
+import jp.co.soramitsu.iroha2.DEFAULT_P2P_PORT
+import jp.co.soramitsu.iroha2.DEFAULT_TELEMETRY_PORT
+import jp.co.soramitsu.iroha2.Genesis
+import jp.co.soramitsu.iroha2.generateKeyPair
+import jp.co.soramitsu.iroha2.generated.datamodel.peer.PeerId
+import jp.co.soramitsu.iroha2.toIrohaPublicKey
+import org.slf4j.LoggerFactory.getLogger
+import org.testcontainers.containers.Network
+import org.testcontainers.containers.Network.newNetwork
+import org.testcontainers.containers.output.OutputFrame
+import org.testcontainers.containers.output.Slf4jLogConsumer
+import org.testcontainers.images.ImagePullPolicy
+import org.testcontainers.images.PullPolicy
+import java.security.KeyPair
+import java.time.Duration
+import java.util.function.Consumer
+
+/**
+ * Iroha configuration
+ */
+class IrohaConfig(
+    var networkToJoin: Network = newNetwork(),
+    var logConsumer: Consumer<OutputFrame> = Slf4jLogConsumer(getLogger(IrohaContainer::class.java)),
+    var genesis: Genesis = Genesis.getEmpty(),
+    var imageTag: String = IrohaContainer.DEFAULT_IMAGE_TAG,
+    var imageName: String = IrohaContainer.DEFAULT_IMAGE_NAME,
+    var pullPolicy: ImagePullPolicy = PullPolicy.ageBased(Duration.ofMinutes(10)),
+    var alias: String = IrohaContainer.NETWORK_ALIAS + DEFAULT_P2P_PORT,
+    var keyPair: KeyPair = generateKeyPair(),
+    var trustedPeers: List<PeerId> = listOf(
+        PeerId(
+            "$alias:$DEFAULT_P2P_PORT",
+            keyPair.public.toIrohaPublicKey()
+        )
+    ),
+    var ports: List<Int> = listOf(DEFAULT_P2P_PORT, DEFAULT_API_PORT, DEFAULT_TELEMETRY_PORT),
+    var shouldCloseNetwork: Boolean = true,
+    var waitStrategy: Boolean = true,
+    var submitGenesis: Boolean = true
+) {
+    companion object {
+        const val P2P_PORT_IDX = 0
+        const val API_PORT_IDX = 1
+        const val TELEMETRY_PORT_IDX = 2
+    }
+}

3. Querying and Registering Domains

Querying and Registering a domain are easier operations. The usual boilerplate code, that often only serves to instantiate a client from an on-disk configuration file, is unnecessary. We will immediately add all the necessary imports to implement this client:

kotlin
import jp.co.soramitsu.iroha2.*
+import jp.co.soramitsu.iroha2.generated.crypto.PublicKey
+import jp.co.soramitsu.iroha2.generated.datamodel.Value
+import jp.co.soramitsu.iroha2.generated.datamodel.account.AccountId
+import jp.co.soramitsu.iroha2.generated.datamodel.asset.AssetValue
+import jp.co.soramitsu.iroha2.generated.datamodel.asset.AssetValueType
+import jp.co.soramitsu.iroha2.generated.datamodel.asset.Mintable
+import jp.co.soramitsu.iroha2.generated.datamodel.metadata.Metadata
+import jp.co.soramitsu.iroha2.generated.datamodel.name.Name
+import jp.co.soramitsu.iroha2.generated.datamodel.predicate.GenericValuePredicateBox
+import jp.co.soramitsu.iroha2.generated.datamodel.predicate.value.ValuePredicate
+import jp.co.soramitsu.iroha2.query.QueryBuilder
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.withTimeout
+import java.net.URL
+import java.security.KeyPair

We shall write this example in the form of a test class, hence the presence of test-related packages. Note the presence of coroutines.runBlocking. Iroha makes extensive use of asynchronous programming (in Rust terminology), hence blocking is not necessarily the only mode of interaction with the Iroha 2 code.

In order to make sure that the raised peers work correctly, you can do a simple operation to get all registered domains.

Next, we will add wrappers to the classes created in this section.

kotlin
fun main(args: Array<String>): Unit = runBlocking{
+    val peerUrl = "http://127.0.0.1:8080"
+    val telemetryUrl = "http://127.0.0.1:8180"
+    val admin = AccountId("bob".asName(), "wonderland".asDomainId())
+    val adminKeyPair = keyPairFromHex("7233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0",
+        "9ac47abf59b356e0bd7dcbbbb4dec080e302156a48ca907e47cb6aea1d32719e")
+
+    val client = AdminIroha2Client(URL(peerUrl), URL(telemetryUrl), log = true)
+    val query = Query(client, admin, adminKeyPair)
+
+    query.findAllDomains()
+        .also { println("ALL DOMAINS: \${it.map { d -> d.id.asString() }}") }
+
+}
+
+open class Query (private val client: AdminIroha2Client,
+                  private val admin: AccountId,
+                  private val keyPair: KeyPair) {
+    
+    suspend fun findAllDomains(queryFilter: GenericValuePredicateBox<ValuePredicate>? = null) = QueryBuilder
+        .findAllDomains(queryFilter)
+        .account(admin)
+        .buildSigned(keyPair)
+        .let { client.sendQuery(it) }
+}

The output in the terminal will contain a list of all domains that are currently registered.

Expand to see the expected output
ALL DOMAINS: [wonderland, genesis, garden_of_live_flowers]

To register a new domain, add the following lines to Main.kt:

kotlin
val sendTransaction = SendTransaction(client, admin, adminKeyPair)
+
+val domain = "looking_glass_\${System.currentTimeMillis()}"
+    sendTransaction.registerDomain(domain).also { println("DOMAIN $domain CREATED") }

Then create new open class SendTransaction in your project:

kotlin
open class SendTransaction (private val client: AdminIroha2Client,
+                            private val admin: AccountId,
+                            private val keyPair: KeyPair,
+                            private val timeout: Long = 10000) {
+
+    suspend fun registerDomain(
+        id: String,
+        metadata: Map<Name, Value> = mapOf(),
+        admin: AccountId = this.admin,
+        keyPair: KeyPair = this.keyPair
+    ) {
+        client.sendTransaction {
+            account(admin)
+            this.registerDomain(id.asDomainId(), metadata)
+            buildSigned(keyPair)
+        }.also {
+            withTimeout(timeout) { it.await() }
+        }
+    }
+}
Expand to see the expected output
DOMAIN looking_glass CREATED
+ALL DOMAINS: [looking_glass, garden_of_live_flowers, genesis, wonderland]

4. Registering an Account

Registering an account is more involved than the aforementioned functions. Previously, we only had to worry about submitting a single instruction, with a single string-based registration box (in Rust terminology, the heap-allocated reference types are all called boxes).

When registering an account, there are a few more variables. The account can only be registered to an existing domain. Also, an account typically has to have a key pair.

To register a new account, add the following lines to Main.kt:

Kotlin
    val madHatter = "madHatter_\${System.currentTimeMillis()}$ACCOUNT_ID_DELIMITER$domain"
+    val madHatterKeyPair = generateKeyPair()
+    sendTransaction.registerAccount(madHatter, listOf(madHatterKeyPair.public.toIrohaPublicKey()))
+        .also { println("ACCOUNT $madHatter CREATED") }
+
+    query.findAllAccounts()
+        .also { println("ALL ACCOUNTS: \${it.map { a -> a.id.asString() }}") }

Then implement new method for class SendTransaction in your project.

Kotlin
    suspend fun registerAccount(
+        id: String,
+        signatories: List<PublicKey>,
+        metadata: Map<Name, Value> = mapOf(),
+        admin: AccountId = this.admin,
+        keyPair: KeyPair = this.keyPair
+    ) {
+        client.sendTransaction {
+            account(admin)
+            this.registerAccount(id.asAccountId(), signatories, Metadata(metadata))
+            buildSigned(keyPair)
+        }.also {
+            withTimeout(timeout) { it.await() }
+        }
+    }

Also, a new method has been added to the Query class.

Kotlin
    suspend fun findAllAccounts(queryFilter: GenericValuePredicateBox<ValuePredicate>? = null) = QueryBuilder
+        .findAllAccounts(queryFilter)
+        .account(admin)
+        .buildSigned(keyPair)
+        .let {
+            client.sendQuery(it)
+    }
Expand to see the expected output
DOMAIN looking_glass_1684835731653 CREATED
+ALL DOMAINS: [looking_glass, garden_of_live_flowers, genesis, wonderland, looking_glass_1684835731653]
+ACCOUNT madHatter_1684835733686@looking_glass_1684835731653 CREATED
+ALL ACCOUNTS: [carpenter@garden_of_live_flowers, genesis@genesis, alice@wonderland, bob@wonderland, madHatter_1684835733686@looking_glass_1684835731653]

As you can see, for illustrative purposes, we have generated a new key-pair. We converted that key-pair into an Iroha-compatible format using toIrohaPublicKey, and added the public key to the instruction to register an account.

5. Registering and minting assets

Iroha has been built with few underlying assumptions about what the assets need to be in terms of their value type and characteristics (fungible or non-fungible, mintable or non-mintable).

INFO

The non-mintable assets are a relatively recent addition to Iroha 2, thus registering and minting such assets is not presently possible through the Kotlin SDK.

To register new assets definition, add the following lines of code to main

Kotlin
    val assetDefinition = "asset_time_\${System.currentTimeMillis()}$ASSET_ID_DELIMITER$domain"
+    sendTransaction.registerAssetDefinition(assetDefinition, AssetValueType.Quantity())
+        .also { println("ASSET DEFINITION $assetDefinition CREATED") }

Then implement new method for class SendTransaction in your project.

Kotlin
    suspend fun registerAssetDefinition(
+        id: String,
+        type: AssetValueType = AssetValueType.Store(),
+        metadata: Map<Name, Value> = mapOf(),
+        mintable: Mintable = Mintable.Infinitely(),
+        admin: AccountId = this.admin,
+        keyPair: KeyPair = this.keyPair
+    ) {
+        client.sendTransaction {
+            account(admin)
+            this.registerAssetDefinition(id.asAssetDefinitionId(), type, Metadata(metadata), mintable)
+            buildSigned(keyPair)
+        }.also {
+            withTimeout(timeout) { it.await() }
+        }
+    }

To mint new assets, add the following lines of code to main

Kotlin
    val madHatterAsset = "$assetDefinition$ASSET_ID_DELIMITER$madHatter"
+    sendTransaction.registerAsset(madHatterAsset, AssetValue.Quantity(100))
+        .also { println("ASSET $madHatterAsset CREATED") }

Then implement new method for class SendTransaction in your project.

Kotlin
    suspend fun registerAsset(
+        id: String,
+        value: AssetValue,
+        admin: AccountId = this.admin,
+        keyPair: KeyPair = this.keyPair
+        ) {
+        client.sendTransaction {
+            account(admin)
+            this.registerAsset(id.asAssetId(), value)
+            buildSigned(keyPair)
+        }.also {
+            withTimeout(timeout) { it.await() }
+            }
+        }

To check the result, add the following line of code to the class main

Kotlin
    query.findAllAssets()
+        .also { println("ALL ASSETS: \${it.map { a -> a.id.asString() }}") }

Also, a new method has been added to the open class Query

Kotlin
    suspend fun findAllAssets(queryFilter: GenericValuePredicateBox<ValuePredicate>? = null) = QueryBuilder
+        .findAllAssets(queryFilter)
+        .account(admin)
+        .buildSigned(keyPair)
+        .let { client.sendQuery(it) }
Expand to see the expected output
DOMAIN looking_glass_1684842996549 CREATED
+ALL DOMAINS: [looking_glass, garden_of_live_flowers, genesis, looking_glass_1684842996549, wonderland, looking_glass_1684835731653]
+ACCOUNT madHatter_1684842997930@looking_glass_1684842996549 CREATED
+ALL ACCOUNTS: [carpenter@garden_of_live_flowers, genesis@genesis, madHatter_1684842997930@looking_glass_1684842996549, alice@wonderland, bob@wonderland, madHatter_1684835733686@looking_glass_1684835731653]
+ASSET DEFINITION asset_time_1684842998891#looking_glass_1684842996549 CREATED
+ASSET asset_time_1684842998891#looking_glass_1684842996549#madHatter_1684842997930@looking_glass_1684842996549 CREATED
+ALL ASSETS: [asset_time_1684842998891#looking_glass_1684842996549#madHatter_1684842997930@looking_glass_1684842996549, cabbage#garden_of_live_flowers#alice@wonderland, rose#wonderland#alice@wonderland]\`\`\`

6. Transferring assets

After we have registered and minted madHatter's assets, let's transfer some of them to another blockchain user. To do this, we will create a new user, register their asset with the main method and add transfer operations for the asset.

Kotlin
    val whiteRabbit = "whiteRabbit_\${System.currentTimeMillis()}$ACCOUNT_ID_DELIMITER$domain"
+    val whiteRabbitKeyPair = generateKeyPair()
+    sendTransaction.registerAccount(whiteRabbit, listOf(whiteRabbitKeyPair.public.toIrohaPublicKey()))
+        .also { println("ACCOUNT $whiteRabbit CREATED") }
+    
+    val whiteRabbitAsset = "$assetDefinition$ASSET_ID_DELIMITER$whiteRabbit"
+    sendTransaction.registerAsset(whiteRabbitAsset, AssetValue.Quantity(0))
+        .also { println("ASSET $whiteRabbitAsset CREATED") }
+    
+    sendTransaction.transferAsset(madHatterAsset, 10, whiteRabbitAsset, madHatter.asAccountId(), madHatterKeyPair)
+        .also { println("$madHatter TRANSFERRED FROM $madHatterAsset TO $whiteRabbitAsset: 10") }
+    query.getAccountAmount(madHatter, madHatterAsset).also { println("$madHatterAsset BALANCE: $it") }
+    query.getAccountAmount(whiteRabbit, whiteRabbitAsset).also { println("$whiteRabbitAsset BALANCE: $it") }

In the sendTransaction class, add a method for transferring assets.

Kotlin
    suspend fun transferAsset(
+        from: String,
+        value: Int,
+        to: String,
+        admin: AccountId = this.admin,
+        keyPair: KeyPair = this.keyPair
+    ) {
+        client.sendTransaction {
+            account(admin)
+            this.transferAsset(from.asAssetId(), value, to.asAssetId())
+            buildSigned(keyPair)
+        }.also {
+            withTimeout(timeout) { it.await() }
+        }
+    }

To check the result of the asset transfer, add the getAccountAmount() method to the Query class:

Kotlin
    suspend fun getAccountAmount(accountId: String, assetId: String): Long {
+        return QueryBuilder.findAccountById(accountId.asAccountId())
+            .account(admin)
+            .buildSigned(keyPair)
+            .let { query ->
+                client.sendQuery(query).assets[assetId.asAssetId()]?.value
+            }.let { value ->
+                value?.cast<AssetValue.Quantity>()?.u32
+            } ?: throw RuntimeException("NOT FOUND")
+    }

The console output should contain similar information.

Expand to see the expected output
DOMAIN looking_glass_1684843200289 CREATED
+ALL DOMAINS: [looking_glass, garden_of_live_flowers, genesis, looking_glass_1684843200289, looking_glass_1684842996549, wonderland, looking_glass_1684835731653]
+ACCOUNT madHatter_1684843202389@looking_glass_1684843200289 CREATED
+ALL ACCOUNTS: [carpenter@garden_of_live_flowers, genesis@genesis, madHatter_1684843202389@looking_glass_1684843200289, madHatter_1684842997930@looking_glass_1684842996549, alice@wonderland, bob@wonderland, madHatter_1684835733686@looking_glass_1684835731653]
+ASSET DEFINITION asset_time_1684843203337#looking_glass_1684843200289 CREATED
+ASSET asset_time_1684843203337#looking_glass_1684843200289#madHatter_1684843202389@looking_glass_1684843200289 CREATED
+ACCOUNT whiteRabbit_1684843205383@looking_glass_1684843200289 CREATED
+ASSET asset_time_1684843203337#looking_glass_1684843200289#whiteRabbit_1684843205383@looking_glass_1684843200289 CREATED
+madHatter_1684843202389@looking_glass_1684843200289 TRANSFERRED FROM asset_time_1684843203337#looking_glass_1684843200289#madHatter_1684843202389@looking_glass_1684843200289 TO asset_time_1684843203337#looking_glass_1684843200289#whiteRabbit_1684843205383@looking_glass_1684843200289: 10
+asset_time_1684843203337#looking_glass_1684843200289#madHatter_1684843202389@looking_glass_1684843200289 BALANCE: 90
+asset_time_1684843203337#looking_glass_1684843200289#whiteRabbit_1684843205383@looking_glass_1684843200289 BALANCE: 10
+ALL ASSETS: [asset_time_1684843203337#looking_glass_1684843200289#madHatter_1684843202389@looking_glass_1684843200289, cabbage#garden_of_live_flowers#alice@wonderland, rose#wonderland#alice@wonderland]

7. Burning assets

Burning assets is quite similar to minting them. To get started, let's add the following lines to the main() method:

Kotlin
    sendTransaction.burnAssets(madHatterAsset, 10, madHatter.asAccountId(), madHatterKeyPair)
+        .also { println("\${madHatterAsset} WAS BURN") }
+
+    query.getAccountAmount(madHatter, madHatterAsset)
+        .also { println("$madHatterAsset BALANCE: $it AFTER ASSETS BURNING") }

Then implement a wrapper over the burnAssets() method in the sendTransaction class:

Kotlin
    suspend fun burnAssets(
+        assetId: String,
+        value: Int,
+        admin: AccountId = this.admin,
+        keyPair: KeyPair = this.keyPair
+    ) {
+        client.sendTransaction {
+            account(admin)
+            this.burnAsset(assetId.asAssetId(), value)
+            buildSigned(keyPair)
+        }.also {
+            withTimeout(timeout) { it.await() }
+        }
+    }
Expand to see the expected output
DOMAIN looking_glass_1684843511587 CREATED
+ALL DOMAINS: [looking_glass, garden_of_live_flowers, looking_glass_1684843344208, genesis, looking_glass_1684843200289, looking_glass_1684842996549, wonderland, looking_glass_1684843511587, looking_glass_1684843451130, looking_glass_1684835731653]
+ACCOUNT madHatter_1684843513272@looking_glass_1684843511587 CREATED
+ALL ACCOUNTS: [carpenter@garden_of_live_flowers, madHatter_1684843345604@looking_glass_1684843344208, whiteRabbit_1684843348692@looking_glass_1684843344208, genesis@genesis, madHatter_1684835733686@looking_glass_1684835731653]
+ASSET DEFINITION asset_time_1684843514251#looking_glass_1684843511587 CREATED
+ASSET asset_time_1684843514251#looking_glass_1684843511587#madHatter_1684843513272@looking_glass_1684843511587 CREATED
+ACCOUNT whiteRabbit_1684843516303@looking_glass_1684843511587 CREATED
+ASSET asset_time_1684843514251#looking_glass_1684843511587#whiteRabbit_1684843516303@looking_glass_1684843511587 CREATED
+madHatter_1684843513272@looking_glass_1684843511587 TRANSFERRED FROM asset_time_1684843514251#looking_glass_1684843511587#madHatter_1684843513272@looking_glass_1684843511587 TO asset_time_1684843514251#looking_glass_1684843511587#whiteRabbit_1684843516303@looking_glass_1684843511587: 10
+asset_time_1684843514251#looking_glass_1684843511587#madHatter_1684843513272@looking_glass_1684843511587 BALANCE: 90
+asset_time_1684843514251#looking_glass_1684843511587#whiteRabbit_1684843516303@looking_glass_1684843511587 BALANCE: 10
+asset_time_1684843514251#looking_glass_1684843511587#madHatter_1684843513272@looking_glass_1684843511587 WAS BURN
+asset_time_1684843514251#looking_glass_1684843511587#madHatter_1684843513272@looking_glass_1684843511587 BALANCE: 80 AFTER ASSETS BURNING
+ALL ASSETS: [asset_time_1684843514251#looking_glass_1684843511587#whiteRabbit_1684843516303@looking_glass_1684843511587, asset_time_1684843454049#looking_glass_1684843451130#madHatter_1684843453085@looking_glass_1684843451130, asset_time_1684843454049#looking_glass_1684843451130#whiteRabbit_1684843456091@looking_glass_1684843451130]

8. Visualizing outputs

Finally, we should talk about visualising data. The Rust API is currently the most complete in terms of available queries and instructions. After all, this is the language in which Iroha 2 was built. Kotlin, by contrast, supports only some features.

There are two possible event filters: PipelineEventFilter and DataEventFilter, we shall focus on the former. This filter sieves events pertaining to the process of submitting a transaction, executing a transaction and committing it to a block.

kotlin
import jp.co.soramitsu.iroha2.generated.datamodel.events.EventFilter.Pipeline
+import jp.co.soramitsu.iroha2.generated.datamodel.events.pipeline.EventFilter
+import jp.co.soramitsu.iroha2.generated.datamodel.events.pipeline.EntityType.Transaction
+import jp.co.soramitsu.iroha2.generated.crypto.hash.Hash
+
+val hash: ByteArray
+val eventFilter = Pipeline(EventFilter(Transaction(), Hash(hash)))

What this short code snippet does is the following: It creates an event pipeline filter that checks if a transaction with the specified hash was submitted/rejected. This can then be used to see if the transaction we submitted was processed correctly and provide feedback to the end-user.

9. Samples in pure Java

java
package jp.co.soramitsu.iroha2;
+
+import jp.co.soramitsu.iroha2.client.Iroha2AsyncClient;
+import jp.co.soramitsu.iroha2.generated.datamodel.Value;
+import jp.co.soramitsu.iroha2.generated.datamodel.account.Account;
+import jp.co.soramitsu.iroha2.generated.datamodel.account.AccountId;
+import jp.co.soramitsu.iroha2.generated.datamodel.asset.AssetId;
+import jp.co.soramitsu.iroha2.generated.datamodel.asset.AssetValue;
+import jp.co.soramitsu.iroha2.generated.datamodel.asset.AssetValueType;
+import jp.co.soramitsu.iroha2.generated.datamodel.domain.Domain;
+import jp.co.soramitsu.iroha2.generated.datamodel.domain.DomainId;
+import jp.co.soramitsu.iroha2.generated.datamodel.metadata.Metadata;
+import jp.co.soramitsu.iroha2.generated.datamodel.name.Name;
+import jp.co.soramitsu.iroha2.generated.datamodel.transaction.VersionedSignedTransaction;
+import jp.co.soramitsu.iroha2.query.QueryAndExtractor;
+import jp.co.soramitsu.iroha2.query.QueryBuilder;
+import jp.co.soramitsu.iroha2.testengine.DefaultGenesis;
+import jp.co.soramitsu.iroha2.testengine.IrohaTest;
+import jp.co.soramitsu.iroha2.testengine.WithIroha;
+import jp.co.soramitsu.iroha2.transaction.TransactionBuilder;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import static jp.co.soramitsu.iroha2.testengine.TestConstsKt.*;
+
+public class JavaTest extends IrohaTest<Iroha2AsyncClient> {
+
+    @Test
+    @WithIroha(sources = DefaultGenesis.class)
+    public void instructionFailed() {
+        final VersionedSignedTransaction transaction = TransactionBuilder.Companion
+            .builder()
+            .account(ALICE_ACCOUNT_ID)
+            .fail("FAIL MESSAGE")
+            .buildSigned(ALICE_KEYPAIR);
+        final CompletableFuture<byte[]> future = client.sendTransactionAsync(transaction);
+        Assertions.assertThrows(ExecutionException.class,
+            () -> future.get(getTxTimeout().getSeconds(), TimeUnit.SECONDS)
+        );
+    }
+
+    @Test
+    @WithIroha(sources = DefaultGenesis.class)
+    public void registerDomainInstructionCommitted() throws ExecutionException, InterruptedException, TimeoutException {
+        final DomainId domainId = new DomainId(new Name("new_domain_name"));
+        final VersionedSignedTransaction transaction = TransactionBuilder.Companion
+            .builder()
+            .account(ALICE_ACCOUNT_ID)
+            .registerDomain(domainId)
+            .buildSigned(ALICE_KEYPAIR);
+        client.sendTransactionAsync(transaction).get(getTxTimeout().getSeconds(), TimeUnit.SECONDS);
+
+        final QueryAndExtractor<Domain> query = QueryBuilder
+            .findDomainById(domainId)
+            .account(ALICE_ACCOUNT_ID)
+            .buildSigned(ALICE_KEYPAIR);
+        final CompletableFuture<Domain> future = client.sendQueryAsync(query);
+        final Domain domain = future.get(getTxTimeout().getSeconds(), TimeUnit.SECONDS);
+        Assertions.assertEquals(domain.getId(), domainId);
+    }
+
+    @Test
+    @WithIroha(sources = DefaultGenesis.class)
+    public void registerAccountInstructionCommitted() throws Exception {
+        final AccountId accountId = new AccountId(
+            new Name("new_account"),
+            DEFAULT_DOMAIN_ID
+        );
+        final VersionedSignedTransaction transaction = TransactionBuilder.Companion
+            .builder()
+            .account(ALICE_ACCOUNT_ID)
+            .registerAccount(accountId, new ArrayList<>())
+            .buildSigned(ALICE_KEYPAIR);
+        client.sendTransactionAsync(transaction).get(getTxTimeout().getSeconds(), TimeUnit.SECONDS);
+
+        final QueryAndExtractor<Account> query = QueryBuilder
+            .findAccountById(accountId)
+            .account(ALICE_ACCOUNT_ID)
+            .buildSigned(ALICE_KEYPAIR);
+        final CompletableFuture<Account> future = client.sendQueryAsync(query);
+        final Account account = future.get(getTxTimeout().getSeconds(), TimeUnit.SECONDS);
+        Assertions.assertEquals(account.getId(), accountId);
+    }
+
+    @Test
+    @WithIroha(sources = DefaultGenesis.class)
+    public void mintAssetInstructionCommitted() throws Exception {
+        final VersionedSignedTransaction registerAssetTx = TransactionBuilder.Companion
+            .builder()
+            .account(ALICE_ACCOUNT_ID)
+            .registerAssetDefinition(DEFAULT_ASSET_DEFINITION_ID, new AssetValueType.Quantity())
+            .buildSigned(ALICE_KEYPAIR);
+        client.sendTransactionAsync(registerAssetTx).get(getTxTimeout().getSeconds(), TimeUnit.SECONDS);
+
+        final VersionedSignedTransaction mintAssetTx = TransactionBuilder.Companion
+            .builder()
+            .account(ALICE_ACCOUNT_ID)
+            .mintAsset(DEFAULT_ASSET_ID, 5)
+            .buildSigned(ALICE_KEYPAIR);
+        client.sendTransactionAsync(mintAssetTx).get(getTxTimeout().getSeconds(), TimeUnit.SECONDS);
+
+        final QueryAndExtractor<Account> query = QueryBuilder
+            .findAccountById(ALICE_ACCOUNT_ID)
+            .account(ALICE_ACCOUNT_ID)
+            .buildSigned(ALICE_KEYPAIR);
+        final CompletableFuture<Account> future = client.sendQueryAsync(query);
+        final Account account = future.get(getTxTimeout().getSeconds(), TimeUnit.SECONDS);
+        final AssetValue value = account.getAssets().get(DEFAULT_ASSET_ID).getValue();
+        Assertions.assertEquals(5, ((AssetValue.Quantity) value).getU32());
+    }
+
+    @Test
+    @WithIroha(sources = DefaultGenesis.class)
+    public void updateKeyValueInstructionCommitted() throws Exception {
+        final Name assetMetadataKey = new Name("asset_metadata_key");
+        final Value.String assetMetadataValue = new Value.String("some string value");
+        final Value.String assetMetadataValue2 = new Value.String("some string value 2");
+        final Metadata metadata = new Metadata(new HashMap<Name, Value>() {{
+            put(assetMetadataKey, assetMetadataValue);
+        }});
+
+        final VersionedSignedTransaction registerAssetTx = TransactionBuilder.Companion
+            .builder()
+            .account(ALICE_ACCOUNT_ID)
+            .registerAssetDefinition(DEFAULT_ASSET_DEFINITION_ID, new AssetValueType.Store(), metadata)
+            .buildSigned(ALICE_KEYPAIR);
+        client.sendTransactionAsync(registerAssetTx).get(getTxTimeout().getSeconds(), TimeUnit.SECONDS);
+
+        final AssetId assetId = new AssetId(DEFAULT_ASSET_DEFINITION_ID, ALICE_ACCOUNT_ID);
+        final VersionedSignedTransaction keyValueTx = TransactionBuilder.Companion
+            .builder()
+            .account(ALICE_ACCOUNT_ID)
+            .setKeyValue(
+                assetId,
+                assetMetadataKey,
+                assetMetadataValue2
+            ).buildSigned(ALICE_KEYPAIR);
+        client.sendTransactionAsync(keyValueTx).get(10, TimeUnit.SECONDS);
+
+        final QueryAndExtractor<Value> assetDefinitionValueQuery = QueryBuilder
+            .findAssetKeyValueByIdAndKey(assetId, assetMetadataKey)
+            .account(ALICE_ACCOUNT_ID)
+            .buildSigned(ALICE_KEYPAIR);
+        final CompletableFuture<Value> future = client.sendQueryAsync(assetDefinitionValueQuery);
+
+        final Value value = future.get(10, TimeUnit.SECONDS);
+        Assertions.assertEquals(
+            ((Value.String) value).getString(),
+            assetMetadataValue2.getString()
+        );
+    }
+
+    @Test
+    @WithIroha(sources = DefaultGenesis.class)
+    public void setKeyValueInstructionCommitted() throws Exception {
+        final Value.String assetValue = new Value.String("some string value");
+        final Name assetKey = new Name("asset_metadata_key");
+
+        final VersionedSignedTransaction registerAssetTx = TransactionBuilder.Companion
+            .builder()
+            .account(ALICE_ACCOUNT_ID)
+            .registerAssetDefinition(DEFAULT_ASSET_DEFINITION_ID, new AssetValueType.Store())
+            .buildSigned(ALICE_KEYPAIR);
+        client.sendTransactionAsync(registerAssetTx).get(getTxTimeout().getSeconds(), TimeUnit.SECONDS);
+
+        final VersionedSignedTransaction keyValueTx = TransactionBuilder.Companion
+            .builder()
+            .account(ALICE_ACCOUNT_ID)
+            .setKeyValue(
+                DEFAULT_ASSET_DEFINITION_ID,
+                assetKey,
+                assetValue
+            ).buildSigned(ALICE_KEYPAIR);
+        client.sendTransactionAsync(keyValueTx).get(10, TimeUnit.SECONDS);
+
+        final QueryAndExtractor<Value> assetDefinitionValueQuery = QueryBuilder
+            .findAssetDefinitionKeyValueByIdAndKey(DEFAULT_ASSET_DEFINITION_ID, assetKey)
+            .account(ALICE_ACCOUNT_ID)
+            .buildSigned(ALICE_KEYPAIR);
+        final CompletableFuture<Value> future = client.sendQueryAsync(assetDefinitionValueQuery);
+
+        final Value value = future.get(10, TimeUnit.SECONDS);
+        Assertions.assertEquals(
+            ((Value.String) value).getString(),
+            assetValue.getString()
+        );
+    }
+}
`,79),p=[k];function e(E,r,d,g,y,o){return a(),i("div",null,p)}const u=s(l,[["render",e]]);export{c as __pageData,u as default}; diff --git a/assets/guide_get-started_kotlin-java.md.BJnusMRj.lean.js b/assets/guide_get-started_kotlin-java.md.BJnusMRj.lean.js new file mode 100644 index 00000000..67cc125e --- /dev/null +++ b/assets/guide_get-started_kotlin-java.md.BJnusMRj.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,V as n}from"./chunks/framework.B6c1f-8R.js";const t="/iroha-2-docs/assets/iroha_java_hash.CWG7jGmi.png",h="/iroha-2-docs/assets/iroha_java_commits.DtyotM0c.png",c=JSON.parse('{"title":"Kotlin/Java Guide","description":"","frontmatter":{},"headers":[],"relativePath":"guide/get-started/kotlin-java.md","filePath":"guide/get-started/kotlin-java.md","lastUpdated":1727242778000}'),l={name:"guide/get-started/kotlin-java.md"},k=n("",79),p=[k];function e(E,r,d,g,y,o){return a(),i("div",null,p)}const u=s(l,[["render",e]]);export{c as __pageData,u as default}; diff --git a/assets/guide_get-started_launch-iroha-2.md.BYWYF67e.js b/assets/guide_get-started_launch-iroha-2.md.BYWYF67e.js new file mode 100644 index 00000000..1917271f --- /dev/null +++ b/assets/guide_get-started_launch-iroha-2.md.BYWYF67e.js @@ -0,0 +1,39 @@ +import{_ as s,c as i,o as a,V as e}from"./chunks/framework.B6c1f-8R.js";const f=JSON.parse('{"title":"Launch Iroha 2","description":"","frontmatter":{},"headers":[],"relativePath":"guide/get-started/launch-iroha-2.md","filePath":"guide/get-started/launch-iroha-2.md","lastUpdated":1727242778000}'),h={name:"guide/get-started/launch-iroha-2.md"},n=e(`

Launch Iroha 2

This tutorial explains how to launch an Iroha 2 network.

1. Prerequisites

To launch an instance of the Iroha 2 network, install the following first:

2. Launch Iroha Network

  1. In your terminal, navigate to the root directory of your local iroha repository:

    bash
    $ cd ~/Git/iroha
  2. Run the docker compose command with the docker-compose.yml network configuration file specified to deploy a network of four containerized peers:

    bash
    $ docker compose -f defaults/docker-compose.yml up

    Depending on your setup, this command will either pull an image from Docker Hub or build the container locally.

    Once the process completes, you will see an output similar to the following:

    [+] Running 9/9
    + irohad2 Pulled                                                          6.3s
    + irohad0 Pulled                                                          6.3s
    + irohad3 Pulled                                                          6.3s
    + irohad1 Pulled                                                          6.3s
    + ec99f8b99825 Already exists                                           0.0s
    + d3a0e7f5d646 Pull complete                                            1.4s
    + 1b1d5514cbbf Pull complete                                            2.1s
    + 86e58c28036c Pull complete                                            2.3s
    + 0d3b3367a826 Pull complete                                            2.5s
    +[+] Running 5/5
    + Network swarm_default      Created                                      0.1s
    + Container swarm-irohad3-1  Created                                      0.4s
    + Container swarm-irohad0-1  Created                                      0.5s
    + Container swarm-irohad1-1  Created                                      0.4s
    + Container swarm-irohad2-1  Created                                      0.5s
    +Attaching to irohad0-1, irohad1-1, irohad2-1, irohad3-1
    +irohad0-1  | 2024-07-15T05:51:39.204411Z  INFO irohad: Hyperledgerいろは2にようこそ!(translation) Welcome to Hyperledger Iroha! version="2.0.0-pre-rc.21" git_commit_sha="185ef76" peer=ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D@@0.0.0.0:1337 chain=00000000-0000-0000-0000-000000000000 listening_on=0.0.0.0:8080
    +irohad0-1  | 2024-07-15T05:51:39.204729Z  INFO init:start{listen_addr=WithOrigin { value: 0.0.0.0:1337, origin: Env { id: ParameterId(network.address), var: "P2P_ADDRESS" } } idle_timeout=60s}: iroha_p2p::network: Network bound to listener
    +irohad0-1  | 2024-07-15T05:51:39.209730Z  INFO init:kura_init: iroha_core::kura: Kura init complete mode=Strict block_count=0
    +irohad0-1  | 2024-07-15T05:51:39.210006Z  INFO init: irohad: Didn't find a state snapshot; creating an empty state
    +irohad0-1  | 2024-07-15T05:51:39.214759Z  INFO init: irohad: Telemetry not started due to absent configuration
    +irohad0-1  | 2024-07-15T05:51:39.215234Z  INFO iroha_core::sumeragi: Sumeragi has finished loading blocks and setting up the state
    +
    +...
    +
    + irohad2-1  | 2024-07-15T05:51:39.332824Z  INFO consensus: iroha_core::sumeragi::main_loop: Listening for genesis... peer_id=ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10@@0.0.0.0:1339 role=Leader
    + irohad0-1  | 2024-07-15T05:51:40.478714Z  INFO consensus: iroha_core::sumeragi::main_loop: Block committed peer_id=ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D@@0.0.0.0:1337 prev_role=ProxyTail next_role=ValidatingPeer block_hash=a638001762e365280677a5407bac9adaa119c8cb82c8afe377b72f85e71ed4a9 new_height=1
    + irohad0-1  | 2024-07-15T05:51:40.478761Z  INFO consensus: iroha_core::sumeragi::main_loop: Sumeragi initialized peer_id=ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D@@0.0.0.0:1337 role=ValidatingPeer
    + irohad2-1  | 2024-07-15T05:51:42.085522Z  INFO consensus: iroha_core::sumeragi::main_loop: Block committed peer_id=ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10@@0.0.0.0:1339 prev_role=Leader next_role=ProxyTail block_hash=a638001762e365280677a5407bac9adaa119c8cb82c8afe377b72f85e71ed4a9 new_height=1
    + irohad2-1  | 2024-07-15T05:51:42.085585Z  INFO consensus: iroha_core::sumeragi::main_loop: Sumeragi initialized peer_id=ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10@@0.0.0.0:1339 role=ProxyTail
    + irohad1-1  | 2024-07-15T05:51:42.109788Z  INFO consensus: iroha_core::sumeragi::main_loop: Block committed peer_id=ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D@@0.0.0.0:1338 prev_role=ValidatingPeer next_role=Leader block_hash=a638001762e365280677a5407bac9adaa119c8cb82c8afe377b72f85e71ed4a9 new_height=1
    + irohad1-1  | 2024-07-15T05:51:42.109858Z  INFO consensus: iroha_core::sumeragi::main_loop: Sumeragi initialized peer_id=ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D@@0.0.0.0:1338 role=Leader
    + irohad3-1  | 2024-07-15T05:51:42.117040Z  INFO consensus: iroha_core::sumeragi::main_loop: Block committed peer_id=ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE@@0.0.0.0:1340 prev_role=ObservingPeer next_role=ObservingPeer block_hash=a638001762e365280677a5407bac9adaa119c8cb82c8afe377b72f85e71ed4a9 new_height=1
    + irohad3-1  | 2024-07-15T05:51:42.117083Z  INFO consensus: iroha_core::sumeragi::main_loop: Sumeragi initialized peer_id=ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE@@0.0.0.0:1340 role=ObservingPeer
    + irohad0-1  | 2024-07-15T05:52:39.238596Z  INFO iroha_core::snapshot: Successfully created a snapshot of state at_height=1
    + irohad1-1  | 2024-07-15T05:52:39.266902Z  INFO iroha_core::snapshot: Successfully created a snapshot of state at_height=1
    + irohad3-1  | 2024-07-15T05:52:39.276634Z  INFO iroha_core::snapshot: Successfully created a snapshot of state at_height=1
    + irohad2-1  | 2024-07-15T05:52:39.349409Z  INFO iroha_core::snapshot: Successfully created a snapshot of state at_height=1

After deploying the network, you can interact with it using the Iroha Client CLI.

TIP

You can monitor blockchain events in the terminal where the network runs.

Docker Options

The following options are also available for local compilation:

  • To test Iroha code quickly, use the docker-compose-single.yml network configuration file, which starts a container with a single peer.
  • To test Iroha code in normal conditions, use the docker-compose-local.yml network configuration file, which starts four connected containers with peers.

Note

There is ongoing work to make our configurations for Docker even more customizable with the help of Swarm.

`,13),t=[n];function l(k,p,r,d,o,c){return a(),i("div",null,t)}const y=s(h,[["render",l]]);export{f as __pageData,y as default}; diff --git a/assets/guide_get-started_launch-iroha-2.md.BYWYF67e.lean.js b/assets/guide_get-started_launch-iroha-2.md.BYWYF67e.lean.js new file mode 100644 index 00000000..704ac669 --- /dev/null +++ b/assets/guide_get-started_launch-iroha-2.md.BYWYF67e.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,V as e}from"./chunks/framework.B6c1f-8R.js";const f=JSON.parse('{"title":"Launch Iroha 2","description":"","frontmatter":{},"headers":[],"relativePath":"guide/get-started/launch-iroha-2.md","filePath":"guide/get-started/launch-iroha-2.md","lastUpdated":1727242778000}'),h={name:"guide/get-started/launch-iroha-2.md"},n=e("",13),t=[n];function l(k,p,r,d,o,c){return a(),i("div",null,t)}const y=s(h,[["render",l]]);export{f as __pageData,y as default}; diff --git a/assets/guide_get-started_operate-iroha-2-via-cli.md.D3UDHgAT.js b/assets/guide_get-started_operate-iroha-2-via-cli.md.D3UDHgAT.js new file mode 100644 index 00000000..5a44d16b --- /dev/null +++ b/assets/guide_get-started_operate-iroha-2-via-cli.md.D3UDHgAT.js @@ -0,0 +1,140 @@ +import{_ as s,c as i,o as a,V as t}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Operate Iroha 2 via CLI","description":"","frontmatter":{},"headers":[],"relativePath":"guide/get-started/operate-iroha-2-via-cli.md","filePath":"guide/get-started/operate-iroha-2-via-cli.md","lastUpdated":1727242778000}'),n={name:"guide/get-started/operate-iroha-2-via-cli.md"},e=t(`

Operate Iroha 2 via CLI

You can perform most operations in an Iroha 2 network using the Iroha Client CLI. This tutorial guides you through setting it up, configuring it, and executing basic operations on the network.

1. Set Up Iroha Client CLI

INFO

To set up the Iroha Client CLI, an instance of the Iroha network must be launched and operational.

Create a new directory and copy the client.toml configuration file there:

bash
$ cp path_to_iroha_repo/defaults/client.toml path_to_new_directory/

2. Configure Iroha Client CLI

  1. Navigate to the directory with the copied client.toml configuration file.

  2. Run the Iroha Client CLI:

    bash
    $ iroha
    Expected result
    bash
    Iroha CLI Client lets you interact with Iroha Peers Web API without direct network usage
    +
    +Usage: iroha [OPTIONS] <COMMAND>
    +
    +Commands:
    +  domain   The subcommand related to domains
    +  account  The subcommand related to accounts
    +  asset    The subcommand related to assets
    +  peer     The subcommand related to p2p networking
    +  events   The subcommand related to event streaming
    +  wasm     The subcommand related to Wasm
    +  blocks   The subcommand related to block streaming
    +  json     The subcommand related to multi-instructions as Json or Json5
    +  help     Print this message or the help of the given subcommand(s)
    +
    +Options:
    +  -c, --config <PATH>  Path to the configuration file [default: client.toml]
    +  -v, --verbose        More verbose output
    +  -h, --help           Print help
    +  -V, --version        Print version

By default, the Iroha Client searches for a configuration in the client.toml file located in its current working directory. We already copied it there, so we're all set.

TIP

To run any of the Iroha client commands with some other configuration file, use the following syntax:

bash
$ iroha --config path/to/client.toml <COMMAND>

This is a non-persistent configuration: each time you run iroha, you must add the --config path/to/client.toml command-line argument, unless the client.toml config file is in the working directory.

The account specified in the [account] section of client.toml is preregistered in the default genesis block of the blockchain. Only it can interact with the blockchain for now. If you change the keys or the domain of the account in the configuration file, make sure that they are preregistered on the blockchain too.

To check that a configuration works, run the following query:

bash
$ iroha domain list all

The output should contain several preregistered domains.

Expected result
json
  {
+    "id": "garden_of_live_flowers",
+    "logo": null,
+    "metadata": {},
+    "owned_by": "ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4@genesis"
+  },
+  {
+    "id": "genesis",
+    "logo": null,
+    "metadata": {},
+    "owned_by": "ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4@genesis"
+  },
+  {
+    "id": "wonderland",
+    "logo": null,
+    "metadata": {
+      "key": "value"
+    },
+    "owned_by": "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland"
+  }

3. Register a Domain

INFO

A domain is a group of entities like asset definitions, accounts, and other objects grouped logically. These are described in greater detail in the Blockchain section of the documentation.

To register a new domain, run:

bash
$ iroha domain register --id="looking_glass"

Once executed, a confirmation message appears. However, since the details of the new domain are not directly readable in that message, to confirm that you have successfully created the new looking_glass domain, run:

bash
$ iroha domain list all
Expected result
json
  {
+    "id": "looking_glass",
+    "logo": null,
+    "metadata": {},
+    "owned_by": "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland"
+  },

Note that the owner of the new domain is the account specified in our config file. They performed the registration.

With a domain available, it is time to register an account in it.

4. Register an Account

To register a new account, you need a cryptographic key pair consisting of a public and a private key. You will use it to establish a secure communication channel between yourself and the network.

For users' convenience, Iroha comes with kagami, a built-in key generator tool. To generate a new key pair with kagami, run the following command:

bash
$ kagami crypto

TIP

To customize the generated keys, you can specify a number of parameters. For instance, kagami can use one of four available algorithms to generate cryptographic keys.

To learn more about generating cryptographic keys with kagami, available algorithms, and other parameters, see Generating Cryptographic Keys with Kagami

For the purposes of this tutorial, we iuse the following key pair:

bash
Public key (multihash): "ed0120ABA0446CFBD4E12627FFA870FB37993ED83EB1AE0588184B90D832A64C24C379"
+Private key (multihash): "802620CBD3D701B561FE98463767729176404DC757D690F78980B8FDD40C171CCB8EB5"

To register a new account within the looking_glass domain, run:

bash
$ iroha account register --id="ed0120ABA0446CFBD4E12627FFA870FB37993ED83EB1AE0588184B90D832A64C24C379@looking_glass"

The --id argument in the above code snippet specifies the account id, the unique identifier of the account. It consists of the user public key (generated using kagami) and the domain it is associated with.

If the account registration is successful, you receive a confirmation message. Similar to the domain registration, to confirm that you have successfully created a new account within the looking_glass domain, run:

bash
$ iroha account list all
Expected result
json
[
+  {
+    "id": "ed0120E9F632D3034BAB6BB26D92AC8FD93EF878D9C5E69E01B61B4C47101884EE2F99@garden_of_live_flowers",
+    "metadata": {}
+  },
+  {
+    "id": "ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4@genesis",
+    "metadata": {}
+  },
+  {
+    "id": "ed0120ABA0446CFBD4E12627FFA870FB37993ED83EB1AE0588184B90D832A64C24C379@looking_glass",
+    "metadata": {}
+  },
+  {
+    "id": "ed012004FF5B81046DDCCF19E2E451C45DFB6F53759D4EB30FA2EFA807284D1CC33016@wonderland",
+    "metadata": {
+      "key": "value"
+    }
+  },
+  {
+    "id": "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland",
+    "metadata": {
+      "key": "value"
+    }
+  }
+]

5. Transfer a Domain

The account we just created is part of the looking_glass domain but doesn't own it, so it can't manage the domain. To enable this, we'll transfer looking_glass ownership to our new account.

We could change the keys and domain in client.toml at this point and continue working with the account we just created, but we wouldn't be able to do much in the looking_glass domain, as our new account is not the owner of the looking_glass domain, and therefore cannot manage it.

To transfer a domain, perform the following:

  1. Run the transfer command:

    bash
    $ iroha domain transfer --id="looking_glass" --from "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland" --to "ed0120ABA0446CFBD4E12627FFA870FB37993ED83EB1AE0588184B90D832A64C24C379@looking_glass"
  2. Check that the ownership changed:

    bash
    $ iroha domain list all
  3. Switch to the newly created account. For this, we need to modify the public_key, private_key, and domain in the client.toml config file with the credentials of the user we want to act as.

Note that here the domain of the user that we are switching to matches the one we just transferred. However, this is not a requirement. A user may be registered in one domain and own multiple others. When setting the domain in the configuration file, always use the one that your user is registered with.

Expected result

The account section of your updated client.toml file:

toml
[account]
+domain = "looking_glass"
+public_key = "ed0120ABA0446CFBD4E12627FFA870FB37993ED83EB1AE0588184B90D832A64C24C379"
+private_key = "802620CBD3D701B561FE98463767729176404DC757D690F78980B8FDD40C171CCB8EB5"

TIP

Permissions determine accounts rights within Iroha. Domain owners have the most rights in a domain by default, but permission configuration in Iroha is very flexible and can be customized to your needs.

Now that we control the domain, we can define and manage assets in it.

6. Register and Mint Assets

To mint an asset, its asset definition must be registered first.

To register a tea token within the looking_glass domain, run:

bash
$ iroha asset definition register --id="tea#looking_glass" --type="Numeric"

The numeric tea asset is now registered within the looking_glass domain.

If you open the terminal where the Iroha network runs, you will see that all our activity caused numerous pipeline events there.

To mint tea tokens run:

bash
$ iroha asset mint --id="tea##ed0120ABA0446CFBD4E12627FFA870FB37993ED83EB1AE0588184B90D832A64C24C379@looking_glass" --quantity="100"

After minting one hundred tea, more pipeline events are expected, and you can also query the assets that you have just minted:

bash
$ iroha asset list all
Expected result
json
[
+  {
+    "id": "tea##ed0120ABA0446CFBD4E12627FFA870FB37993ED83EB1AE0588184B90D832A64C24C379@looking_glass",
+    "value": {
+      "Numeric": "100"
+    }
+  },
+  {
+    "id": "cabbage#garden_of_live_flowers#ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland",
+    "value": {
+      "Numeric": "44"
+    }
+  },
+  {
+    "id": "rose##ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland",
+    "value": {
+      "Numeric": "13"
+    }
+  }
+]

7. Transfer Assets

After minting the assets, you can transfer some of your tea to another account:

bash
$ iroha asset transfer --to="ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland" --id="tea##ed0120ABA0446CFBD4E12627FFA870FB37993ED83EB1AE0588184B90D832A64C24C379@looking_glass"  --quantity=33

8. Burn Assets

Burning assets is quite similar to minting them:

bash
$ iroha asset burn --id="tea##ed0120ABA0446CFBD4E12627FFA870FB37993ED83EB1AE0588184B90D832A64C24C379@looking_glass" --quantity="15"

9. Visualize Outputs

Although you will get a constant data feed of the network within the terminal running docker compose, you can also configure an output to listen to events of several types on the network: blocks generation, transactions, data events and triggers.

We will set up an event listener for the block pipeline.

From a new terminal tab/window run:

bash
$ iroha events block-pipeline
Expected result
json
Listening to events with filter: Pipeline(Block(BlockEventFilter { height: None, status: None }))
+{
+  "Pipeline": {
+    "Block": {
+      "header": {
+        "height": 14,
+        "prev_block_hash": "AF1ABC889019971D4C4E8866C347367D63A024319E50AEF989DB255F761E9D1D",
+        "transactions_hash": "7F2091D887BF9DBF6100DFEA696B06AE269C288AE55F1D281D9FDDAD93D1B8F1",
+        "creation_time_ms": 1721132667162,
+        "view_change_index": 1,
+        "consensus_estimation_ms": 4000
+      },
+      "hash": "1CC6256356418D02F19B17487AD4F7F105AE6CD3FD129760C575066484F3EF97",
+      "status": "Approved"
+    }
+  }
+}
+{
+  "Pipeline": {
+    "Block": {
+      "header": {
+        "height": 14,
+        "prev_block_hash": "AF1ABC889019971D4C4E8866C347367D63A024319E50AEF989DB255F761E9D1D",
+        "transactions_hash": "7F2091D887BF9DBF6100DFEA696B06AE269C288AE55F1D281D9FDDAD93D1B8F1",
+        "creation_time_ms": 1721132667162,
+        "view_change_index": 1,
+        "consensus_estimation_ms": 4000
+      },
+      "hash": "99D30F9DD159A397A76E4A37143433BD302264F7509B6E154CA9C18263543857",
+      "status": "Committed"
+    }
+  }
+}
+{
+  "Pipeline": {
+    "Block": {
+      "header": {
+        "height": 14,
+        "prev_block_hash": "AF1ABC889019971D4C4E8866C347367D63A024319E50AEF989DB255F761E9D1D",
+        "transactions_hash": "7F2091D887BF9DBF6100DFEA696B06AE269C288AE55F1D281D9FDDAD93D1B8F1",
+        "creation_time_ms": 1721132667162,
+        "view_change_index": 1,
+        "consensus_estimation_ms": 4000
+      },
+      "hash": "99D30F9DD159A397A76E4A37143433BD302264F7509B6E154CA9C18263543857",
+      "status": "Applied"
+    }
+  }
+}

TIP

To find out how to listen to other types of events, run the iroha events help command.

What's Next

Now that you understand the basics, you can explore these advanced documentation:

`,71),h=[e];function l(p,k,o,r,d,E){return a(),i("div",null,h)}const u=s(n,[["render",l]]);export{g as __pageData,u as default}; diff --git a/assets/guide_get-started_operate-iroha-2-via-cli.md.D3UDHgAT.lean.js b/assets/guide_get-started_operate-iroha-2-via-cli.md.D3UDHgAT.lean.js new file mode 100644 index 00000000..4ba115ee --- /dev/null +++ b/assets/guide_get-started_operate-iroha-2-via-cli.md.D3UDHgAT.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,V as t}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Operate Iroha 2 via CLI","description":"","frontmatter":{},"headers":[],"relativePath":"guide/get-started/operate-iroha-2-via-cli.md","filePath":"guide/get-started/operate-iroha-2-via-cli.md","lastUpdated":1727242778000}'),n={name:"guide/get-started/operate-iroha-2-via-cli.md"},e=t("",71),h=[e];function l(p,k,o,r,d,E){return a(),i("div",null,h)}const u=s(n,[["render",l]]);export{g as __pageData,u as default}; diff --git a/assets/guide_get-started_python.md.DD-VCkqN.js b/assets/guide_get-started_python.md.DD-VCkqN.js new file mode 100644 index 00000000..eb8ac6b9 --- /dev/null +++ b/assets/guide_get-started_python.md.DD-VCkqN.js @@ -0,0 +1,37 @@ +import{_ as i,c as s,o as a,V as t}from"./chunks/framework.B6c1f-8R.js";const y=JSON.parse('{"title":"Python 3 Guide","description":"","frontmatter":{},"headers":[],"relativePath":"guide/get-started/python.md","filePath":"guide/get-started/python.md","lastUpdated":1727242778000}'),e={name:"guide/get-started/python.md"},n=t(`

Python 3 Guide

1. Iroha 2 Client Setup

There are two versions of Iroha Python to choose from. In theory, the Iroha 1 version of Iroha Python (that also has the best documentation) should be compatible with an Iroha 2 deployment.

Thus we should build and install the Iroha 2 compatible version of Iroha-python, using (for now) its GitHub repository.

Let's create a separate folder for Iroha Python and clone its GitHub repository into it:

bash
$ cd ~/Git/
+$ git clone https://github.com/hyperledger/iroha-python/ --branch iroha2
+$ cd iroha-python

Iroha Python is written in Rust using the PyO3 library. Thus, unlike most Python packages, you must build it first:

bash
$ pip install maturin
+$ maturin build

After the build is complete, install it into your system:

bash
$ pip install ./target/wheels/iroha_python-*.whl

Finally, you will need a working client configuration:

bash
$ cp -vfr ~/Git/iroha/configs/client/config.json example/config.json

TIP

You can also use the provided config.json in the example folder if you also call docker compose up from that same folder. This has to do with the fact that the configuration for the Docker files in Iroha Python is slightly different.

2. Configuring Iroha 2

Unlike iroha binary, finding the configuration file in a scripting language is the responsibility of the person writing the script. The easiest method is to de-serialise a dictionary type from the provided config.json.

This is an example of how you could do that in Python:

python
import json
+from iroha2 import Client
+
+cfg = json.loads(open("config.json").read())
+cl = Client(cfg)

If the configuration file is malformed, you can expect an exception to notify you. However, the client doesn't do any verification: if the account used in config.json is not in the blockchain or has the wrong private key, you won't know that until you try and execute a simple instruction. More on that in the following section.

INFO

It should also be noted that Iroha Python is under heavy development. It severely lacks in documentation and its API can be made more idiomatically Python.

3. Registering a Domain

It is important to remember that Iroha Python is wrapping Rust code. As such, many of Python idioms are not yet accommodated; for example, there's no duck-typing of the Register instruction.

python
from iroha2.data_model.isi import *
+from iroha2.data_model.domain import *
+
+domain = Domain("looking_glass")
+register = Register(Expression(Value(Identifiable(domain))))

Instead, we are creating a domain and wrapping it in multiple type-erasing constructs. A domain is wrapped in Identifiable (which would be a trait in Rust), which is wrapped in Value, which is wrapped in Expression, which finally is wrapped in the Register instruction. This is not entirely against Python conventions (it is strongly typed, after all), and not entirely counter-intuitive, once you see the corresponding Rust code.

The instruction to register must be submitted, in order for anything to happen.

python
hash = cl.submit_isi(register)

Note that we also keep track of the hash of the transaction. This will become useful when you visualize the output.

4. Registering an Account

Registering an account is similar to the process of registering a domain, except the wrapping structures are different. There are a couple of things to watch out for.

First of all, we can only register an account to an existing domain. The best UX design practices dictate that you should check if the requested domain exists now, and if it doesn't, suggest a fix to the user.

python
from iroha2.data_model.isi import *
+from iroha2.data_model.account import *
+
+public_key =# Get this from white_rabbit.
+bunny = Account("white_rabbit@looking_glass", signatories=[public_key])
+register = Register(Expression(Value(Identifiable(bunny))))

Second, you should provide the account with a public key. It is tempting to generate both the public and the private key at this time, but it isn't the brightest idea. Remember that the white_rabbit trusts you, alice@wonderland, to create an account for them in the domain looking_glass, but doesn't want you to have access to that account after creation.

If you gave white_rabbit a key that you generated yourself, how would they know if you don't have a copy of their private key? Instead, the best way is to ask white_rabbit to generate a new key-pair, and then give you the public half of it.

After putting all of this together, we submit it as before:

python
hash = cl.submit_isi(register)

5. Registering and minting assets

Iroha has been built with few underlying assumptions about what the assets need to be in terms of their value type and characteristics (fungible or non-fungible, mintable or non-mintable).

Asset creation is by far the most cumbersome:

python
import iroha2.data_model.asset as asset
+from iroha2.sys.iroha_data_model import Value
+
+time = asset.Definition(
+    value_type=asset.ValueType.Quantity,
+    id=asset.DefinitionId(name="time", domain_name="looking_glass"),
+    metadata={"a": Value.U32(10)},
+    mintable=False
+)

Note the following; First, we used the **kwargs syntax to make everything more explicit.

We have a value_type which must be specified. Python is duck-typed, while Rust isn't. Make sure that you track the types diligently, and make use of mypy annotations.

The Quantity value type is an internal 32-bit unsigned integer. Your other options are BigQuantity, which is a 128-bit unsigned integer, and Fixed. All of these are unsigned. Any checked operation with a negative Fixed value (one that you got by converting a negative floating-point number), will result in an error.

Continuing the theme of explicit typing, the asset.DefinitionId is its own type. We could have also written asset.DefinitionId.parse("time#looking_glass"), but making sure that you know what's going on is more useful in this case.

Finally, we have mintable. By default this is set to True, however, setting it to False means that any attempt to mint more of time#looking_glass is doomed to fail. Unfortunately, since we didn't add any time at genesis, the white_rabbit will never have time. There just isn't any in his domain, and more can't be minted.

OK. So how about a mint demonstration? Fortunately, alice@wonderland has an asset called roses#wonderland, which can be minted. For that we need to do something much simpler.

python
amount = Expression(Value(U32(42)))
+destination = Expression(Value(Identifiable(asset.DefinitionId.parse("rose#wonderland"))))
+mint_amount = Mint(amount, destination)
+cl.submit_isi(mint_amount)

This would add 42 to the current tally of roses that Alice has.

6. Visualizing outputs

The paradigm that Iroha chose to allow monitoring some events is the filter-map paradigm. Let's look at what we need to do in order to know e.g. what happened to a submitted instruction.

First, we'll need to remember the hash of the transaction that we want to track, next we create a filter:

python
filter = EventFilter.Pipeline(
+    pipeline.EventFilter(
+        entity=pipeline.EntityType.Transaction(),
+        hash=None,
+    ))

And add a listener on that filter. Don't worry, the Rust side of the process is asynchronous, so barring issues with the GIL, you won't lock up your interpreter.

Note the types. The EventFilter is a type that filters out anything that isn't an event (and non-event types are beyond the scope of this tutorial). The pipeline module helps us by providing a concrete type of EventFilter, namely one that listens for transactions. Note that we haven't used the hash here.

Finally, we add a listening filter to the client:

python
listener = cl.listen(filter)

Now we must actually listen for events:

python
for event in listener:
+    print(event)
+
+    if event["Pipeline"]["status"] == "Committed" \\
+        and event["Pipeline"]["hash"] == hash:
+        break

And now, we have an infinite loop that will not quit until the event gets committed.

WARNING

Nobody should do this in production code, and instead monitor the event queue for (at least) the possibility that the transaction gets Rejected.

`,58),h=[n];function l(p,o,r,k,d,c){return a(),s("div",null,h)}const u=i(e,[["render",l]]);export{y as __pageData,u as default}; diff --git a/assets/guide_get-started_python.md.DD-VCkqN.lean.js b/assets/guide_get-started_python.md.DD-VCkqN.lean.js new file mode 100644 index 00000000..8a0d0161 --- /dev/null +++ b/assets/guide_get-started_python.md.DD-VCkqN.lean.js @@ -0,0 +1 @@ +import{_ as i,c as s,o as a,V as t}from"./chunks/framework.B6c1f-8R.js";const y=JSON.parse('{"title":"Python 3 Guide","description":"","frontmatter":{},"headers":[],"relativePath":"guide/get-started/python.md","filePath":"guide/get-started/python.md","lastUpdated":1727242778000}'),e={name:"guide/get-started/python.md"},n=t("",58),h=[n];function l(p,o,r,k,d,c){return a(),s("div",null,h)}const u=i(e,[["render",l]]);export{y as __pageData,u as default}; diff --git a/assets/guide_get-started_rust.md.DD6cfJYD.js b/assets/guide_get-started_rust.md.DD6cfJYD.js new file mode 100644 index 00000000..6aa2948b --- /dev/null +++ b/assets/guide_get-started_rust.md.DD6cfJYD.js @@ -0,0 +1,82 @@ +import{_ as s,c as i,o as a,V as t}from"./chunks/framework.B6c1f-8R.js";const y=JSON.parse('{"title":"Rust Guide","description":"","frontmatter":{},"headers":[],"relativePath":"guide/get-started/rust.md","filePath":"guide/get-started/rust.md","lastUpdated":1727242778000}'),n={name:"guide/get-started/rust.md"},e=t(`

Rust Guide

1. Iroha 2 Client Setup

In this part we shall cover the process of using the Iroha 2 Rust libraries. Instead of providing the complete basics, we shall assume knowledge of the most widely used concepts, explain what's unusual about Iroha 2 specifically, and provide a step-by-step guide to creating your own Rust client for it.

We assume that you know how to create a new package and have basic understanding of the fundamental Rust code; async functions, enum types, traits and borrowing/ownership, as well as the libraries that we use: serde, tokio, tracing, etc.

TIP

If you don't feel comfortable with any of the above, we recommend consulting the Rust book and docs.rs.

Iroha 2 makes extensive use of workspaces. Currently, there are two workspaces, the one that contains the WASM support library and the one that contains the core support libraries, which go in a domain-first order. What that means is that instead of having a global constants crate, we have a crate for the blockchain data model (iroha_data_model), a crate with cryptographic primitives (iroha_crypto), and so on. These, individually, have a module for constants.

If you add iroha_client to the other two crates, you get the minimum number of dependencies to start your own client, similar to iroha binary.

Once the initial v2.0.0 release is complete, we plan to create a package on crates.io with all the documentation. In the meantime, you could use the local copy that you've just created in the previous step as a local installation in your client's Cargo.toml:

toml
[dependencies]
+iroha_client = { version = "=2.0.0-pre-rc.13", path = "~/Git/iroha/client" }
+iroha_data_model = { version = "=2.0.0-pre-rc.13", path = "~/Git/iroha/data_model" }
+iroha_crypto = { version = "=2.0.0-pre-rc.13", path = "~/Git/iroha/crypto" }
+iroha_config = { version = "=2.0.0-pre-rc.13", path = "~/Git/iroha/config" }

The added benefit of using a local copy is that you have access to the minimal BFT network in the form of docker-compose.yml, which allows you to experiment. The drawbacks are mitigated by the fact that Rust links statically by default, so we recommend you experiment with the local set up first.

INFO

You could also make use of our test_network crate, which is available via GitHub but not via crates.io.

You would also benefit from having immediate access to the example configurations in the ~/Git/iroha/configs folder.

So let's copy the example client configuration somewhere useful:

bash
$ cp -vfr ~/Git/iroha/configs/client/config.json example/config.json

We recommend looking through it to familiarise yourself with the key pieces of information that every Iroha 2 client needs. Specifically, each client operates on behalf of a pre-existing account. These accounts are identified by a name@domain_name ID and can only be accessed provided that you know their specific key.

2. Configuring Iroha 2

Your application written in Rust needs to instantiate a client. The client typically needs specific configuration options, which you could either generate or load from the provided config.json. Let's do that now:

rs
rs
let config = Config::load("../configs/swarm/client.toml").unwrap();

Using said configuration, instantiate a client:

rs
// Create an Iroha client
+let iroha_client = Client::new(config);

Note that it used to be necessary to create a mutable client. Sending and receiving messages affects the client's internal state, but now that state is hidden behind interior mutable smart pointers.

Of course, depending on your application, you might want to de-serialise your ClientConfiguration structure from a different location. Perhaps, you might want to build the configuration in place using the command-line arguments, or perhaps, you're using the XDG specification to store the file persistently in a different location. For this purpose, it's useful to try and construct an instance of ClientConfiguration:

rust
use iroha_core::prelude::*;
+use iroha_data_model::prelude::*;
+
+let kp = KeyPair::new(
+    PublicKey::from_str(
+        r#"ed01207233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0"#,
+    )?,
+    PrivateKey::from_hex(
+        Algorithm::Ed25519,
+        "9ac47abf59b356e0bd7dcbbbb4dec080e302156a48ca907e47cb6aea1d32719e7233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0"
+            .into(),
+    )?
+)?;
+
+let (public_key, private_key) = kp.clone().into();
+let account_id: AccountId = "alice@wonderland".parse()?;
+
+let config = ClientConfiguration {
+    public_key,
+    private_key,
+    account_id,
+    torii_api_url: SmallStr::from_string(iroha_config::torii::uri::DEFAULT_API_URL.to_owned()),
+    ..ClientConfiguration::default()
+};

INFO

Note that the keys in client configuration are given in multi-hash format. If you are experiencing issues parsing the keys in this format, check the troubleshooting section.

3. Registering a Domain

Registering a domain is a relatively easy operation. Most of the boilerplate code has to do with setting up the Iroha 2 client and deserialising its configuration.

rs
use iroha_client::{
+    client::Client,
+    data_model::{
+        metadata::UnlimitedMetadata,
+        prelude::{Domain, DomainId, InstructionBox, Register},
+    },
+};

To register a domain, you need the domain name:

rs
// Create a domain Id
+let looking_glass: DomainId = "looking_glass".parse()?;

Which we convert into an instruction:

rs
// Create an ISI
+let create_looking_glass = Register::domain(Domain::new(looking_glass));

Note that we use RegisterBox and IdentifiableBox. Despite what your instincts as a Rust developer might suggest, we're not actually using any kind of dynamic dispatch. There's no dyn anywhere, and RegisterBox isn't an alias for Box<dyn Register>.

A RegisterBox is a specialised enum that uses static dispatch to achieve what looks like dynamic dispatch, without any heap allocation. If you want to add more types to RegisterBox you must either open an issue on GitHub, or do that by yourself on a local fork of Iroha.

The instruction is then batched into a transaction:

rs
// Prepare a transaction
+let metadata = UnlimitedMetadata::default();
+let instructions: Vec<InstructionBox> = vec![create_looking_glass.into()];
+let tx = iroha_client.build_transaction(instructions, metadata);

Which is then submitted into the pipeline:

rs
// Submit a prepared domain registration transaction
+iroha_client
+    .submit_transaction(&tx)
+    .wrap_err("Failed to submit transaction")?;

Note the question mark here. This will return an Err variant if there's something immediately and obviously wrong with the transaction: for example, if it couldn't submit the transaction to the peer (e.g. there's no connection), or if the transaction got rejected with an error. The cost is that the submit_transaction function is synchronous.

We could have also done the following:

rust
iroha_client
+    .submit_with_metadata(create_looking_glass, UnlimitedMetadata::default())?;

or

rust
iroha_client.submit(create_looking_glass)?;

The latter style is just syntactic sugar. Every submission comes in the form of a transaction that has metadata.

While the latter is a convenient shorthand that we shall use frequently, we strongly advise using explicit construction in production code.

INFO

It is likely that we shall replace most if not all instances of submit in our code base with explicit transactions.

4. Registering an Account

Registering an account is a bit more involved than registering a domain. With a domain, the only concern is the domain name. However, with an account, there are a few more things to worry about.

First of all, we need to create an AccountId. Note that we can only register an account to an existing domain. The best UX design practices dictate that you should check if the requested domain exists now, and if it doesn't, suggest a fix to the user. After that, we can create a new account named white_rabbit.

rs
use iroha_client::data_model::prelude::AccountId;
+
+// Create an \`iroha_client::data_model::AccountId\` instance
+// with a DomainId instance and a Domain ID for an account
+let longhand_account_id = AccountId::new("white_rabbit".parse()?, "looking_glass".parse()?);
+let account_id: AccountId = "white_rabbit@looking_glass"
+    .parse()
+    .expect("Valid, because the string contains no whitespace, has a single '@' character and is not empty after");
+
+// Check that two ways to define an account match
+assert_eq!(account_id, longhand_account_id);

Second, you should provide the account with a public key. It is tempting to generate both it and the private key at this time, but it isn't the brightest idea. Remember, that the white_rabbit trusts you, alice@wonderland, to create an account for them in the domain _looking_glass, but doesn't want you to have access to that account after creation.

If you gave white_rabbit a key that you generated yourself, how would they know if you don't have a copy of their private key? Instead, the best way is to ask white_rabbit to generate a new key-pair, and give you the public half of it:

rust
let key: PublicKey = get_key_from_white_rabbit();

Only then do we build an instruction from it:

rust
let create_account =
+    RegisterBox::new(IdentifiableBox::from(NewAccount::with_signatory(id, key)));

Which is then wrapped in a transaction and submitted to the peer as in the previous section.

5. Registering and minting assets

Iroha has been built with few underlying assumptions about what the assets need to be in terms of their value type and characteristics (fungible or non-fungible, mintable or non-mintable).

To register an asset, we first construct an iroha_data_model::asset::DefinitionId like so:

rs
// Create an asset
+let asset_def_id = AssetDefinitionId::from_str("time#looking_glass")
+    .expect("Valid, because the string contains no whitespace, has a single '#' character and is not empty after");

INFO

Note that we use # symbol to separate the name of the asset from the domain to which it belongs. This is intentional. This reflects the rule that there can be many alices in many domains, with only one alice per domain, and there can be an asset that is also named alice, but there can be only one, regardless of type.

Then construct an instruction:

rs
// Initialise the registration time
+let register_time =
+    Register::asset_definition(AssetDefinition::numeric(asset_def_id.clone()).mintable_once());
+
+// Submit a registration time
+iroha_client.submit(register_time)?;

This creates an asset time that can only be minted once and has the type fixed. AssetDefinition::fixed just like its other cousins (quantity and big_quantity) returns a builder of an AssetDefinition.

This asset is mintable_once, which means that the next time we mint it, we have to specify the entire amount that is going to exist for the rest of the existence of the blockchain.

rs
// Create a MintBox using a previous asset and account
+let mint = Mint::asset_numeric(numeric!(12.34), AssetId::new(asset_def_id, account_id));
+
+// Submit a minting transaction
+iroha_client.submit_all([mint])?;

Now imagine that the white_rabbit@looking_glass was not very keen and didn't notice that he wanted 123.4_f64 as the amount of time. Now white rabbit notices the problem and thinks "oh dear, not a lot of time has passed, perhaps I can give myself some more", and submits another mint request with 111.06_f64 instead of the original 12.34_f64. But, alas, no such luck. The white rabbit cannot mint more time and is thus perpetually late.

Roses, by contrast, are already registered in the network during the genesis round, and belong to alice@wonderland. Moreover, when they were registered, we didn't add the restriction, so we can mint them again and again as alice:

rs
let mint_roses = Mint::asset_numeric(42u32, AssetId::new(roses, alice));

Then submit the instruction as usual:

rs
iroha_client
+    .submit(mint_roses)
+    .wrap_err("Failed to submit transaction")?;

INFO

Our assets are strongly typed. As such, when you create a MintBox, you need to check that the asset has the correct underlying type. If you don't know the type, query it. This is also why we specifically annotate numerical literals with their type.

Contrary to what you might think, this restriction isn't just for pedantry. Implicit conversion errors are the bane of all programmers, if you got the AssetValueType incorrect, how do you know that it was the only mistake in that transaction?

6. Transferring assets

Transferring assets is a bit more involved than minting them. First, you need to know the account ID of the account that you're transferring from and the account ID of the account that you're transferring to.

rust
let from_account_id: AccountId = "alice@wonderland".parse().unwrap();
+let to_id: AccountId = "bob@wonderland".parse().unwrap();

You also need to know the asset ID of the asset that you're transferring:

rust
let asset_definition_id: AssetDefinitionId = "time#looking_glass".parse().unwrap();
+let from_asset_id = AssetId::new(asset_definition_id, from_account_id);

Then you need to specify the amount that you're transferring:

rust
let amount = 1 as u32;
+let value: Value = amount.into();

Then you can create a transfer instruction and submit it:

rust
let from_id_box = IdBox::AssetId(from_asset_id);
+let to_id_box = IdBox::AccountId(to_id);
+let transfer_expr = TransferExpr::new(from_id_box, value, to_id_box);
+client.submit(transfer_expr);

7. Burning assets

Burning assets is quite similar to minting. First, you create the burn instruction indicating which asset to burn and its quantity.

rs
// Burn the Asset instance
+let burn_roses = Burn::asset_numeric(10u32, AssetId::new(roses, alice));

Then submit this instruction:

rust
iroha_client.submit(burn_roses)?;

8. Visualising outputs

Finally, we should talk about visualising data. The Rust API is currently the most complete in terms of available queries and instructions. After all, this is the language in which Iroha 2 was built.

We shall, however, leave most of the aforementioned advanced features down the rabbit hole, up to the reader's own devices to discover. This document can easily get out of sync with the state of the API features. By contrast, the online documentation is always up to date. Plus a short tutorial wouldn't be able to do all these features justice. Instead, we shall retain parity with other language tutorials and introduce you to pipeline filters.

There are two possible event filters: PipelineEventFilter and DataEventFilter, we shall focus on the former. This filter sieves events pertaining to the process of submitting a transaction, executing a transaction, and committing it to a block.

First, let's build a filter:

rust
use iroha_data_model::prelude::*;
+
+let filter = FilterBox::Pipeline(PipelineEventFilter::identity());

Then, we start listening for events in an infinite loop:

rust
for event in iroha_client.listen_for_events(filter)? {
+    match event {
+        Ok(event) => println!("Success: {:#?}", event),
+        Err(err) => println!("Sadness:( {:#?}",  err),
+    }
+};

Needless to say, an synchronous infinite blocking loop is bad UX for anything but a command-line program, but for illustration purposes, this would create a nice printout, just like in iroha binary.

`,95),h=[e];function l(p,k,r,o,d,g){return a(),i("div",null,h)}const E=s(n,[["render",l]]);export{y as __pageData,E as default}; diff --git a/assets/guide_get-started_rust.md.DD6cfJYD.lean.js b/assets/guide_get-started_rust.md.DD6cfJYD.lean.js new file mode 100644 index 00000000..e0dbde56 --- /dev/null +++ b/assets/guide_get-started_rust.md.DD6cfJYD.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,V as t}from"./chunks/framework.B6c1f-8R.js";const y=JSON.parse('{"title":"Rust Guide","description":"","frontmatter":{},"headers":[],"relativePath":"guide/get-started/rust.md","filePath":"guide/get-started/rust.md","lastUpdated":1727242778000}'),n={name:"guide/get-started/rust.md"},e=t("",95),h=[e];function l(p,k,r,o,d,g){return a(),i("div",null,h)}const E=s(n,[["render",l]]);export{y as __pageData,E as default}; diff --git a/assets/guide_get-started_tutorials.md.Czean8cR.js b/assets/guide_get-started_tutorials.md.Czean8cR.js new file mode 100644 index 00000000..7fc53882 --- /dev/null +++ b/assets/guide_get-started_tutorials.md.Czean8cR.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as a,V as o}from"./chunks/framework.B6c1f-8R.js";const f=JSON.parse('{"title":"Introduction","description":"","frontmatter":{},"headers":[],"relativePath":"guide/get-started/tutorials.md","filePath":"guide/get-started/tutorials.md","lastUpdated":1727242778000}'),i={name:"guide/get-started/tutorials.md"},r=o('

Introduction

Welcome to the Hyperledger Iroha 2 tutorial. This document is designed to help you get started with Iroha 2, regardless of your knowledge of Hyperledger technology, coding experience or familiarity with blockchains.

Preamble

This tutorial is suitable for both experienced developers, prospective users, and people casually curious about blockchain technology. The level of detail is sufficient so that you wouldn't need any supplementary guide. However, should you want to learn more, we have more detailed documentation in the works.

In this guide, we shall

  • walk you through starting an Iroha network, either with docker (recommended) or using one of the provided scripts;
  • introduce you to the client libraries;
  • take a small detour into the basic concepts of Iroha special instructions, and how they interact with the world state.

We invite you to follow the tutorial in this order:

  1. If you are already familiar with Hyperledger Iroha, read about the differences between the two versions of Iroha.
  2. Install Iroha 2.
  3. Follow one of the language-specific guides to learn how to set up and configure Iroha 2, register a domain and an account, register and mind assets, and visualize outputs:

Tutorial Updates

The current iteration of the Iroha 2 tutorial is a constant work in progress. We are updating the tutorial with each release to reflect the state of Iroha and the newly added features. While we do our best to keep this tutorial up to date, it can go out of sync by a few days or maybe a week.

',11),l=[r];function s(n,d,h,u,c,p){return a(),t("div",null,l)}const m=e(i,[["render",s]]);export{f as __pageData,m as default}; diff --git a/assets/guide_get-started_tutorials.md.Czean8cR.lean.js b/assets/guide_get-started_tutorials.md.Czean8cR.lean.js new file mode 100644 index 00000000..4d7ddd95 --- /dev/null +++ b/assets/guide_get-started_tutorials.md.Czean8cR.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as a,V as o}from"./chunks/framework.B6c1f-8R.js";const f=JSON.parse('{"title":"Introduction","description":"","frontmatter":{},"headers":[],"relativePath":"guide/get-started/tutorials.md","filePath":"guide/get-started/tutorials.md","lastUpdated":1727242778000}'),i={name:"guide/get-started/tutorials.md"},r=o("",11),l=[r];function s(n,d,h,u,c,p){return a(),t("div",null,l)}const m=e(i,[["render",s]]);export{f as __pageData,m as default}; diff --git a/assets/guide_iroha-2.md.Bj0eOTQ9.js b/assets/guide_iroha-2.md.Bj0eOTQ9.js new file mode 100644 index 00000000..78c40e72 --- /dev/null +++ b/assets/guide_iroha-2.md.Bj0eOTQ9.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as t,V as o}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Iroha 2 vs. Iroha 1","description":"","frontmatter":{},"headers":[],"relativePath":"guide/iroha-2.md","filePath":"guide/iroha-2.md","lastUpdated":1727242778000}'),i={name:"guide/iroha-2.md"},r=o('

Iroha 2 vs. Iroha 1

Iroha 2 is a complete rewrite of Hyperledger Iroha in Rust.

In this introduction we outline the differences between the two versions of Iroha and highlight the new features of Iroha 2. It should be of particular interest to those who are already familiar with Iroha but wish to upgrade and start using the newer version.

Note

Iroha 1 and Iroha 2 are not compatible. Both projects are very different in their approaches and implementations as evident from the comparisons below.

Among other changes, cryptography and account structures are implemented differently, meaning that users would have to generate new keys and link their new account with the old one through a centralized service, and no data from Iroha 1 would be accessible from Iroha 2.

Fault Tolerance

Iroha 2 learned a great deal from the development of the original Iroha. Of particular importance is the new and improved Byzantine-fault-tolerant consensus algorithm—Sumeragi—that allowed us to expand what could be done on a blockchain without any security risks.

INFO

Iroha 1 uses a consensus algorithm called Yac. Yac is crash-fault-tolerant, which means that it can survive a set number of nodes crashing, i.e., losing power, being cut off from the network, or being destroyed with a sledgehammer.

Sumeragi, by contrast, was designed to be Byzantine-fault-tolerant. This means that Iroha 2 can tolerate not only peers being inactive on the network, but also running malicious software and actively trying to falsify data in the blockchain.

We can mathematically prove that Iroha 2 can work when up to 33% of its nodes are actively trying to stop Iroha 2 from working properly or at all. In other words, even if someone gained control of a third of all of your network nodes, an Iroha 2 deployment is mathematically guaranteed to keep working.

Minimalist Code Base

Iroha 2 utilizes a minimalist code base. We take great care to vet our dependencies and avoid large interdependent chunks of code.

We provide a few telemetry APIs, including prometheus tooling, structured logging in JSON, as well as compatibility with standard tools used in Parity Substrate.

Our data is strongly-typed, our methods are statically dispatched. We make use of the best that Rust has to offer: serde and parity_scale_codec for serialisation, tokio for co-operative multi-threading, as well as testing, bench-marking, static analysis and code auditing tools that come packaged with the exemplary cargo.

Our code is easy to reason about, and quick to compile, whilst also being ergonomic to use and thoughtfully crafted. We have no panics and no unsafe code.

Flexibility

Iroha 2 is also more flexible than the original Iroha due to its modular design.

It is possible to add or remove features based on a particular use-case. If you want the blockchain to be extremely fast and work on embedded hardware, just compile Iroha 2 without the expensive metrics feature. Don't use telemetry at all? Remove it entirely and enjoy even more performance. Permission sets are plugins that can be upgraded during run-time.

We have an extensive module system as well as a robust WASM runtime framework.

Smart Contracts

Iroha 2 is an event-driven ledger. Each change in the state of the blockchain is necessarily accompanied by its own event that can trigger a smart contract: complex logic designed for use in on-chain scripting.

For smart contracts, Iroha 2 supports two approaches:

The first approach is useful when you want very simple transparent logic and also want to minimize the footprint in the blockchain. All interactions with the World state, that is, the state of the blockchain at any given point in time, has to be done using the aforementioned instructions. There is also rudimentary support for domain-specific conditional logic.

If you want to learn more about smart contracts in Iroha 2, please consult our Wiki.

Static and Dynamic Linking

Iroha 2 smartly chooses when to use dynamic linking. This strikes a balance between it being easy to patch a critical security vulnerability in a vendored library like OpenSSL, but also remaining reproducible and portable across platforms, architectures, and deployments.

INFO

You get the best of both worlds. Patching a security vulnerability is as easy as running sudo apt upgrade. On the other hand, only security-critical dependencies are linked dynamically, so it is highly unlikely that any of the smaller and less important libraries can break Iroha after an upgrade.

Testing

Iroha 2 is extensively tested. Despite being in active development, Iroha has 80% line coverage. Keep in mind that line coverage includes documentation comments, some of which are also tests.

INFO

There are plans to include Fuzz testing, property-based testing, and failure-point testing to ensure that Iroha is reliable.

',28),n=[r];function s(l,c,h,d,m,p){return t(),a("div",null,n)}const f=e(i,[["render",s]]);export{g as __pageData,f as default}; diff --git a/assets/guide_iroha-2.md.Bj0eOTQ9.lean.js b/assets/guide_iroha-2.md.Bj0eOTQ9.lean.js new file mode 100644 index 00000000..8e6a80b4 --- /dev/null +++ b/assets/guide_iroha-2.md.Bj0eOTQ9.lean.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as t,V as o}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Iroha 2 vs. Iroha 1","description":"","frontmatter":{},"headers":[],"relativePath":"guide/iroha-2.md","filePath":"guide/iroha-2.md","lastUpdated":1727242778000}'),i={name:"guide/iroha-2.md"},r=o("",28),n=[r];function s(l,c,h,d,m,p){return t(),a("div",null,n)}const f=e(i,[["render",s]]);export{g as __pageData,f as default}; diff --git a/assets/guide_reports_csd-rtgs.md.DeBNoVPL.js b/assets/guide_reports_csd-rtgs.md.DeBNoVPL.js new file mode 100644 index 00000000..01b1ac25 --- /dev/null +++ b/assets/guide_reports_csd-rtgs.md.DeBNoVPL.js @@ -0,0 +1 @@ +import{_ as t,c as o,o as s,m as e,a}from"./chunks/framework.B6c1f-8R.js";const m=JSON.parse('{"title":"CSD/RTGS linkages Proof of concept","description":"","frontmatter":{},"headers":[],"relativePath":"guide/reports/csd-rtgs.md","filePath":"guide/reports/csd-rtgs.md","lastUpdated":1727242778000}'),r={name:"guide/reports/csd-rtgs.md"},c=e("h1",{id:"csd-rtgs-linkages-proof-of-concept",tabindex:"-1"},[a("CSD/RTGS linkages Proof of concept "),e("a",{class:"header-anchor",href:"#csd-rtgs-linkages-proof-of-concept","aria-label":'Permalink to "CSD/RTGS linkages Proof of concept"'},"​")],-1),n=e("p",null,"In this document we will describe the CSD/RTGS linkages PoC execution via Iroha. This is a project which was done in collaboration with the Asian Development Bank, and Fujitsu. Other participants used technologies such as R3 Corda, Hyperledger Cactus (Cacti), Hyperledger Fabric and many other popular blockchain solutions.",-1),i=[c,n];function d(l,p,h,f,g,u){return s(),o("div",null,i)}const k=t(r,[["render",d]]);export{m as __pageData,k as default}; diff --git a/assets/guide_reports_csd-rtgs.md.DeBNoVPL.lean.js b/assets/guide_reports_csd-rtgs.md.DeBNoVPL.lean.js new file mode 100644 index 00000000..01b1ac25 --- /dev/null +++ b/assets/guide_reports_csd-rtgs.md.DeBNoVPL.lean.js @@ -0,0 +1 @@ +import{_ as t,c as o,o as s,m as e,a}from"./chunks/framework.B6c1f-8R.js";const m=JSON.parse('{"title":"CSD/RTGS linkages Proof of concept","description":"","frontmatter":{},"headers":[],"relativePath":"guide/reports/csd-rtgs.md","filePath":"guide/reports/csd-rtgs.md","lastUpdated":1727242778000}'),r={name:"guide/reports/csd-rtgs.md"},c=e("h1",{id:"csd-rtgs-linkages-proof-of-concept",tabindex:"-1"},[a("CSD/RTGS linkages Proof of concept "),e("a",{class:"header-anchor",href:"#csd-rtgs-linkages-proof-of-concept","aria-label":'Permalink to "CSD/RTGS linkages Proof of concept"'},"​")],-1),n=e("p",null,"In this document we will describe the CSD/RTGS linkages PoC execution via Iroha. This is a project which was done in collaboration with the Asian Development Bank, and Fujitsu. Other participants used technologies such as R3 Corda, Hyperledger Cactus (Cacti), Hyperledger Fabric and many other popular blockchain solutions.",-1),i=[c,n];function d(l,p,h,f,g,u){return s(),o("div",null,i)}const k=t(r,[["render",d]]);export{m as __pageData,k as default}; diff --git a/assets/guide_security_generating-cryptographic-keys.md.yXKGjTVS.js b/assets/guide_security_generating-cryptographic-keys.md.yXKGjTVS.js new file mode 100644 index 00000000..82a38187 --- /dev/null +++ b/assets/guide_security_generating-cryptographic-keys.md.yXKGjTVS.js @@ -0,0 +1,47 @@ +import{_ as i,c as a,o as s,V as e}from"./chunks/framework.B6c1f-8R.js";const u=JSON.parse('{"title":"Generating Cryptographic Keys","description":"","frontmatter":{},"headers":[],"relativePath":"guide/security/generating-cryptographic-keys.md","filePath":"guide/security/generating-cryptographic-keys.md","lastUpdated":1727242778000}'),t={name:"guide/security/generating-cryptographic-keys.md"},n=e(`

Generating Cryptographic Keys

In the realm of blockchain technology, cryptographic keys play a crucial role in upholding the security and authenticity of data transactions. With Iroha 2, you can create these vital keys to safeguard your digital assets and communications.

This section describes how to generate keys using the kagami tool, shipped alongside Iroha 2.

In the future, alternative methods of generating public keys shall be added.

Generating Cryptographic Keys with Kagami

TIP

Since kagami does not come with a manual page, you can use the --help (-h) command to retrieve a brief summary of all the usable kagami parameters within the CLI you are using.

After installing Iroha, run the following command from the project's root directory to generate a new key pair:

bash
$ cargo run --bin kagami --release -- crypto

You can specify a number of different parameters to tailor the generated key pair to your specific needs. The following parameters are available:

  • --algorithm (-a): Specifies the algorithm used for the key pair generation and encryption. If no algorithm is specified, ed25519 is used by default. Can be one of the following:

    • ed25519ECC an algorithm that utilises the Ed25519 curve, offering efficient and secure cryptographic operations for digital signatures and key exchange. If no algorithm is specified in a request, then ed25519 is used by default. Learn more:

    • secp256k1ECC an algorithm known for its application in blockchain systems like Bitcoin. It provides a robust foundation for secure key generation, digital signatures, and encryption.

    Learn more:
    Secp256k1 (Bitcoin Wiki)

    • bls_small — The Boneh-Lynn-Shacham algorithm with a small parameter configuration. This variant of the BLS cryptographic scheme is optimised for efficiency in certain resource-constrained environments while maintaining fundamental security properties.

    Learn more:
    BLS digital signature (Wikipedia)

    • bls_normal — The Boneh-Lynn-Shacham algorithm with a standard parameter configuration. This configuration of the BLS cryptographic scheme offers a balanced approach between efficiency and security, making it suitable for a wide range of applications in blockchain and cryptographic protocols.

    Learn more:
    BLS digital signature (Wikipedia)

  • --seed (-s): Specifies a string that serves as a deterministic starting point for the key pair generation. If a seed string is specified, kagami will generate the same key for the same string. If no seed is specified, a random seed value is chosen, and each invocation of kagami crypto will result in a different key. This parameter accepts a valid string of Unicode characters. For example, the seed string can contain not only numeric and latin, but also cyrillic, logographic (e.g., Japanese kanji characters) and ideographic (e.g., emojis) characters, as well as any font-related variations of those characters introduced to Unicode over the years.

    TIP

    If one chooses to use a seed, it must be treated as if it were a password: more randomness and longer seed strings make the cryptographic keys more resilient to dictionary attacks.

  • --private-key (-p): Specifies an existing private key as a string in the multihash format that is used to generate a public key.

  • --json (-j): Specifies that the output must be generated in the JSON format, which is mostly helpful for copy-and-pasting into the config.json file.

  • --compact (-c): Specifies that the output private and public keys are displayed on separate lines and are not labeled.

Examples

bash

+# Input
+$ cargo run --bin kagami crypto
+
+# Possible Output (same layout, different keys)
+Public key (multihash): "ed01206B0F56F58761060056355DBA0E0FC489CFB2F974481ED64873082E6032796235"
+Private key (ed25519): "F71EA9D897C4338CBF4F1DC7B492AAD0BF6CE896B803D7CDB9CF25ECC15109826B0F56F58761060056355DBA0E0FC489CFB2F974481ED64873082E6032796235"
bash
# Input
+$ kagami crypto -a secp256k1
+
+# Possible output
+Public key (multihash): "e70121022A9D6E0D54022C0E2752E43ADD91ADA28259E1F2CE0C6D4E9183FB2882DE6749"
+Private key (secp256k1): "7687B1433FB6731E6DC635A376B3EB3B5FCD1E02C9775C1642E7FD5DA035EC75"
bash
# Input
+$ kagami crypto -s 1729
+
+# Exact output
+Public key (multihash): "ed0120B678073CFAE6E247A58B442661C7DA0E13BAC5031CBC6343EF566B8718D47D04"
+Private key (ed25519): "2669BB1099477B970E1D7D7C54E345A64A54213FCFBA2465CBCD6D4E5091A71DB678073CFAE6E247A58B442661C7DA0E13BAC5031CBC6343EF566B8718D47D04"
bash

+# Input
+$ kagami crypto -p 2669BB1099477B970E1D7D7C54E345A64A54213FCFBA2465CBCD6D4E5091A71DB678073CFAE6E247A58B442661C7DA0E13BAC5031CBC6343EF566B8718D47D04
+
+# Exact output
+Public key (multihash): "ed0120B678073CFAE6E247A58B442661C7DA0E13BAC5031CBC6343EF566B8718D47D04"
+Private key (ed25519): "2669BB1099477B970E1D7D7C54E345A64A54213FCFBA2465CBCD6D4E5091A71DB678073CFAE6E247A58B442661C7DA0E13BAC5031CBC6343EF566B8718D47D04"
bash
# Input
+$ cargo run --bin kagami crypto -j
+
+# Possible output
+{
+  "public_key": "ed0120B678073CFAE6E247A58B442661C7DA0E13BAC5031CBC6343EF566B8718D47D04",
+  "private_key": {
+    "digest_function": "ed25519",
+    "payload": "2669bb1099477b970e1d7d7c54e345a64a54213fcfba2465cbcd6d4e5091a71db678073cfae6e247a58b442661c7da0e13bac5031cbc6343ef566b8718d47d04"
+  }
+}
bash
# Input
+$ cargo run --bin kagami crypto -c
+
+# Possible output
+ed0120B678073CFAE6E247A58B442661C7DA0E13BAC5031CBC6343EF566B8718D47D04
+2669BB1099477B970E1D7D7C54E345A64A54213FCFBA2465CBCD6D4E5091A71DB678073CFAE6E247A58B442661C7DA0E13BAC5031CBC6343EF566B8718D47D04
+ed25519
bash
# Input
+$ cargo run --bin kagami crypto -a bls_normal -s 2048
+
+# Exact output
+Public key (multihash): "ea01610402A54ABCC40819F15E3553CC8D42D628EEAD7E1B10724BD2AFE523A7C0446EB1CB3F14D4500BD68C997784136FD056BA04215DFD2D3FDC7883B43AE94AC52B7D01525F5A80B41C01701502B46DBB9F0384CC7BE037DC2CBC928014E52A4C5C3B"
+Private key (bls_normal): "0000000000000000000000000000000035D9120A174E35E966DD92DE90B2446D4B060C8B72018B3917A1C97D7E93EAEC"

Other Operations with Kagami

1. Building kagami

The Iroha 2 node binary and all supporting tools are supplied in the official docker image. However, using it like this is cumbersome, as kagami is meant to be used as a standalone external tool, so building it from a source may be helpful.

To build kagami, run the following:

bash
$ cargo build --bin kagami

This will produce a single statically linked executable in the target/debug directory, that still links dynamically against the system-provided standard C-library.

Note

Iroha and all supporting tools can also be built to statically link against the musl standard library, which allows the application to run on any POSIX-compliant ELF-capable system (all GNU+Linux distributions, some BSD variants).

2. Installing the source-built kagami into /bin

There are multiple ways to make your command line be able to use the kagami version that you have just compiled. One of the easiest ways that should work on most systems is to move or link the binary into the /bin directory on UNIX systems.

bash
$ sudo mv target/debug/kagami /bin

3. Moving kagami to the .local/bin directory

To circumvent the requirement of having the binary in the global binary folder, and thus necessarily exposing the binary to all other users, as well as requiring root authentication (which is not always available), one can instead install the application as a regular user.

To move kagami to the authenticated user's .local/bin directory, making it uniquely accessible only by that user, run the following:

bash
$ mv target/debug/kagami ~/.local/bin

This method works on most GNU Linux distributions, but is not guaranteed to do so. If it doesn't, consult the next subtopic.

Making the <username>/.local/bin directory available to the shell

To make the <username>/.local/bin directory explicitly available to your shell's .rc file, perform the following:

  1. Check if kagami is available by running the following:
bash
$ whereis kagami
+kagami:
  1. Depending on the shell that you are using, perform one of the following:
  • If using Bash: Fix the PATH variable for the shell and then reload the .bashrc script by running the following:

    bash
    $ echo "export PATH='\${HOME}/.local/bin:\${PATH}'" >> ~/.bashrc
    +$ source ~/.bashrc
  • If using Zsh: Fix the PATH variable for the shell and reload the .zshrc script by running the following:

    bash
    $ echo "export PATH='\${HOME}/.local/bin:\${PATH}'" >> ~/.zshrc
    +$ source ~/.zshrc
  • If using fish: Fix the PATH variable for the shell variable permanently by running the following:

    bash
    $ fish_add_path ~/.local/bin

INFO

In addition to the methods listed above, consult documentation for the shell you're using or consider adding the PATH variant to your terminal's session configuration.

`,34),l=[n];function h(p,o,r,k,d,c){return s(),a("div",null,l)}const y=i(t,[["render",h]]);export{u as __pageData,y as default}; diff --git a/assets/guide_security_generating-cryptographic-keys.md.yXKGjTVS.lean.js b/assets/guide_security_generating-cryptographic-keys.md.yXKGjTVS.lean.js new file mode 100644 index 00000000..d21a2b02 --- /dev/null +++ b/assets/guide_security_generating-cryptographic-keys.md.yXKGjTVS.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as s,V as e}from"./chunks/framework.B6c1f-8R.js";const u=JSON.parse('{"title":"Generating Cryptographic Keys","description":"","frontmatter":{},"headers":[],"relativePath":"guide/security/generating-cryptographic-keys.md","filePath":"guide/security/generating-cryptographic-keys.md","lastUpdated":1727242778000}'),t={name:"guide/security/generating-cryptographic-keys.md"},n=e("",34),l=[n];function h(p,o,r,k,d,c){return s(),a("div",null,l)}const y=i(t,[["render",h]]);export{u as __pageData,y as default}; diff --git a/assets/guide_security_index.md.CyMsOmKt.js b/assets/guide_security_index.md.CyMsOmKt.js new file mode 100644 index 00000000..ca4f8fd5 --- /dev/null +++ b/assets/guide_security_index.md.CyMsOmKt.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as i,V as a}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Security","description":"","frontmatter":{},"headers":[],"relativePath":"guide/security/index.md","filePath":"guide/security/index.md","lastUpdated":1727242778000}'),r={name:"guide/security/index.md"},o=a('

Security

When utilizing Iroha 2—or any other blockchain ledger for that matter—security is paramount for financial organizations, as it forms the foundation of trust in an industry where sensitive financial data and transactions are routine. A successful security breach performed by a malicious party can lead to devastating consequences for you. Therefore establishing preemptive security measures is essential to protect the integrity and confidentiality of your sensitive data.

In this section you can learn about various aspects of securing your Iroha 2 network. To learn more, choose one of the following topics:

  • Security Principles:

    The core security principles that individuals and organizations can adopt to protect their data and decrease the chance of a breach and/or leak.

  • Operational Security:

    Best practices for securing the day-to-day operations of your network, including access controls, monitoring, incident responses, the use of browsers, etc.

  • Password Security:

    A deep-dive into password entropy, creating strong passwords and avoiding password vulnerabilities.

  • Public Key Cryptography:

    An introduction into public key cryptography, encryption, signatures, and their role in establishing secure communication within the blockchain.

    • Generating Cryptographic Keys:

      Instructions on how to generate cryptographic keys and use kagami (a supporting tool shipped alongside Iroha 2).

    • Storing Cryptographic Keys:

      Best practices for securing your cryptographic keys with a number of different approaches that can also be combined.

',5),n=[o];function s(c,p,l,h,u,d){return i(),t("div",null,n)}const f=e(r,[["render",s]]);export{g as __pageData,f as default}; diff --git a/assets/guide_security_index.md.CyMsOmKt.lean.js b/assets/guide_security_index.md.CyMsOmKt.lean.js new file mode 100644 index 00000000..be8148a8 --- /dev/null +++ b/assets/guide_security_index.md.CyMsOmKt.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as i,V as a}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Security","description":"","frontmatter":{},"headers":[],"relativePath":"guide/security/index.md","filePath":"guide/security/index.md","lastUpdated":1727242778000}'),r={name:"guide/security/index.md"},o=a("",5),n=[o];function s(c,p,l,h,u,d){return i(),t("div",null,n)}const f=e(r,[["render",s]]);export{g as __pageData,f as default}; diff --git a/assets/guide_security_operational-security.md.DtcsL8SB.js b/assets/guide_security_operational-security.md.DtcsL8SB.js new file mode 100644 index 00000000..78a0f045 --- /dev/null +++ b/assets/guide_security_operational-security.md.DtcsL8SB.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as r,V as t}from"./chunks/framework.B6c1f-8R.js";const f=JSON.parse('{"title":"Operational Security","description":"","frontmatter":{},"headers":[],"relativePath":"guide/security/operational-security.md","filePath":"guide/security/operational-security.md","lastUpdated":1727242778000}'),i={name:"guide/security/operational-security.md"},o=t('

Operational Security

Operational Security (OPSEC) is a systematic approach to security and risk management, which is essentially a collection of strategies and advice adopted for specific use-cases with the aim of preventing unauthorized access and data leakage.

OPSEC is the standard practice for most companies to guarantee the availability and stability of their assets. This includes considering such factors as physical security (e.g., making sure that unattended post-it notes do not contain sensitive data), secure communication protocols (e.g., not sending sensitive data over unencrypted SMS), threat analysis (e.g., determining potential malicious parties, learning about the latest attack methods), personnel training (e.g., without employees following OPSEC measures, they will, sooner or later, prove to be ineffective), and risk mitigation (e.g., encrypting your hard drives and USB devices).

Since Iroha 2 is likely to be deployed as a financial ledger, OPSEC measures and practices must be taken seriously. This topic describes strategies and approaches that individuals and organizations using Iroha 2 in their operations should consider as part of their extensive security protocol.

Following and adopting the guidelines in this topic is a necessary step towards achieving total security, however, it is not sufficient on its own. To further improve your security, learn more throughout the rest of the Security section and specifically the following topics:

  • Stay vigilant. The most likely way in which one can lose their assets in a blockchain is by giving away their sensitive details.

  • Encrypt your disks. Encrypting boot devices allows them to protect your data even if an attacker have gained access to the hardware. Doing it for your portable devices is twice as important.

  • Use trusted software. Software that ships via reproducible binary builds, and that you build from source, is the most trustworthy. Proprietary or open-source software that hasn't been audited is a potential risk that must be taken seriously.

  • Never leave portable devices with sensitive data unattended. A split second is enough to steal your device.

  • Verify the signatures on binary packages. This is not too different from the public key cryptography used inside Iroha v2.

  • To prevent unauthorized access, always secure your laptop or personal computer when leaving it unattended. Use strong passwords, lock the screen, and follow best practices for securing your devices.

  • Establish a secure air-gapped location for your keys. First, encrypt the keys, then store them in an offline-only device, ideally with electromagnetic shielding installed. Hardware keys are specifically designed this purpose.

  • Always keep your software updated to their latest version across all devices, including computers and phones. Regular updates help patch vulnerabilities and minimise potential risks associated with outdated software, even before such vulnerabilities are disclosed.

  • Develop a routine for periodically updating passwords and cryptographic keys. This proactive approach significantly contributes to enhancing overall security posture, since it is much harder to hit a moving target.

Using Browsers

If an application connected to Iroha 2 features a web UI, your browser can either aid the security or pose a potential threat. It is essential to exercise caution, especially when it comes to the plugins you choose to install.

Consider the following measures to enhance your browsing security:

  • Avoid using browsers that are known for having bad security models and for leaking their users' data.

    You can look up privacy violations and security issues for any browser. For example, this article on browser privacy discusses a variety of browsers and how secure they are. Note that proprietary browsers (such as Chrome, Safari, Opera, Vivaldi, Edge, and others) are generally tremendously harder to audit due to their code being hidden from public, which means that you cannot be sure how secure they are.

  • Give preference to browsers with solid history of valuing and protecting their users' privacy and security:

    • Librewolf, Icecat, Firedragon, etc. — well established forks of Mozilla Firefox with added security features.
    • Ungoogled chromium — a highly audited open-source version of Google Chrome that is enhanced with additional security measures and has all of the Google-related web services removed.
    • Brave — a highly audited open-source version of Google Chromium that is enhanced with additional security measures; has a built-in VPN and ad blocker functionality.
    • Falkon — an open-source Qt-based web browser (built on QtWebEngine, a wrapper for Google Chromium) with known track record of being secure; has a number of extensions available for download from its KDE store page.
    • Qutebrowser — an open-source Qt-based web browser (built on QtWebEngine, a wrapper for Google Chromium) with known track record of being secure; has a unique keyboard-focused approach with minimalist GUI; considered to be a browser of choice for many security specialists.
  • Avoid enabling JavaScript unless necessary.

  • Use the browser's built-in confinement mechanism for plugins to restrict the access rights that the installed plugins have.

  • Clear cookies before and after important operations. Be mindful not to enable the Keep Me Signed In or Remember me feature. Keep in mind that some websites have this feature enabled by default.

  • Use an ad blocker. These not only block ads but also disable site tracking features. Depending on the browser you use, an ad blocker may not be a built-in feature.

  • Be mindful of lookalike characters (e.g., 0, θ, O, О, and ߀ are six different characters). Paying attention to details like this may save you from a phishing attack.

  • Avoid web UI email clients in favour of desktop clients. Before using it, set up your desktop email client to sign and verify GPG key signatures.

  • Avoid using web-based messaging services. For instance, Discord (built with the infamous electron framework) is susceptible to many of the same attacks as would a Google Chromium window with the web version of Discord open.

  • Update your browser to the latest version whenever possible. Updates often include critical security patches that address vulnerabilities.

  • Be cautious of what browser extensions you install. Only use well-known and trusted extensions from reputable sources. Rogue extensions can compromise your data and privacy.

  • Create separate browser profiles for various tasks. Use one profile for everyday browsing and another for activities involving high security and sensitive data. This way, extensions installed on the profile for everyday browsing cannot access the sensitive data from the secure one.

  • Use a portable version of your browser copied to a USB flash drive. This method ensures that even if a security bug grants one of the installed plugins with access to data between the profiles, your security-related profile remains on a separate and removable device.

  • Periodically clear your browser's cache and cookies to remove potentially sensitive data that may accidentally be stored on your device.

Recovery Plan

In the event of an emergency, such as losing a key or facing a security breach, a well-structured and prepared in advance recovery plan is an essential lifeline. Creating a clear set of steps to follow can help mitigate potential damage and promptly reinstate security.

Organizations should consider the following key aspects when developing their recovery plan:

  • Outline step-by-step procedures to be followed in case of key loss or other security incidents. Ensure that these steps are easily accessible and understandable by the users and/or employees.

  • Establish a communication channel that may be used to promptly report security breaches and potential threats, such as leaked or lost cryptographic keys and password.

  • If you utilize hardware keys (e.g., YubiKey or SoloKeys Solo) as a security measure, consider adopting redundancy strategy. Keep two keys: one for daily use and another stored in a secure location. This precaution ensures access even if the primary key is compromised or lost.

  • When security breaches or leaks are reported, react promptly by replacing or disabling affected keys and passwords. This proactive response minimizes the potential risks and damage.

  • Periodically review and update your recovery plan. This ensures that the plan remains relevant and effective as your security landscape evolves.

WARNING

Remember that a recovery plan is not just another document. Rather, it's a lifeline that helps navigate unexpected challenges. By anticipating potential scenarios and establishing a clear roadmap for action, you fortify your operational security and enhance your readiness to respond effectively to any security incident.

',17),s=[o];function n(l,c,d,p,h,u){return r(),a("div",null,s)}const g=e(i,[["render",n]]);export{f as __pageData,g as default}; diff --git a/assets/guide_security_operational-security.md.DtcsL8SB.lean.js b/assets/guide_security_operational-security.md.DtcsL8SB.lean.js new file mode 100644 index 00000000..725cd10e --- /dev/null +++ b/assets/guide_security_operational-security.md.DtcsL8SB.lean.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as r,V as t}from"./chunks/framework.B6c1f-8R.js";const f=JSON.parse('{"title":"Operational Security","description":"","frontmatter":{},"headers":[],"relativePath":"guide/security/operational-security.md","filePath":"guide/security/operational-security.md","lastUpdated":1727242778000}'),i={name:"guide/security/operational-security.md"},o=t("",17),s=[o];function n(l,c,d,p,h,u){return r(),a("div",null,s)}const g=e(i,[["render",n]]);export{f as __pageData,g as default}; diff --git a/assets/guide_security_password-security.md.BYbpZhLC.js b/assets/guide_security_password-security.md.BYbpZhLC.js new file mode 100644 index 00000000..8369e67a --- /dev/null +++ b/assets/guide_security_password-security.md.BYbpZhLC.js @@ -0,0 +1,3 @@ +import{_ as e,c as n,o as l,V as t,m as s,a}from"./chunks/framework.B6c1f-8R.js";const P=JSON.parse('{"title":"Password Security","description":"","frontmatter":{},"headers":[],"relativePath":"guide/security/password-security.md","filePath":"guide/security/password-security.md","lastUpdated":1727242778000}'),r={name:"guide/security/password-security.md"},i=t('

Password Security

In the realm of blockchain security, protecting passwords is paramount. To ensure your data and everything it represents remain impervious to unauthorized access, let's delve into the nuances of password security.

Password Strength

Likely enough, you may have previously encountered recommendations on how to come up with a strong password. These may entail such advice as minimum password length, addition of special characters, etc. Such recommendations aim to increase the strength of your password that hinges on entropy, i.e. randomness of the password.

So, what defines a strong password? A strong password is a password with high entropy.

To calculate the entropy of a password, we may follow the Entropy formula:

',6),o=s("div",{class:"tip custom-block"},[s("p",{class:"custom-block-title"},"Entropy formula"),s("p",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"L")]),s("annotation",{encoding:"application/x-tex"},"L")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"L")])])]),a(" — Password length; number of symbols in the password."),s("br"),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"S")]),s("annotation",{encoding:"application/x-tex"},"S")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"S")])])]),a(" — Character set; size of the pool of unique possible symbols."),s("br"),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mi",null,"S"),s("mi",null,"L")])]),s("annotation",{encoding:"application/x-tex"},"S^L")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8413em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"S"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8413em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"L")])])])])])])])])])]),a(" — Number of possible combinations.")]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mi",null,"n"),s("mi",null,"t"),s("mi",null,"r"),s("mi",null,"o"),s("mi",null,"p"),s("mi",null,"y"),s("mo",null,"="),s("mi",null,"l"),s("mi",null,"o"),s("msub",null,[s("mi",null,"g"),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("msup",null,[s("mi",null,"S"),s("mi",null,"L")]),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"}," Entropy=log_2(S^L) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mord mathnormal"},"ro"),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1413em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mord mathnormal"},"o"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"S"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8913em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"L")])])])])])])]),s("span",{class:"mclose"},")")])])])])]),s("p",null,"The resulting number is the amount of entropy bits in a password. The higher the number, the harder the password is to crack."),s("p",null,"Knowing the entropy value, the amount of attempts required to brute-force a password with said entropy can be derived by using the following formula:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mi",null,"S"),s("mi",null,"L")]),s("mo",null,"="),s("msup",null,[s("mn",null,"2"),s("mi",null,"E")]),s("mi",null,"n"),s("mi",null,"t"),s("mi",null,"r"),s("mi",null,"o"),s("mi",null,"p"),s("mi",null,"y")]),s("annotation",{encoding:"application/x-tex"}," S^L=2^Entropy ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8913em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"S"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8913em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"L")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0858em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8913em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05764em"}},"E")])])])])])])]),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mord mathnormal"},"ro"),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y")])])])])]),s("p",null,[a("There is no universal answer as to how high the entropy of a password should be. For financial organizations, it is advised to keep the entropy of their passwords in the range from "),s("code",null,"64"),a(" to "),s("code",null,"127"),a(" bits ("),s("code",null,"128"),a(" bits or more is generally considered to be an overkill). However, keep in mind that "),s("abbr",{title:"Graphics Processing Unit"},"GPU"),a("s keep constantly evolving, and the time required for password cracking keeps decreasing over time.")])],-1),m=s("p",null,"Following the entropy formula, let us compare the following two examples:",-1),p=s("ol",null,[s("li",null,[a("A 16-character password with the character set utilizing only lowercase letters of the modern English alphabet (26 characters) yields approximately 43 sextillion ("),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"43"),s("mo",null,"∗"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mn",null,"2")]),s("mn",null,"1")]),s("annotation",{encoding:"application/x-tex"},"43*10^21")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"43"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"∗"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"1")])])]),a(") possible combinations.")])],-1),c=s("pre",null,[s("code",null,`$$Entropy=log_2(26^{16})=log_2(43,608,742,899,428,874,059,776)=75.20703...$$ +`)],-1),h=s("ol",{start:"2"},[s("li",null,[a("A 16-character password with the character set expanded to 96, including uppercase letters and special symbols, inflates the number of possible combinations to a staggering 52 nonillion ("),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"52"),s("mo",null,"∗"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mn",null,"3")]),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"52*10^30")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"52"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"∗"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])])])])])]),s("span",{class:"mord"},"0")])])]),a("), improving entropy significantly.")])],-1),u=s("pre",null,[s("code",null,`$$Entropy=log_2(96^{16})=log_2(52,040,292,466,647,269,602,037,015,248,896)=105.35940... $$ +`)],-1),d=s("p",null,[a("As can be seen, even by only expanding the character set from 26 to 96 symbols, the number of possible combinations that a malicious party would need to bruteforce has expanded by "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1.1933"),s("mo",null,"∗"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mn",null,"9")])]),s("annotation",{encoding:"application/x-tex"},"1.1933*10^9")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"1.1933"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"∗"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"9")])])])])])])])])])]),a(" times.")],-1),g=t('

Additionally increasing the length of the password, will grow the number of possible combinations even further, therefore enhancing the entropy—strength—of the password.

However, instead of wrestling with complexities, we advise using a password manager program—like KeePassXC (for more details, see Adding a Password Manager Program and Configuring KeePassXC)—to generate and securely store your passwords.

TIP

Certain websites limit the maximum possible entropy of passwords, i.e., either limit the maximum password length or the set of accepted characters, or both.

Keep this in mind when using such websites and aim to periodically update your passwords.

Password Vulnerabilities

Passwords can fall victim to brute-force attacks, typically executed using powerful GPUs in conjunction with dictionaries or exhaustive iteration through all possibilities. To thwart such attempts, craft a unique password devoid of personal information like birthdays, addresses, phone numbers, or social security numbers. Avoid providing attackers with easily guessable clues.

So, how hard it is to crack a modern password? It really depends on who you ask.

With a setup like Kevin Mitnick's cluster setup housing 24 NVIDIA® GeForce RTX 4090's and 6 NVIDIA® GeForce RTX 2080's, all of them running Hashtopolis software, he used to crack passwords that supposed to take a year in mere half a month.

However, let's now compare it to a single RTX 4090, capable of processing through 300 H/s using NTLM and 200 H/s using bcrypt, as outlined in this tweet.

As an extension of our previous entropy calculations, let's now examine the following projected cracking times:

',9),y=s("ol",null,[s("li",null,[s("p",null,[a("There are "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"31"),s("mo",{separator:"true"},","),s("mn",null,"540"),s("mo",{separator:"true"},","),s("mn",null,"000")]),s("annotation",{encoding:"application/x-tex"},"31,540,000")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8389em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"31"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"540"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"000")])])]),a(" seconds in a regular non-leap year. Assuming the worst-case scenario with "),s("code",null,"NTLM"),a(", at the speed of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"300"),s("mo",null,"∗"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mn",null,"9")])]),s("annotation",{encoding:"application/x-tex"},"300*10^9")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"300"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"∗"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"9")])])])])])])])])])]),a(),s("abbr",{title:"Hashes per second"},"H/s"),a(", it would take a single RTX 4090 approximately "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"4"),s("mo",{separator:"true"},","),s("mn",null,"608.83")]),s("annotation",{encoding:"application/x-tex"},"4,608.83")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8389em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"4"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"608.83")])])]),a(" years to crack a 16-character password with a character set of 26 letters of the modern English alphabet.")])]),s("li",null,[s("p",null,[a("If instead of "),s("code",null,"NTLM"),a(" we use "),s("code",null,"bcrypt"),a(", therefore reducing the iteration speed to "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"200"),s("mo",null,"∗"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"200*10^3")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"200"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"∗"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])])])])])])])])]),a(),s("abbr",{title:"Hashes per second"},"H/s"),a(", while also expanding the character set to 96, including uppercase letters and special symbols, the time to crack soars to about "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"8"),s("mo",{separator:"true"},","),s("mn",null,"249"),s("mo",{separator:"true"},","),s("mn",null,"887"),s("mo",{separator:"true"},","),s("mn",null,"835"),s("mo",{separator:"true"},","),s("mn",null,"549"),s("mo",{separator:"true"},","),s("mn",null,"662"),s("mo",{separator:"true"},","),s("mn",null,"270.456")]),s("annotation",{encoding:"application/x-tex"},"8,249,887,835,549,662,270.456")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8389em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"8"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"249"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"887"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"835"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"549"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"662"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"270.456")])])]),a(" years, far surpassing the age of the universe.")])])],-1),w=s("p",null,[a("So, simply picking higher entropy raised the time it takes to crack a password to unfathomable numbers. Yes, the process may be sped up by using multiple GPUs, however this method pales in comparison with the "),s("a",{href:"https://xkcd.com/538/",target:"_blank",rel:"noreferrer"},"XKCD approach"),a(".")],-1),b=s("p",null,[a("It is important to note that an extensive character set isn't always necessary to reach high entropy. It can be obtained by using multi-word passwords, or lengthy sentences in particular. The classic "),s("a",{href:"https://xkcd.com/936/",target:"_blank",rel:"noreferrer"},"XKCD comic"),a(" illustrates this concept eloquently.")],-1),x=s("div",{class:"warning custom-block"},[s("p",{class:"custom-block-title"},"WARNING"),s("p",null,"Avoid writing your password down anywhere. Store your password recovery phrase securely. If the phrase is too long, you may write it down, ensuring that you can read it out and type it out later. Store the physical copy of the phrase in a secure location and/or container.")],-1),k=[i,o,m,p,c,h,u,d,g,y,w,b,x];function f(v,_,M,z,S,T){return l(),n("div",null,k)}const A=e(r,[["render",f]]);export{P as __pageData,A as default}; diff --git a/assets/guide_security_password-security.md.BYbpZhLC.lean.js b/assets/guide_security_password-security.md.BYbpZhLC.lean.js new file mode 100644 index 00000000..da598920 --- /dev/null +++ b/assets/guide_security_password-security.md.BYbpZhLC.lean.js @@ -0,0 +1,3 @@ +import{_ as e,c as n,o as l,V as t,m as s,a}from"./chunks/framework.B6c1f-8R.js";const P=JSON.parse('{"title":"Password Security","description":"","frontmatter":{},"headers":[],"relativePath":"guide/security/password-security.md","filePath":"guide/security/password-security.md","lastUpdated":1727242778000}'),r={name:"guide/security/password-security.md"},i=t("",6),o=s("div",{class:"tip custom-block"},[s("p",{class:"custom-block-title"},"Entropy formula"),s("p",null,[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"L")]),s("annotation",{encoding:"application/x-tex"},"L")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal"},"L")])])]),a(" — Password length; number of symbols in the password."),s("br"),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mi",null,"S")]),s("annotation",{encoding:"application/x-tex"},"S")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6833em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"S")])])]),a(" — Character set; size of the pool of unique possible symbols."),s("br"),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mi",null,"S"),s("mi",null,"L")])]),s("annotation",{encoding:"application/x-tex"},"S^L")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8413em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"S"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8413em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"L")])])])])])])])])])]),a(" — Number of possible combinations.")]),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("mi",null,"E"),s("mi",null,"n"),s("mi",null,"t"),s("mi",null,"r"),s("mi",null,"o"),s("mi",null,"p"),s("mi",null,"y"),s("mo",null,"="),s("mi",null,"l"),s("mi",null,"o"),s("msub",null,[s("mi",null,"g"),s("mn",null,"2")]),s("mo",{stretchy:"false"},"("),s("msup",null,[s("mi",null,"S"),s("mi",null,"L")]),s("mo",{stretchy:"false"},")")]),s("annotation",{encoding:"application/x-tex"}," Entropy=log_2(S^L) ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8778em","vertical-align":"-0.1944em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"E"),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mord mathnormal"},"ro"),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y"),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.1413em","vertical-align":"-0.25em"}}),s("span",{class:"mord mathnormal",style:{"margin-right":"0.01968em"}},"l"),s("span",{class:"mord mathnormal"},"o"),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"g"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t vlist-t2"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.3011em"}},[s("span",{style:{top:"-2.55em","margin-left":"-0.0359em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])]),s("span",{class:"vlist-s"},"​")]),s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.15em"}},[s("span")])])])])]),s("span",{class:"mopen"},"("),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"S"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8913em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"L")])])])])])])]),s("span",{class:"mclose"},")")])])])])]),s("p",null,"The resulting number is the amount of entropy bits in a password. The higher the number, the harder the password is to crack."),s("p",null,"Knowing the entropy value, the amount of attempts required to brute-force a password with said entropy can be derived by using the following formula:"),s("p",{class:"katex-block"},[s("span",{class:"katex-display"},[s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("semantics",null,[s("mrow",null,[s("msup",null,[s("mi",null,"S"),s("mi",null,"L")]),s("mo",null,"="),s("msup",null,[s("mn",null,"2"),s("mi",null,"E")]),s("mi",null,"n"),s("mi",null,"t"),s("mi",null,"r"),s("mi",null,"o"),s("mi",null,"p"),s("mi",null,"y")]),s("annotation",{encoding:"application/x-tex"}," S^L=2^Entropy ")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8913em"}}),s("span",{class:"mord"},[s("span",{class:"mord mathnormal",style:{"margin-right":"0.05764em"}},"S"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8913em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight"},"L")])])])])])])]),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}}),s("span",{class:"mrel"},"="),s("span",{class:"mspace",style:{"margin-right":"0.2778em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"1.0858em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},[s("span",{class:"mord"},"2"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8913em"}},[s("span",{style:{top:"-3.113em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mathnormal mtight",style:{"margin-right":"0.05764em"}},"E")])])])])])])]),s("span",{class:"mord mathnormal"},"n"),s("span",{class:"mord mathnormal"},"t"),s("span",{class:"mord mathnormal"},"ro"),s("span",{class:"mord mathnormal"},"p"),s("span",{class:"mord mathnormal",style:{"margin-right":"0.03588em"}},"y")])])])])]),s("p",null,[a("There is no universal answer as to how high the entropy of a password should be. For financial organizations, it is advised to keep the entropy of their passwords in the range from "),s("code",null,"64"),a(" to "),s("code",null,"127"),a(" bits ("),s("code",null,"128"),a(" bits or more is generally considered to be an overkill). However, keep in mind that "),s("abbr",{title:"Graphics Processing Unit"},"GPU"),a("s keep constantly evolving, and the time required for password cracking keeps decreasing over time.")])],-1),m=s("p",null,"Following the entropy formula, let us compare the following two examples:",-1),p=s("ol",null,[s("li",null,[a("A 16-character password with the character set utilizing only lowercase letters of the modern English alphabet (26 characters) yields approximately 43 sextillion ("),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"43"),s("mo",null,"∗"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mn",null,"2")]),s("mn",null,"1")]),s("annotation",{encoding:"application/x-tex"},"43*10^21")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"43"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"∗"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"2")])])])])])])]),s("span",{class:"mord"},"1")])])]),a(") possible combinations.")])],-1),c=s("pre",null,[s("code",null,`$$Entropy=log_2(26^{16})=log_2(43,608,742,899,428,874,059,776)=75.20703...$$ +`)],-1),h=s("ol",{start:"2"},[s("li",null,[a("A 16-character password with the character set expanded to 96, including uppercase letters and special symbols, inflates the number of possible combinations to a staggering 52 nonillion ("),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"52"),s("mo",null,"∗"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mn",null,"3")]),s("mn",null,"0")]),s("annotation",{encoding:"application/x-tex"},"52*10^30")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"52"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"∗"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])])])])])]),s("span",{class:"mord"},"0")])])]),a("), improving entropy significantly.")])],-1),u=s("pre",null,[s("code",null,`$$Entropy=log_2(96^{16})=log_2(52,040,292,466,647,269,602,037,015,248,896)=105.35940... $$ +`)],-1),d=s("p",null,[a("As can be seen, even by only expanding the character set from 26 to 96 symbols, the number of possible combinations that a malicious party would need to bruteforce has expanded by "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"1.1933"),s("mo",null,"∗"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mn",null,"9")])]),s("annotation",{encoding:"application/x-tex"},"1.1933*10^9")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"1.1933"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"∗"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"9")])])])])])])])])])]),a(" times.")],-1),g=t("",9),y=s("ol",null,[s("li",null,[s("p",null,[a("There are "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"31"),s("mo",{separator:"true"},","),s("mn",null,"540"),s("mo",{separator:"true"},","),s("mn",null,"000")]),s("annotation",{encoding:"application/x-tex"},"31,540,000")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8389em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"31"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"540"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"000")])])]),a(" seconds in a regular non-leap year. Assuming the worst-case scenario with "),s("code",null,"NTLM"),a(", at the speed of "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"300"),s("mo",null,"∗"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mn",null,"9")])]),s("annotation",{encoding:"application/x-tex"},"300*10^9")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"300"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"∗"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"9")])])])])])])])])])]),a(),s("abbr",{title:"Hashes per second"},"H/s"),a(", it would take a single RTX 4090 approximately "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"4"),s("mo",{separator:"true"},","),s("mn",null,"608.83")]),s("annotation",{encoding:"application/x-tex"},"4,608.83")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8389em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"4"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"608.83")])])]),a(" years to crack a 16-character password with a character set of 26 letters of the modern English alphabet.")])]),s("li",null,[s("p",null,[a("If instead of "),s("code",null,"NTLM"),a(" we use "),s("code",null,"bcrypt"),a(", therefore reducing the iteration speed to "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"200"),s("mo",null,"∗"),s("mn",null,"1"),s("msup",null,[s("mn",null,"0"),s("mn",null,"3")])]),s("annotation",{encoding:"application/x-tex"},"200*10^3")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.6444em"}}),s("span",{class:"mord"},"200"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}}),s("span",{class:"mbin"},"∗"),s("span",{class:"mspace",style:{"margin-right":"0.2222em"}})]),s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8141em"}}),s("span",{class:"mord"},"1"),s("span",{class:"mord"},[s("span",{class:"mord"},"0"),s("span",{class:"msupsub"},[s("span",{class:"vlist-t"},[s("span",{class:"vlist-r"},[s("span",{class:"vlist",style:{height:"0.8141em"}},[s("span",{style:{top:"-3.063em","margin-right":"0.05em"}},[s("span",{class:"pstrut",style:{height:"2.7em"}}),s("span",{class:"sizing reset-size6 size3 mtight"},[s("span",{class:"mord mtight"},"3")])])])])])])])])])]),a(),s("abbr",{title:"Hashes per second"},"H/s"),a(", while also expanding the character set to 96, including uppercase letters and special symbols, the time to crack soars to about "),s("span",{class:"katex"},[s("span",{class:"katex-mathml"},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[s("semantics",null,[s("mrow",null,[s("mn",null,"8"),s("mo",{separator:"true"},","),s("mn",null,"249"),s("mo",{separator:"true"},","),s("mn",null,"887"),s("mo",{separator:"true"},","),s("mn",null,"835"),s("mo",{separator:"true"},","),s("mn",null,"549"),s("mo",{separator:"true"},","),s("mn",null,"662"),s("mo",{separator:"true"},","),s("mn",null,"270.456")]),s("annotation",{encoding:"application/x-tex"},"8,249,887,835,549,662,270.456")])])]),s("span",{class:"katex-html","aria-hidden":"true"},[s("span",{class:"base"},[s("span",{class:"strut",style:{height:"0.8389em","vertical-align":"-0.1944em"}}),s("span",{class:"mord"},"8"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"249"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"887"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"835"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"549"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"662"),s("span",{class:"mpunct"},","),s("span",{class:"mspace",style:{"margin-right":"0.1667em"}}),s("span",{class:"mord"},"270.456")])])]),a(" years, far surpassing the age of the universe.")])])],-1),w=s("p",null,[a("So, simply picking higher entropy raised the time it takes to crack a password to unfathomable numbers. Yes, the process may be sped up by using multiple GPUs, however this method pales in comparison with the "),s("a",{href:"https://xkcd.com/538/",target:"_blank",rel:"noreferrer"},"XKCD approach"),a(".")],-1),b=s("p",null,[a("It is important to note that an extensive character set isn't always necessary to reach high entropy. It can be obtained by using multi-word passwords, or lengthy sentences in particular. The classic "),s("a",{href:"https://xkcd.com/936/",target:"_blank",rel:"noreferrer"},"XKCD comic"),a(" illustrates this concept eloquently.")],-1),x=s("div",{class:"warning custom-block"},[s("p",{class:"custom-block-title"},"WARNING"),s("p",null,"Avoid writing your password down anywhere. Store your password recovery phrase securely. If the phrase is too long, you may write it down, ensuring that you can read it out and type it out later. Store the physical copy of the phrase in a secure location and/or container.")],-1),k=[i,o,m,p,c,h,u,d,g,y,w,b,x];function f(v,_,M,z,S,T){return l(),n("div",null,k)}const A=e(r,[["render",f]]);export{P as __pageData,A as default}; diff --git a/assets/guide_security_public-key-cryptography.md.CKYeyqvW.js b/assets/guide_security_public-key-cryptography.md.CKYeyqvW.js new file mode 100644 index 00000000..a0640d20 --- /dev/null +++ b/assets/guide_security_public-key-cryptography.md.CKYeyqvW.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as a,V as i}from"./chunks/framework.B6c1f-8R.js";const m=JSON.parse('{"title":"Public Key Cryptography","description":"","frontmatter":{},"headers":[],"relativePath":"guide/security/public-key-cryptography.md","filePath":"guide/security/public-key-cryptography.md","lastUpdated":1727242778000}'),r={name:"guide/security/public-key-cryptography.md"},n=i('

Public Key Cryptography

Public key cryptography provides the means for secure communication and data protection, enabling activities such as secure online transactions, encrypted email communications, etc.

Public key cryptography employs a pair of cryptographic keys—a public key and a private key—to create a highly secure method of transmitting information over online networks.

It's easy to make a public key from a private key, but the opposite is rather difficult, if not impossible. This keeps things safe. You can freely share your public key without risking your private key, which remains secure.

Encryption and Signatures

Public key cryptography allows individuals to send encrypted messages and data that can only be deciphered by the intended recipient possessing their corresponding private key. In other words, the public key functions as a lock, and the private key serves as an actual unique key that unlocks the encrypted data.

This encryption process not only ensures the privacy and confidentiality of sensitive information but also establishes the authenticity of the sender. By combining the sender's private key with the public key, a digital signature is created. This signature serves as a digital stamp of approval, verifying the sender's identity and the validity of the transferred data. Anyone with your public key can verify that the person who initiated the transaction used your private key.

Keys on the Client Side

Since every transaction must be signed on behalf of a peer, every operation requires a private key that is kept secret (hence the name). Therefore, the client program must handle both the storage and secure signing of transactions.

WARNING

All clients are different, but iroha binary is the least secure in this regard, as it stores a peer's private key in the multihash format saved to a plain text file that could be overridden with an environment variable.

This is currently a reference implementation that will not be a part of the production release.

One needs to register a user on behalf of another already registered user (just like you need to already have a pair of scissors to cut off the tag from a new one). Suppose that we want to register a user on behalf of mad_hatter@wonderland.

This entails generating a new private key, and sending its public key to the network so that said network can verify that it's indeed the trustworthy mad_hatter@wonderland, and not some impostor (e.g. mad_hatter@wünderbar). In this case, the client application must prompt you, the user, to provide a key pair and verify the authenticity of the transactions: belonging to mad_hatter@wonderland and having a signature derived from the appropriate public key.

For public key cryptography to work effectively, avoid re-using keys when you need to specify a new key. While there's nothing stopping you from doing that, the public keys are public, which means that if an attacker sees the same public key being used, they will know that the private keys are also identical.

Even though private keys operate on slightly different principles than passwords, the advice—to make them as random as possible, never store them unencrypted and never share them with anyone under any circumstances—applies.

',14),o=[n];function s(c,p,h,d,y,l){return a(),t("div",null,o)}const g=e(r,[["render",s]]);export{m as __pageData,g as default}; diff --git a/assets/guide_security_public-key-cryptography.md.CKYeyqvW.lean.js b/assets/guide_security_public-key-cryptography.md.CKYeyqvW.lean.js new file mode 100644 index 00000000..c5d22dbc --- /dev/null +++ b/assets/guide_security_public-key-cryptography.md.CKYeyqvW.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as a,V as i}from"./chunks/framework.B6c1f-8R.js";const m=JSON.parse('{"title":"Public Key Cryptography","description":"","frontmatter":{},"headers":[],"relativePath":"guide/security/public-key-cryptography.md","filePath":"guide/security/public-key-cryptography.md","lastUpdated":1727242778000}'),r={name:"guide/security/public-key-cryptography.md"},n=i("",14),o=[n];function s(c,p,h,d,y,l){return a(),t("div",null,o)}const g=e(r,[["render",s]]);export{m as __pageData,g as default}; diff --git a/assets/guide_security_security-principles.md.DIghKKgf.js b/assets/guide_security_security-principles.md.DIghKKgf.js new file mode 100644 index 00000000..23d9962a --- /dev/null +++ b/assets/guide_security_security-principles.md.DIghKKgf.js @@ -0,0 +1 @@ +import{_ as e,c as i,o as t,V as a}from"./chunks/framework.B6c1f-8R.js";const y=JSON.parse('{"title":"Security Principles","description":"","frontmatter":{},"headers":[],"relativePath":"guide/security/security-principles.md","filePath":"guide/security/security-principles.md","lastUpdated":1727242778000}'),s={name:"guide/security/security-principles.md"},r=a('

Security Principles

Organisations and individual users need to work together to ensure secure interactions with Iroha installations. This topic explains the basic principles behind this cooperation.

General Security Principles

  1. Use a Virtual Private Network (VPN):

    • Whenever accessing sensitive data or resources, especially over public networks, use a VPN to establish a secure connection that safeguards your information.
  2. Use a firewall for network protection:

    • Strengthen home and/or office networks by setting up a firewall that helps to counter unauthorized access and protect the connected devices from viruses and malware.
  3. Secure physical and digital information:

    • Safeguard physical documents containing sensitive information in a secure location, and ensure digital documents are encrypted and stored in password-protected folders.
  4. Keep Regular Data Backups:

    • Always have copies of your important information saved somewhere safe. This way, if you lose your data or something goes wrong, you can quickly get everything back on track. Keep these backups in a different secure place from where you usually keep your data.

Security Principles for Individual Users

  1. Adopt robust authentication rules:

    • Utilise strong and unique passwords for all accounts.

    • Never reuse passwords.

    • Set up 2FA whenever possible. 2FA improves the overall security by not only requiring a password, but also an additional factor such as an OTP, fingerprint, or a third-party app-based authentication (e.g., Google Authenticator).

    • Avoid using SMS authentication as the second factor. There is no guarantee that malicious software is not monitoring all of your SMS messages. For example, Android applications cannot be limited to only accessing the messages intended specifically for them.

  2. Exercise caution in digital communication:

    • Set up an email client to sign and verify signatures of all the received emails. While it is possible to impersonate the sender's address and even pose as a bank, it is not possible to fake a signature.

    • Disable both HTML messages and loading of external resources from unknown or unverified addresses.

    • Learn about common phishing techniques to recognise and avoid suspicious emails, links, and requests for personal information.

    • Set up an email client to sign and verify signatures of all the received emails. While it is possible to impersonate the sender's address and even pose as a bank, it is not possible to fake a signature.

  3. Safeguard personal information:

    • When communicating with unfamiliar individuals, especially on the phone or online, be careful about sharing private information.

    • Consider independently researching the individuals or organizations you are communicating with to confirm the legitimacy of their identity.

    • Be mindful of the personal information you share on social media platforms, as malicious parties can exploit this information.

Security Principles for Organisations

  1. Establish clear security policies and procedures:

    • Develop well-defined security policies and protocols for all employees dealing with sensitive data. Thoroughly train employees to adhere to these guidelines, mitigating the risk of negligent actions.

    • Ensure that security policies are accessible to all employees and are regularly reviewed and updated to reflect changing security landscapes.

    • Provide the security policies with examples and scenarios to make them more relatable and actionable for employees.

  2. Cultivate employee awareness:

    • Educate employees about data and operational security measures. Heightened awareness and comprehensive training are pivotal in fortifying organizational security.

    • Encourage employees to report any suspicious activities or security concerns promptly.

  3. Protect physical infrastructure:

    • Restrict physical entry to servers and infrastructure. Set up access controls that only allow authorised personnel to enter restricted areas.

    • Ensure that access control measures are regularly reviewed and updated to align with evolving security needs.

    • Consider implementing biometric access controls for sensitive areas to enhance physical security.

  4. Deploy security monitoring:

    • Enforce a comprehensive security monitoring system that scrutinizes activities and identifies potential security breaches.

    • Implement automated alerts to promptly notify security personnel of any unusual or unauthorized activities.

    • Consider using machine learning algorithms to enhance the system's ability to detect anomalies and potential threats.

    • Employ staff or designate personnel to oversee database security, identify, track and address software vulnerabilities, and conduct regular checks on critical machines for the presence of unauthorized software not included in the approved list.

  5. Conduct recurring security audits:

    • Perform routine security audits to evaluate vulnerabilities and confirm that established security measures align with the commonly-accepted standards and regulations.

    • Consider hiring external security experts for periodic assessments to gain an impartial evaluation of your organization's security condition.

  6. Implement an access control system:

    • Set up a role-based access control system to ensure that employees only have access to the resources and information necessary for their roles.
  7. Embrace Continuous Improvement:

    • Recognize that security is a continuous process. Maintain ongoing assessment of security measures and proactively enhance them to address emerging threats and challenges.

    • Consider establishing a feedback loop that encourages employees to contribute security improvement suggestions, fostering the culture of continuous enhancement.

',8),n=[r];function o(l,c,p,u,d,h){return t(),i("div",null,n)}const f=e(s,[["render",o]]);export{y as __pageData,f as default}; diff --git a/assets/guide_security_security-principles.md.DIghKKgf.lean.js b/assets/guide_security_security-principles.md.DIghKKgf.lean.js new file mode 100644 index 00000000..0b1bfbfc --- /dev/null +++ b/assets/guide_security_security-principles.md.DIghKKgf.lean.js @@ -0,0 +1 @@ +import{_ as e,c as i,o as t,V as a}from"./chunks/framework.B6c1f-8R.js";const y=JSON.parse('{"title":"Security Principles","description":"","frontmatter":{},"headers":[],"relativePath":"guide/security/security-principles.md","filePath":"guide/security/security-principles.md","lastUpdated":1727242778000}'),s={name:"guide/security/security-principles.md"},r=a("",8),n=[r];function o(l,c,p,u,d,h){return t(),i("div",null,n)}const f=e(s,[["render",o]]);export{y as __pageData,f as default}; diff --git a/assets/guide_security_storing-cryptographic-keys.md.CSvApCcZ.js b/assets/guide_security_storing-cryptographic-keys.md.CSvApCcZ.js new file mode 100644 index 00000000..0d648af6 --- /dev/null +++ b/assets/guide_security_storing-cryptographic-keys.md.CSvApCcZ.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as s,V as a}from"./chunks/framework.B6c1f-8R.js";const r="/iroha-2-docs/assets/KeePassXC.BngrXRS-.png",o="/iroha-2-docs/assets/keepassxc_ssh_agent.AbN915DX.png",i="/iroha-2-docs/assets/keepassxc_private_key.BBWlfudY.png",n="/iroha-2-docs/assets/keepassxc_pk_agent.Ds-M6u5k.png",b=JSON.parse('{"title":"Storing Cryptographic Keys","description":"","frontmatter":{},"headers":[],"relativePath":"guide/security/storing-cryptographic-keys.md","filePath":"guide/security/storing-cryptographic-keys.md","lastUpdated":1727242778000}'),c={name:"guide/security/storing-cryptographic-keys.md"},h=a('

Storing Cryptographic Keys

Your sensitive data only remains private if you adopt OPSEC practices to protect the cryptographic keys. Social engineering threats, where someone posing as a figure with authority tries to manipulate you into giving them your private cryptographic key, are real. Always be cautious and avoid sharing your private key, treating it as you would your apartment keys—reserved for trusted individuals only.

For more information on OPSEC and its best practices, see Operational Security.

Storing Cryptographic Keys Digitally

When it comes to protecting cryptographic keys digitally, mainly only two approaches—SSH and GPG—are available. These methods provide layers of security to prevent unauthorized access to your cryptographic keys.

Many of Iroha 2's architectural decisions have been influenced by the principles of the Secure Shell (SSH) protocol, which is why this section primarily focuses on the SSH approach, offering instructions on how to effectively implement the protocol for storing your cryptographic keys within the Iroha 2 ecosystem.

Using SSH and SSH Agent

Secure Shell Protocol (SSH) is a cryptographic network protocol that serves as a virtual gateway, enabling secure access to remote machines via potentially not-so-secure networks by using SSH keys—access credentials. It provides an efficient way to remotely interact with systems without the necessity of physical presence. In this context, SSH offers two primary authentication mechanisms: the conventional password-based approach and the more secure public-private key pair method.

For more information on SSH, see the related SSH Academy topic.

To streamline the login process and bypass the need for repetitive input, it is possible to pair the SSH keys with the SSH Agent (ssh-agent)—the assistant program that remembers your SSH keys and/or password for the duration of a session. This setup permits the SSH gateway to effortlessly access the keys whenever it connects to other machines.

The workflow here is as follows: you have your public key stored on a remote system and keep your private key secure. Whenever you want to access a remote system, the ssh-agent steps in to communicate your public key to the accessed system. The remote system then sends back a challenge that only your private key can properly respond to. Your ssh-agent handles this challenge by using your private key and sends the correct response back to the remote system. If the response matches what the system expected, you're granted access.

The beauty of the ssh-agent is that it holds onto your private key during your session, so there is no need to keep entering your password or private key passphrase every time you connect to a remote system.

For more information on the ssh-agent, see the related SSH Academy topic.

Note

For a detailed overview of the SSH protocol and the ssh-agent tool, see the following SSH Academy topics:

Adding a Password Manager Program

It is recommended to enhance the security of your SSH keys by protecting them with a password, which acts as an additional obstacle in the way of malicious parties aiming to obtain your sensitive information.

A variety of password managers can be used to store user passwords and SSH keys temporarily. For the sake of clarity, KeePass is used as an example password manager, specifically, the KeePassXC port running on Linux-based operating systems.

For instructions on how to set up KeePassXC see the Configuring KeePassXC section below.

KeePassXC:  screen UI

KeePassXC offers enhanced security, flexibility, and control. It not only stores passwords but also the SSH keys. When used for key storage, this password manager provides the ssh-agent with the stored keys, which are then promptly removed from its memory once the KeePassXC window is closed.

TIP

Theoretically, any of the KeePass ports listed on the official website can be utilized for key storage purposes. We recommend any of the following: KeePassX or KeePassXC.

Configuring KeePassXC

To configure KeePassXC, perform the following steps:

  1. Launch KeePassXC, then go to Tools > Settings, or select the Gear button from the top UI panel.

  2. In the Application Settings tab that appears, select SSH Agent from the left menu, and then select the Enable SSH Agent integration checkbox.

    Show reference screenshot

    KeePassXC  tab: Enabling SSH Agent

  3. Create a new KeePassXC Database. For instructions, see KeePassXC User Guide > Creating Your First Database.

  4. For every key that you would like to store in the KeePassXC Database you created, perform the following steps:

    • Add a new entry in the database. For instructions, see KeePassXC User Guide > Creating Your First Database.

    • When adding a new entry, attach the file containing the key by doing the following: select Advanced from the left menu, then select Add in the Attachments section, choose the required file in the Select files window that appears.

    • When adding a new entry, select SSH Agent from the left menu, then select the key file you added from the Attachment menu in the Private key section; then select the following checkboxes:

      • Add key to agent when database is opened/unlocked

      • Remove key from agent when database is closed/locked

      • Require user confirmation when this key is used

    • If necessary, make other changes to the entry.

    • When ready, select OK to save the entry.

    Show reference screenshots

    KeePassXC  tab: Adding a private key attachment

    KeePassXC  tab: Adding a private key attachment

Expected Results
  • Cryptographic and shh keys are stored as entries in a KeePassXC Database that can be accessed while the KeePassXC window is open.

  • Stored cryptographic and ssh keys can be used whenever they are required for authorization.

  • Stored cryptographic and ssh keys are removed from the ssh-agent once the KeePassXC window is closed.

Note

Without enabling the Require user confirmation when this key is used option, the ssh-agent may not monitor the process that provided it with a key. In the event that the password manager process is terminated by malware or a system service through a SIGKILL signal, the key is likely to remain in the ssh-agent, as Unix system programs cannot intercept SIGKILL.

Storing Cryptographic Keys Physically

For those who seek the highest level of offline security, the option of storing cryptographic keys physically ensures that the keys remain completely disconnected from digital networks, thus minimizing the risk of unauthorized access. Acknowledging the physical option underscores our commitment to catering to diverse security needs.

Using a Hardware Key

Our team considers hardware keys to be one of the best safety measures. A hardware key—a compact device that connects via a USB port and has the size of a typical flash drive—only processes security-related events when it is connected to a machine. This allows you to easily disconnect the device in case of a security breach, or simply reconnect it to a different machine whenever it is required.

However, since there are many brands of hardware keys—each with their unique APIs—it is important to research the market to find the key that best suits your needs.

So far, our team has internally tested the YubiKey 5C hardware key which proved to have many positive features, including versatile API functionality.

However, there's a potential drawback to consider. Implementing the HMAC challenge-response authentication and storing a corresponding private key for this response could create a vulnerability. This setup might inadvertently enable attackers to make educated guesses about the information stored within the YubiKey 5C's memory, thereby compromising the overall security.

Luckily, this vulnerability can be mitigated by adopting an alternative approach to utilizing the YubiKey 5C. The idea is to use YubiKey 5C to securely access a KeePassXC database storing your cryptographic and SSH keys. This method can even be considered beneficial, since it surpasses the security of most passwords and makes it necessary for the malicious party to be in possession of your hardware key in case the KeePassXC database is leaked.

INFO

To read more about the method above, see the answer by one of the KeePassXC developers—Janek Bevendorff—to the following StackExchange question:

Is it reasonable to use KeePassXC with YubiKey?

Using a Mnemonic Phrase

Alternatively, you can memorize a private key as a series of words, known as a mnemonic phrase. This method, used in many wallets, requires remembering around 25 specific words. Most password managers, including the previously discussed KeePassXC, offer mnemonic passphrase generation.

',38),p=[h];function l(d,g,y,u,m,f){return s(),t("div",null,p)}const w=e(c,[["render",l]]);export{b as __pageData,w as default}; diff --git a/assets/guide_security_storing-cryptographic-keys.md.CSvApCcZ.lean.js b/assets/guide_security_storing-cryptographic-keys.md.CSvApCcZ.lean.js new file mode 100644 index 00000000..9329ac3b --- /dev/null +++ b/assets/guide_security_storing-cryptographic-keys.md.CSvApCcZ.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as s,V as a}from"./chunks/framework.B6c1f-8R.js";const r="/iroha-2-docs/assets/KeePassXC.BngrXRS-.png",o="/iroha-2-docs/assets/keepassxc_ssh_agent.AbN915DX.png",i="/iroha-2-docs/assets/keepassxc_private_key.BBWlfudY.png",n="/iroha-2-docs/assets/keepassxc_pk_agent.Ds-M6u5k.png",b=JSON.parse('{"title":"Storing Cryptographic Keys","description":"","frontmatter":{},"headers":[],"relativePath":"guide/security/storing-cryptographic-keys.md","filePath":"guide/security/storing-cryptographic-keys.md","lastUpdated":1727242778000}'),c={name:"guide/security/storing-cryptographic-keys.md"},h=a("",38),p=[h];function l(d,g,y,u,m,f){return s(),t("div",null,p)}const w=e(c,[["render",l]]);export{b as __pageData,w as default}; diff --git a/assets/guide_support.md.BVe2ZRzv.js b/assets/guide_support.md.BVe2ZRzv.js new file mode 100644 index 00000000..f3c57793 --- /dev/null +++ b/assets/guide_support.md.BVe2ZRzv.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as r,V as o}from"./chunks/framework.B6c1f-8R.js";const _=JSON.parse('{"title":"Receive support","description":"","frontmatter":{},"headers":[],"relativePath":"guide/support.md","filePath":"guide/support.md","lastUpdated":1727242778000}'),a={name:"guide/support.md"},s=o('

Receive support

From time to time, you may have questions about Iroha that you would like to discuss in detail with others. There are three ways to quickly get in touch with our community: Telegram, Discord, and GitHub.

A large part of the community currently uses Telegram for communication. The Hyperledger part of the team prefers Discord, with two dedicated channels: iroha and iroha-2-contributors. The Discord and Telegram channels are synchronized, so users of both media see your messages.

Finally, you can create a GitHub issue, whether it's a request to update documentation, a suggestion for the core team, or a bug you have found.

',4),i=[s];function c(n,u,d,h,p,l){return r(),t("div",null,i)}const g=e(a,[["render",c]]);export{_ as __pageData,g as default}; diff --git a/assets/guide_support.md.BVe2ZRzv.lean.js b/assets/guide_support.md.BVe2ZRzv.lean.js new file mode 100644 index 00000000..9a54e835 --- /dev/null +++ b/assets/guide_support.md.BVe2ZRzv.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as r,V as o}from"./chunks/framework.B6c1f-8R.js";const _=JSON.parse('{"title":"Receive support","description":"","frontmatter":{},"headers":[],"relativePath":"guide/support.md","filePath":"guide/support.md","lastUpdated":1727242778000}'),a={name:"guide/support.md"},s=o("",4),i=[s];function c(n,u,d,h,p,l){return r(),t("div",null,i)}const g=e(a,[["render",c]]);export{_ as __pageData,g as default}; diff --git a/assets/guide_troubleshooting_configuration-issues.md.FQp4rSwT.js b/assets/guide_troubleshooting_configuration-issues.md.FQp4rSwT.js new file mode 100644 index 00000000..96c0e843 --- /dev/null +++ b/assets/guide_troubleshooting_configuration-issues.md.FQp4rSwT.js @@ -0,0 +1 @@ +import{_ as e,c as o,o as t,V as i}from"./chunks/framework.B6c1f-8R.js";const m=JSON.parse('{"title":"Troubleshooting Configuration Issues","description":"","frontmatter":{},"headers":[],"relativePath":"guide/troubleshooting/configuration-issues.md","filePath":"guide/troubleshooting/configuration-issues.md","lastUpdated":1727242778000}'),s={name:"guide/troubleshooting/configuration-issues.md"},a=i('

Troubleshooting Configuration Issues

This section offers troubleshooting tips for issues with Iroha 2 configuration. Make sure you checked the keys first, as it is the most common source of issues in Iroha.

If the issue you are experiencing is not described here, contact us via Telegram.

Outdated genesis on a Docker-compose setup

When you are using the Docker-compose version of Iroha, you might encounter the issue of one of the peer containers failing with the Failed to deserialize raw genesis block error. This happens if there is a mismatch between Iroha versions, meaning an Iroha peer cannot be initialized with the given genesis file.

If one of the peers is failing and it's been a while since you pulled the Iroha code for the first time, it's safe to assume the outdated genesis file is the cause. Here is how you can make sure Iroha is working incorrectly for exactly this reason:

  1. Use docker ps to check the current containers. Depending on the version, you will see either hyperledger/iroha2:dev or hyperledger/iroha2:lts containers. Check the number of Iroha peer containers in the docker ps output. By default, there are 4 peers configured in docker-compose.yml for Iroha, although you may have changed that value. You will see that the first container that should have been running Iroha just exited with an error, while three other containers remain active.

  2. Check the logs and look for the Failed to deserialize raw genesis block error. If you started your Iroha in daemon mode with docker compose up -d, use docker compose logs command.

The way to troubleshoot such an issue depends on the use of Iroha.

If this is a basic demo and you don't need the peer data to be restored, you can simply reset the genesis file to its latest state. To do this, use the git checkout configs/peer/genesis.json command.

If you need to restore the Iroha instance data, do the following:

  1. Connect the second Iroha peer that will copy the data from the first (failed) peer.
  2. Wait for the new peer to synchronize the data with the first peer.
  3. Leave the new peer active.
  4. Update the genesis file of the first peer.

INFO

The features needed to monitor the copying progress between peers and a migration tool to update the genesis file are to be implemented in future releases.

Multihash Format of Private and Public Keys

If you look at the client configuration, you will notice that the keys there are given in multi-hash format.

If you've never worked with multi-hash before, it is natural to assume that the right-hand-side is not a hexadecimal representation of the key bytes (two symbols per byte), but rather the bytes encoded as ASCII (or UTF-8), and call from_hex on the string literal in both the public_key and private_key instantiation.

It is also natural to assume that calling PrivateKey::try_from_str on the string literal would yield only the correct key. So if you get the number of bits in the key wrong, e.g. 32 bytes vs 64, that it would raise an error message.

Both of these assumptions are wrong. Unfortunately, the error messages don't help in de-bugging this particular kind of failure.

How to fix: use hex_literal. This will also turn an ugly string of characters into a nice small table of obviously hexadecimal numbers.

WARNING

Even the try_from_str implementation cannot verify if a given string is a valid PrivateKey and warn you if it isn't.

It will catch some obvious errors, e.g. if the string contains an invalid symbol. However, since we aim to support many key formats, it can't do much else. It cannot tell if the key is the correct private key for the given account either, unless you submit an instruction.

These sorts of subtle mistakes can be avoided, for example, by deserialising directly from string literals, or by generating a fresh key-pair in places where it makes sense.

',20),r=[a];function n(h,c,l,d,u,p){return t(),o("div",null,r)}const g=e(s,[["render",n]]);export{m as __pageData,g as default}; diff --git a/assets/guide_troubleshooting_configuration-issues.md.FQp4rSwT.lean.js b/assets/guide_troubleshooting_configuration-issues.md.FQp4rSwT.lean.js new file mode 100644 index 00000000..19c22f73 --- /dev/null +++ b/assets/guide_troubleshooting_configuration-issues.md.FQp4rSwT.lean.js @@ -0,0 +1 @@ +import{_ as e,c as o,o as t,V as i}from"./chunks/framework.B6c1f-8R.js";const m=JSON.parse('{"title":"Troubleshooting Configuration Issues","description":"","frontmatter":{},"headers":[],"relativePath":"guide/troubleshooting/configuration-issues.md","filePath":"guide/troubleshooting/configuration-issues.md","lastUpdated":1727242778000}'),s={name:"guide/troubleshooting/configuration-issues.md"},a=i("",20),r=[a];function n(h,c,l,d,u,p){return t(),o("div",null,r)}const g=e(s,[["render",n]]);export{m as __pageData,g as default}; diff --git a/assets/guide_troubleshooting_deployment-issues.md.2-b_HLFn.js b/assets/guide_troubleshooting_deployment-issues.md.2-b_HLFn.js new file mode 100644 index 00000000..4352f84f --- /dev/null +++ b/assets/guide_troubleshooting_deployment-issues.md.2-b_HLFn.js @@ -0,0 +1 @@ +import{_ as e,c as t,o,V as s}from"./chunks/framework.B6c1f-8R.js";const m=JSON.parse('{"title":"Troubleshooting Deployment Issues","description":"","frontmatter":{},"headers":[],"relativePath":"guide/troubleshooting/deployment-issues.md","filePath":"guide/troubleshooting/deployment-issues.md","lastUpdated":1727242778000}'),r={name:"guide/troubleshooting/deployment-issues.md"},a=s('

Troubleshooting Deployment Issues

This section offers troubleshooting tips for issues with Iroha 2 deployment. If the issue you are experiencing is not described here, contact us via Telegram.

Docker

TBD

Kubernetes

TBD

',6),n=[a];function i(l,u,d,h,c,p){return o(),t("div",null,n)}const b=e(r,[["render",i]]);export{m as __pageData,b as default}; diff --git a/assets/guide_troubleshooting_deployment-issues.md.2-b_HLFn.lean.js b/assets/guide_troubleshooting_deployment-issues.md.2-b_HLFn.lean.js new file mode 100644 index 00000000..c9ad671f --- /dev/null +++ b/assets/guide_troubleshooting_deployment-issues.md.2-b_HLFn.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o,V as s}from"./chunks/framework.B6c1f-8R.js";const m=JSON.parse('{"title":"Troubleshooting Deployment Issues","description":"","frontmatter":{},"headers":[],"relativePath":"guide/troubleshooting/deployment-issues.md","filePath":"guide/troubleshooting/deployment-issues.md","lastUpdated":1727242778000}'),r={name:"guide/troubleshooting/deployment-issues.md"},a=s("",6),n=[a];function i(l,u,d,h,c,p){return o(),t("div",null,n)}const b=e(r,[["render",i]]);export{m as __pageData,b as default}; diff --git a/assets/guide_troubleshooting_installation-issues.md.D56PejpD.js b/assets/guide_troubleshooting_installation-issues.md.D56PejpD.js new file mode 100644 index 00000000..9edf9fc7 --- /dev/null +++ b/assets/guide_troubleshooting_installation-issues.md.D56PejpD.js @@ -0,0 +1,9 @@ +import{_ as s,c as a,o as i,V as t}from"./chunks/framework.B6c1f-8R.js";const e="/iroha-2-docs/assets/install-troubles.BZrv1Q7d.png",b=JSON.parse('{"title":"Troubleshooting Installation Issues","description":"","frontmatter":{},"headers":[],"relativePath":"guide/troubleshooting/installation-issues.md","filePath":"guide/troubleshooting/installation-issues.md","lastUpdated":1727242778000}'),n={name:"guide/troubleshooting/installation-issues.md"},o=t('

Troubleshooting Installation Issues

This section offers troubleshooting tips for issues with Iroha 2 installation. If the issue you are experiencing is not described here, contact us via Telegram.

Troubleshooting Rust Toolchain

Sometimes, things don’t go as planned. Especially if you had rust on your system a while ago, but didn’t upgrade. A similar problem can occur in Python: XKCD has a famous example of what that might look like:

Untitled

Check Rust version

In the interest of preserving both your and our sanity, make sure that you have the right version of cargo paired with the right version of rustc (1.57 and 1.57) respectively. To show the versions, do

bash
$ cargo -V
+$ cargo 1.60.0 (d1fd9fe 2022-03-01)

and then

bash
$ rustc --version
+$ rustc 1.60.0 (7737e0b5c 2022-04-04)

If you have higher versions, you're fine. If you have lower versions, you can run the following command to update it:

bash
$ rustup toolchain update stable

Check installation location

If you get lower version numbers and you updated the toolchain and it didn’t work… let’s just say it’s a common problem, but it doesn’t have a common solution.

Firstly, you should establish where the version that you want to use is installed:

bash
$ rustup which rustc
+$ rustup which cargo

User installations of the toolchains are usually in ~/.rustup/toolchains/stable-*/bin/. If that is the case, you should be able to run

bash
$ rustup toolchain update stable

and that should fix your problems.

Check the default Rust version

Another option is that you have the up-to-date stable toolchain, but it is not set as the default. Run:

bash
$ rustup default stable

This can happen if you installed a nightly version, or set a specific Rust version, but forgot to un-set it.

Check if there are other Rust versions

Continuing down the troubleshooting rabbit-hole, we could have shell aliases:

bash
$ type rustc
+$ type cargo

If these point to locations other than the one you saw when running rustup which *, then you have a problem. Note that it’s not enough to just

bash
$ alias rustc "~/.rustup/toolchains/stable-*/bin/rustc"
+$ alias cargo "~/.rustup/toolchains/stable-*/bin/cargo"

because there is an internal logic that could break, regardless of how you re-arrange your shell aliases.

The simplest solution would be to remove the versions that you don’t use.

It’s easier said than done, however, since it entails tracking all the versions of rustup installed and available to you. Usually, there are only two: the system package manager version and the one that got installed into the standard location in your home folder when you ran the command in the beginning of this tutorial. For the former, consult your (Linux) distribution’s manual, (apt remove rust). For the latter, run:

bash
$ rustup toolchain list

And then, for every <toolchain> (without the angle brackets of course):

bash
$ rustup remove <toolchain>

After that, make sure that

bash
$ cargo --help

results in a command-not-found error, i.e. that you have no active Rust toolchain installed. Then, run:

bash
$ rustup toolchain install stable

Troubleshooting Python toolchain

When you install the Python Wheel package using pip on the "client setup" step, you may encounter an error like: "iroha_python-*.whl is not a supported wheel on this platform".

This error means that pip is outdated, so you need to update it. First of all, it is recommended to check your OS for updates and perform a system upgrade.

If this doesn't work, you can try updating pip for your user directory.

python -m pip install --upgrade pip

Make sure that pip that is installed in your home directory. To do this, run whereis pip and check if /home/username/.local/bin/pip is among the paths. If not, update your shell's PATH variable.

If the issue persists, please contact us and report the outputs.

python --version
+python3 --version
+pip --version
+pip3 --version
`,46),h=[o];function l(p,r,d,c,u,k){return i(),a("div",null,h)}const y=s(n,[["render",l]]);export{b as __pageData,y as default}; diff --git a/assets/guide_troubleshooting_installation-issues.md.D56PejpD.lean.js b/assets/guide_troubleshooting_installation-issues.md.D56PejpD.lean.js new file mode 100644 index 00000000..dace2e5f --- /dev/null +++ b/assets/guide_troubleshooting_installation-issues.md.D56PejpD.lean.js @@ -0,0 +1 @@ +import{_ as s,c as a,o as i,V as t}from"./chunks/framework.B6c1f-8R.js";const e="/iroha-2-docs/assets/install-troubles.BZrv1Q7d.png",b=JSON.parse('{"title":"Troubleshooting Installation Issues","description":"","frontmatter":{},"headers":[],"relativePath":"guide/troubleshooting/installation-issues.md","filePath":"guide/troubleshooting/installation-issues.md","lastUpdated":1727242778000}'),n={name:"guide/troubleshooting/installation-issues.md"},o=t("",46),h=[o];function l(p,r,d,c,u,k){return i(),a("div",null,h)}const y=s(n,[["render",l]]);export{b as __pageData,y as default}; diff --git a/assets/guide_troubleshooting_integration-issues.md.Drm7WPT6.js b/assets/guide_troubleshooting_integration-issues.md.Drm7WPT6.js new file mode 100644 index 00000000..9ef97433 --- /dev/null +++ b/assets/guide_troubleshooting_integration-issues.md.Drm7WPT6.js @@ -0,0 +1 @@ +import{_ as s,c as o,o as i,m as e,a as t}from"./chunks/framework.B6c1f-8R.js";const m=JSON.parse('{"title":"Troubleshooting Integration Issues","description":"","frontmatter":{},"headers":[],"relativePath":"guide/troubleshooting/integration-issues.md","filePath":"guide/troubleshooting/integration-issues.md","lastUpdated":1727242778000}'),n={name:"guide/troubleshooting/integration-issues.md"},r=e("h1",{id:"troubleshooting-integration-issues",tabindex:"-1"},[t("Troubleshooting Integration Issues "),e("a",{class:"header-anchor",href:"#troubleshooting-integration-issues","aria-label":'Permalink to "Troubleshooting Integration Issues"'},"​")],-1),a=e("p",null,[t("This section offers troubleshooting tips for issues with Iroha 2 integration. If the issue you are experiencing is not described here, contact us via "),e("a",{href:"https://t.me/hyperledgeriroha",target:"_blank",rel:"noreferrer"},"Telegram"),t(".")],-1),l=e("p",null,[e("strong",null,"TBD")],-1),u=[r,a,l];function h(c,g,d,_,p,f){return i(),o("div",null,u)}const I=s(n,[["render",h]]);export{m as __pageData,I as default}; diff --git a/assets/guide_troubleshooting_integration-issues.md.Drm7WPT6.lean.js b/assets/guide_troubleshooting_integration-issues.md.Drm7WPT6.lean.js new file mode 100644 index 00000000..9ef97433 --- /dev/null +++ b/assets/guide_troubleshooting_integration-issues.md.Drm7WPT6.lean.js @@ -0,0 +1 @@ +import{_ as s,c as o,o as i,m as e,a as t}from"./chunks/framework.B6c1f-8R.js";const m=JSON.parse('{"title":"Troubleshooting Integration Issues","description":"","frontmatter":{},"headers":[],"relativePath":"guide/troubleshooting/integration-issues.md","filePath":"guide/troubleshooting/integration-issues.md","lastUpdated":1727242778000}'),n={name:"guide/troubleshooting/integration-issues.md"},r=e("h1",{id:"troubleshooting-integration-issues",tabindex:"-1"},[t("Troubleshooting Integration Issues "),e("a",{class:"header-anchor",href:"#troubleshooting-integration-issues","aria-label":'Permalink to "Troubleshooting Integration Issues"'},"​")],-1),a=e("p",null,[t("This section offers troubleshooting tips for issues with Iroha 2 integration. If the issue you are experiencing is not described here, contact us via "),e("a",{href:"https://t.me/hyperledgeriroha",target:"_blank",rel:"noreferrer"},"Telegram"),t(".")],-1),l=e("p",null,[e("strong",null,"TBD")],-1),u=[r,a,l];function h(c,g,d,_,p,f){return i(),o("div",null,u)}const I=s(n,[["render",h]]);export{m as __pageData,I as default}; diff --git a/assets/guide_troubleshooting_overview.md.43cANCE4.js b/assets/guide_troubleshooting_overview.md.43cANCE4.js new file mode 100644 index 00000000..dc2f1157 --- /dev/null +++ b/assets/guide_troubleshooting_overview.md.43cANCE4.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as s,V as o}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Troubleshooting","description":"","frontmatter":{},"headers":[],"relativePath":"guide/troubleshooting/overview.md","filePath":"guide/troubleshooting/overview.md","lastUpdated":1727242778000}'),i={name:"guide/troubleshooting/overview.md"},r=o('

Troubleshooting

This section is intended to help if you encounter issues while working with Iroha. If something goes wrong, please check the keys first. If that doesn't help, check the troubleshooting instructions for each stage:

If the issue you are experiencing is not described here, contact us via Telegram.

Check the keys

Most issues arise as a result of unmatched keys. This is why we recommend to follow this rule: If something goes wrong, check the keys first.

Here's a quick explanation: It is not possible to differentiate the error messages that arise when peers' keys do not match the keys in the array of trusted peers, because it would expose the peers' public key. As such, if you have Helm charts or K8s deployed with keys defined via the environment variables, you should check for Key definitions.

If in doubt, generate a new pair of keys.

',8),a=[r];function n(h,l,c,u,d,p){return s(),t("div",null,a)}const k=e(i,[["render",n]]);export{g as __pageData,k as default}; diff --git a/assets/guide_troubleshooting_overview.md.43cANCE4.lean.js b/assets/guide_troubleshooting_overview.md.43cANCE4.lean.js new file mode 100644 index 00000000..b5218e7a --- /dev/null +++ b/assets/guide_troubleshooting_overview.md.43cANCE4.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as s,V as o}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Troubleshooting","description":"","frontmatter":{},"headers":[],"relativePath":"guide/troubleshooting/overview.md","filePath":"guide/troubleshooting/overview.md","lastUpdated":1727242778000}'),i={name:"guide/troubleshooting/overview.md"},r=o("",8),a=[r];function n(h,l,c,u,d,p){return s(),t("div",null,a)}const k=e(i,[["render",n]]);export{g as __pageData,k as default}; diff --git a/assets/index.md.CQwI35wr.js b/assets/index.md.CQwI35wr.js new file mode 100644 index 00000000..454570be --- /dev/null +++ b/assets/index.md.CQwI35wr.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as a}from"./chunks/framework.B6c1f-8R.js";const f=JSON.parse('{"title":"","description":"","frontmatter":{"layout":"home","hero":{"name":"Iroha 2 Documentation","tagline":"Fully-featured blockchain ledger"},"features":[{"icon":"🚀","title":"Get Started","details":"Install and build Iroha, follow a step-by-step tutorial to start working with Iroha","link":"/guide/get-started/"},{"icon":"📖","title":"Iroha Overview","details":"Learn about Iroha functionality in great detail and understand the underlying principles","link":"/guide/blockchain/how-iroha-works"},{"icon":"💻","title":"Reference","details":"Consult reference documentation for extensive information about available functionality","link":"/reference/torii-endpoints"}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1727242778000}'),n={name:"index.md"};function i(o,r,l,d,s,c){return a(),t("div")}const h=e(n,[["render",i]]);export{f as __pageData,h as default}; diff --git a/assets/index.md.CQwI35wr.lean.js b/assets/index.md.CQwI35wr.lean.js new file mode 100644 index 00000000..454570be --- /dev/null +++ b/assets/index.md.CQwI35wr.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as a}from"./chunks/framework.B6c1f-8R.js";const f=JSON.parse('{"title":"","description":"","frontmatter":{"layout":"home","hero":{"name":"Iroha 2 Documentation","tagline":"Fully-featured blockchain ledger"},"features":[{"icon":"🚀","title":"Get Started","details":"Install and build Iroha, follow a step-by-step tutorial to start working with Iroha","link":"/guide/get-started/"},{"icon":"📖","title":"Iroha Overview","details":"Learn about Iroha functionality in great detail and understand the underlying principles","link":"/guide/blockchain/how-iroha-works"},{"icon":"💻","title":"Reference","details":"Consult reference documentation for extensive information about available functionality","link":"/reference/torii-endpoints"}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1727242778000}'),n={name:"index.md"};function i(o,r,l,d,s,c){return a(),t("div")}const h=e(n,[["render",i]]);export{f as __pageData,h as default}; diff --git a/assets/install-troubles.BZrv1Q7d.png b/assets/install-troubles.BZrv1Q7d.png new file mode 100644 index 00000000..031335ad Binary files /dev/null and b/assets/install-troubles.BZrv1Q7d.png differ diff --git a/assets/inter-italic-cyrillic-ext.5XJwZIOp.woff2 b/assets/inter-italic-cyrillic-ext.5XJwZIOp.woff2 new file mode 100644 index 00000000..2a687296 Binary files /dev/null and b/assets/inter-italic-cyrillic-ext.5XJwZIOp.woff2 differ diff --git a/assets/inter-italic-cyrillic.D6csxwjC.woff2 b/assets/inter-italic-cyrillic.D6csxwjC.woff2 new file mode 100644 index 00000000..f6403515 Binary files /dev/null and b/assets/inter-italic-cyrillic.D6csxwjC.woff2 differ diff --git a/assets/inter-italic-greek-ext.CHOfFY1k.woff2 b/assets/inter-italic-greek-ext.CHOfFY1k.woff2 new file mode 100644 index 00000000..00218960 Binary files /dev/null and b/assets/inter-italic-greek-ext.CHOfFY1k.woff2 differ diff --git a/assets/inter-italic-greek.9J96vYpw.woff2 b/assets/inter-italic-greek.9J96vYpw.woff2 new file mode 100644 index 00000000..71c265f8 Binary files /dev/null and b/assets/inter-italic-greek.9J96vYpw.woff2 differ diff --git a/assets/inter-italic-latin-ext.BGcWXLrn.woff2 b/assets/inter-italic-latin-ext.BGcWXLrn.woff2 new file mode 100644 index 00000000..9c1b9440 Binary files /dev/null and b/assets/inter-italic-latin-ext.BGcWXLrn.woff2 differ diff --git a/assets/inter-italic-latin.DbsTr1gm.woff2 b/assets/inter-italic-latin.DbsTr1gm.woff2 new file mode 100644 index 00000000..01fcf207 Binary files /dev/null and b/assets/inter-italic-latin.DbsTr1gm.woff2 differ diff --git a/assets/inter-italic-vietnamese.DHNAd7Wr.woff2 b/assets/inter-italic-vietnamese.DHNAd7Wr.woff2 new file mode 100644 index 00000000..e4f788ee Binary files /dev/null and b/assets/inter-italic-vietnamese.DHNAd7Wr.woff2 differ diff --git a/assets/inter-roman-cyrillic-ext.DxP3Awbn.woff2 b/assets/inter-roman-cyrillic-ext.DxP3Awbn.woff2 new file mode 100644 index 00000000..28593ccb Binary files /dev/null and b/assets/inter-roman-cyrillic-ext.DxP3Awbn.woff2 differ diff --git a/assets/inter-roman-cyrillic.CMhn1ESj.woff2 b/assets/inter-roman-cyrillic.CMhn1ESj.woff2 new file mode 100644 index 00000000..a20adc16 Binary files /dev/null and b/assets/inter-roman-cyrillic.CMhn1ESj.woff2 differ diff --git a/assets/inter-roman-greek-ext.D0mI3NpI.woff2 b/assets/inter-roman-greek-ext.D0mI3NpI.woff2 new file mode 100644 index 00000000..e3b0be76 Binary files /dev/null and b/assets/inter-roman-greek-ext.D0mI3NpI.woff2 differ diff --git a/assets/inter-roman-greek.JvnBZ4YD.woff2 b/assets/inter-roman-greek.JvnBZ4YD.woff2 new file mode 100644 index 00000000..f790e047 Binary files /dev/null and b/assets/inter-roman-greek.JvnBZ4YD.woff2 differ diff --git a/assets/inter-roman-latin-ext.ZlYT4o7i.woff2 b/assets/inter-roman-latin-ext.ZlYT4o7i.woff2 new file mode 100644 index 00000000..715bd903 Binary files /dev/null and b/assets/inter-roman-latin-ext.ZlYT4o7i.woff2 differ diff --git a/assets/inter-roman-latin.Bu8hRsVA.woff2 b/assets/inter-roman-latin.Bu8hRsVA.woff2 new file mode 100644 index 00000000..a540b7af Binary files /dev/null and b/assets/inter-roman-latin.Bu8hRsVA.woff2 differ diff --git a/assets/inter-roman-vietnamese.ClpjcLMQ.woff2 b/assets/inter-roman-vietnamese.ClpjcLMQ.woff2 new file mode 100644 index 00000000..5a9f9cb9 Binary files /dev/null and b/assets/inter-roman-vietnamese.ClpjcLMQ.woff2 differ diff --git a/assets/iroha_java_commits.DtyotM0c.png b/assets/iroha_java_commits.DtyotM0c.png new file mode 100644 index 00000000..33fe2c86 Binary files /dev/null and b/assets/iroha_java_commits.DtyotM0c.png differ diff --git a/assets/iroha_java_hash.CWG7jGmi.png b/assets/iroha_java_hash.CWG7jGmi.png new file mode 100644 index 00000000..c82346c1 Binary files /dev/null and b/assets/iroha_java_hash.CWG7jGmi.png differ diff --git a/assets/keepassxc_pk_agent.Ds-M6u5k.png b/assets/keepassxc_pk_agent.Ds-M6u5k.png new file mode 100644 index 00000000..fdd07dad Binary files /dev/null and b/assets/keepassxc_pk_agent.Ds-M6u5k.png differ diff --git a/assets/keepassxc_private_key.BBWlfudY.png b/assets/keepassxc_private_key.BBWlfudY.png new file mode 100644 index 00000000..297f9440 Binary files /dev/null and b/assets/keepassxc_private_key.BBWlfudY.png differ diff --git a/assets/keepassxc_ssh_agent.AbN915DX.png b/assets/keepassxc_ssh_agent.AbN915DX.png new file mode 100644 index 00000000..9ae65627 Binary files /dev/null and b/assets/keepassxc_ssh_agent.AbN915DX.png differ diff --git a/assets/reference_compatibility-matrix.md.PV7SJ-rB.js b/assets/reference_compatibility-matrix.md.PV7SJ-rB.js new file mode 100644 index 00000000..39efded6 --- /dev/null +++ b/assets/reference_compatibility-matrix.md.PV7SJ-rB.js @@ -0,0 +1 @@ +import{_ as n,E as o,c as r,m as t,a as e,J as i,o as l}from"./chunks/framework.B6c1f-8R.js";const M=JSON.parse('{"title":"Compatibility Matrix","description":"","frontmatter":{},"headers":[],"relativePath":"reference/compatibility-matrix.md","filePath":"reference/compatibility-matrix.md","lastUpdated":1727242778000}'),c={name:"reference/compatibility-matrix.md"},m=t("h1",{id:"compatibility-matrix",tabindex:"-1"},[e("Compatibility Matrix "),t("a",{class:"header-anchor",href:"#compatibility-matrix","aria-label":'Permalink to "Compatibility Matrix"'},"​")],-1),d=t("p",null,[e("In our continuous efforts to provide clear documentation and to ensure seamless compatibility across multiple SDKs, we present the "),t("strong",null,"SDK Compatibility Matrix"),e(". This matrix provides an instantaneous overview of how different stories, sourced from TestOps API, fare across varying SDKs.")],-1),p=t("p",null,"The matrix consists of:",-1),u=t("li",null,[t("strong",null,"Stories"),e(": Represented in the first column of the matrix, these are directly fetched from the TestOps API.")],-1),h=t("li",null,[t("strong",null,"SDKs"),e(': Each subsequent column represents an SDK, such as "Java/Kotlin", "JavaScript", "Swift", etc.')],-1),f=t("strong",null,"Status Symbols",-1),_=t("div",{class:"info custom-block"},[t("p",{class:"custom-block-title"},"INFO"),t("p",null,[e("The data for this matrix is retrieved dynamically from our "),t("a",{href:"https://github.com/soramitsu/iroha2-docs-compat-matrix-service",target:"_blank",rel:"noreferrer"},"backend service"),e(", balancing the latest information with a swift response for documentation readers.")])],-1);function b(x,y,v,g,S,T){const a=o("CompatibilityMatrixTableIcon"),s=o("CompatibilityMatrixTable");return l(),r("div",null,[m,d,p,t("ul",null,[u,h,t("li",null,[f,e(": The status of each story for an SDK is denoted with: "),t("ul",null,[t("li",null,[i(a,{status:"ok",inline:""}),e(" indicating the story passed.")]),t("li",null,[i(a,{status:"failed",inline:""}),e(" indicating the story failed to pass.")]),t("li",null,[i(a,{status:"no-data",inline:""}),e(" indicating the data is missing.")])])])]),i(s),_])}const k=n(c,[["render",b]]);export{M as __pageData,k as default}; diff --git a/assets/reference_compatibility-matrix.md.PV7SJ-rB.lean.js b/assets/reference_compatibility-matrix.md.PV7SJ-rB.lean.js new file mode 100644 index 00000000..39efded6 --- /dev/null +++ b/assets/reference_compatibility-matrix.md.PV7SJ-rB.lean.js @@ -0,0 +1 @@ +import{_ as n,E as o,c as r,m as t,a as e,J as i,o as l}from"./chunks/framework.B6c1f-8R.js";const M=JSON.parse('{"title":"Compatibility Matrix","description":"","frontmatter":{},"headers":[],"relativePath":"reference/compatibility-matrix.md","filePath":"reference/compatibility-matrix.md","lastUpdated":1727242778000}'),c={name:"reference/compatibility-matrix.md"},m=t("h1",{id:"compatibility-matrix",tabindex:"-1"},[e("Compatibility Matrix "),t("a",{class:"header-anchor",href:"#compatibility-matrix","aria-label":'Permalink to "Compatibility Matrix"'},"​")],-1),d=t("p",null,[e("In our continuous efforts to provide clear documentation and to ensure seamless compatibility across multiple SDKs, we present the "),t("strong",null,"SDK Compatibility Matrix"),e(". This matrix provides an instantaneous overview of how different stories, sourced from TestOps API, fare across varying SDKs.")],-1),p=t("p",null,"The matrix consists of:",-1),u=t("li",null,[t("strong",null,"Stories"),e(": Represented in the first column of the matrix, these are directly fetched from the TestOps API.")],-1),h=t("li",null,[t("strong",null,"SDKs"),e(': Each subsequent column represents an SDK, such as "Java/Kotlin", "JavaScript", "Swift", etc.')],-1),f=t("strong",null,"Status Symbols",-1),_=t("div",{class:"info custom-block"},[t("p",{class:"custom-block-title"},"INFO"),t("p",null,[e("The data for this matrix is retrieved dynamically from our "),t("a",{href:"https://github.com/soramitsu/iroha2-docs-compat-matrix-service",target:"_blank",rel:"noreferrer"},"backend service"),e(", balancing the latest information with a swift response for documentation readers.")])],-1);function b(x,y,v,g,S,T){const a=o("CompatibilityMatrixTableIcon"),s=o("CompatibilityMatrixTable");return l(),r("div",null,[m,d,p,t("ul",null,[u,h,t("li",null,[f,e(": The status of each story for an SDK is denoted with: "),t("ul",null,[t("li",null,[i(a,{status:"ok",inline:""}),e(" indicating the story passed.")]),t("li",null,[i(a,{status:"failed",inline:""}),e(" indicating the story failed to pass.")]),t("li",null,[i(a,{status:"no-data",inline:""}),e(" indicating the data is missing.")])])])]),i(s),_])}const k=n(c,[["render",b]]);export{M as __pageData,k as default}; diff --git a/assets/reference_data-model-schema.md.Ncq8wG4o.js b/assets/reference_data-model-schema.md.Ncq8wG4o.js new file mode 100644 index 00000000..5116c228 --- /dev/null +++ b/assets/reference_data-model-schema.md.Ncq8wG4o.js @@ -0,0 +1 @@ +import{_ as t,c as e,o as a,V as d}from"./chunks/framework.B6c1f-8R.js";const x=JSON.parse('{"title":"Data Model Schema","description":"","frontmatter":{},"headers":[],"relativePath":"reference/data-model-schema.md","filePath":"reference/data-model-schema.md","lastUpdated":1727242778000}'),o={name:"reference/data-model-schema.md"},r=d('

Data Model Schema

TODO: explain what this page contains

Account

Type: Struct

Declarations:

Field nameField value
idAccountId
assetsSortedMap<AssetId, Asset>
signatoriesSortedVec<PublicKey>
signature_check_conditionSignatureCheckCondition
metadataMetadata

AccountEvent

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
AssetAssetEvent0
CreatedAccount1
DeletedAccountId2
AuthenticationAddedAccountId3
AuthenticationRemovedAccountId4
PermissionAddedAccountPermissionChanged5
PermissionRemovedAccountPermissionChanged6
RoleRevokedAccountRoleChanged7
RoleGrantedAccountRoleChanged8
MetadataInsertedMetadataChanged<AccountId>9
MetadataRemovedMetadataChanged<AccountId>10

AccountEventFilter

Type: Struct

Declarations:

Field nameField value
id_matcherOption<AccountId>
event_setAccountEventSet

AccountEventSet

Type: Bitmap

Repr: u32

Masks:

Field nameField value
AnyAsset0x1
Created0x2
Deleted0x4
AuthenticationAdded0x8
AuthenticationRemoved0x10
PermissionAdded0x20
PermissionRemoved0x40
RoleRevoked0x80
RoleGranted0x100
MetadataInserted0x200
MetadataRemoved0x400

AccountId

Type: Struct

Declarations:

Field nameField value
domain_idDomainId
nameName

AccountMintBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
PublicKeyMint<PublicKey, Account>0
SignatureCheckConditionMint<SignatureCheckCondition, Account>1

AccountPermissionChanged

Type: Struct

Declarations:

Field nameField value
account_idAccountId
permission_idName

AccountRoleChanged

Type: Struct

Declarations:

Field nameField value
account_idAccountId
role_idRoleId

Action

Type: Struct

Declarations:

Field nameField value
executableExecutable
repeatsRepeats
authorityAccountId
filterTriggeringEventFilterBox
metadataMetadata

Algorithm

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
Ed255190
Secp256k11
BlsNormal2
BlsSmall3

Array<u16, 8>

Type: Array

Length: 8

Value: u16

Array<u8, 32>

Type: Array

Length: 32

Value: u8

Array<u8, 4>

Type: Array

Length: 4

Value: u8

Asset

Type: Struct

Declarations:

Field nameField value
idAssetId
valueAssetValue

AssetChanged

Type: Struct

Declarations:

Field nameField value
asset_idAssetId
amountAssetValue

AssetDefinition

Type: Struct

Declarations:

Field nameField value
idAssetDefinitionId
value_typeAssetValueType
mintableMintable
logoOption<IpfsPath>
metadataMetadata
owned_byAccountId

AssetDefinitionEvent

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
CreatedAssetDefinition0
MintabilityChangedAssetDefinitionId1
OwnerChangedAssetDefinitionOwnerChanged2
DeletedAssetDefinitionId3
MetadataInsertedMetadataChanged<AssetDefinitionId>4
MetadataRemovedMetadataChanged<AssetDefinitionId>5
TotalQuantityChangedAssetDefinitionTotalQuantityChanged6

AssetDefinitionEventFilter

Type: Struct

Declarations:

Field nameField value
id_matcherOption<AssetDefinitionId>
event_setAssetDefinitionEventSet

AssetDefinitionEventSet

Type: Bitmap

Repr: u32

Masks:

Field nameField value
Created0x1
MintabilityChanged0x2
OwnerChanged0x4
Deleted0x8
MetadataInserted0x10
MetadataRemoved0x20
TotalQuantityChanged0x40

AssetDefinitionId

Type: Struct

Declarations:

Field nameField value
domain_idDomainId
nameName

AssetDefinitionOwnerChanged

Type: Struct

Declarations:

Field nameField value
asset_definition_idAssetDefinitionId
new_ownerAccountId

AssetDefinitionTotalQuantityChanged

Type: Struct

Declarations:

Field nameField value
asset_definition_idAssetDefinitionId
total_amountNumeric

AssetEvent

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
CreatedAsset0
DeletedAssetId1
AddedAssetChanged2
RemovedAssetChanged3
MetadataInsertedMetadataChanged<AssetId>4
MetadataRemovedMetadataChanged<AssetId>5

AssetEventFilter

Type: Struct

Declarations:

Field nameField value
id_matcherOption<AssetId>
event_setAssetEventSet

AssetEventSet

Type: Bitmap

Repr: u32

Masks:

Field nameField value
Created0x1
Deleted0x2
Added0x4
Removed0x8
MetadataInserted0x10
MetadataRemoved0x20

AssetId

Type: Struct

Declarations:

Field nameField value
definition_idAssetDefinitionId
account_idAccountId

AssetTransferBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
NumericTransfer<Asset, Numeric, Account>0
StoreTransfer<Asset, Metadata, Account>1

AssetValue

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
NumericNumeric0
StoreMetadata1

AssetValueType

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
NumericNumericSpec0
Store1

AtIndex

Type: Struct

Declarations:

Field nameField value
indexu32
predicateQueryOutputPredicate

BatchedResponse<QueryOutputBox>

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
V1BatchedResponseV1<QueryOutputBox>1

BatchedResponseV1<QueryOutputBox>

Type: Struct

Declarations:

Field nameField value
batchQueryOutputBox
cursorForwardCursor

BlockEvent

Type: Struct

Declarations:

Field nameField value
headerBlockHeader
hashHashOf<SignedBlock>
statusBlockStatus

BlockEventFilter

Type: Struct

Declarations:

Field nameField value
heightOption<u64>
statusOption<BlockStatus>

BlockHeader

Type: Struct

Declarations:

Field nameField value
heightu64
previous_block_hashOption<HashOf<SignedBlock>>
transactions_hashOption<HashOf<MerkleTree<SignedTransaction>>>
timestamp_msu64
view_change_indexu64
consensus_estimation_msu64

BlockMessage

Type: Alias

To: SignedBlock

BlockPayload

Type: Struct

Declarations:

Field nameField value
headerBlockHeader
commit_topologyVec<PeerId>
transactionsVec<TransactionValue>
event_recommendationsVec<EventBox>

BlockRejectionReason

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
ConsensusBlockRejection0

BlockStatus

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
Approved0
RejectedBlockRejectionReason1
Committed2
Applied3

BlockSubscriptionRequest

Type: Alias

To: NonZero<u64>

Burn<Numeric, Asset>

Type: Struct

Declarations:

Field nameField value
objectNumeric
destination_idAssetId

Burn<PublicKey, Account>

Type: Struct

Declarations:

Field nameField value
objectPublicKey
destination_idAccountId

Burn<u32, Trigger>

Type: Struct

Declarations:

Field nameField value
objectu32
destination_idTriggerId

BurnBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
AccountPublicKeyBurn<PublicKey, Account>0
AssetBurn<Numeric, Asset>1
TriggerRepetitionsBurn<u32, Trigger>2

ChainId

Type: Alias

To: String

Compact<u128>

Type: Int

Kind: Compact

Compact<u32>

Type: Int

Kind: Compact

ConfigurationEvent

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
ChangedParameterId0
CreatedParameterId1
DeletedParameterId2

ConfigurationEventFilter

Type: Struct

Declarations:

Field nameField value
id_matcherOption<ParameterId>
event_setConfigurationEventSet

ConfigurationEventSet

Type: Bitmap

Repr: u32

Masks:

Field nameField value
Changed0x1
Created0x2
Deleted0x4

Container

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
AnyQueryOutputPredicate0
AllQueryOutputPredicate1
AtIndexAtIndex2

DataEvent

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
PeerPeerEvent0
DomainDomainEvent1
TriggerTriggerEvent2
RoleRoleEvent3
PermissionTokenPermissionTokenSchemaUpdateEvent4
ConfigurationConfigurationEvent5
ExecutorExecutorEvent6

DataEventFilter

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
Any0
PeerPeerEventFilter1
DomainDomainEventFilter2
AccountAccountEventFilter3
AssetAssetEventFilter4
AssetDefinitionAssetDefinitionEventFilter5
TriggerTriggerEventFilter6
RoleRoleEventFilter7
PermissionTokenSchemaUpdate8
ConfigurationConfigurationEventFilter9
ExecutorExecutorEventFilter10

Domain

Type: Struct

Declarations:

Field nameField value
idDomainId
accountsSortedMap<AccountId, Account>
asset_definitionsSortedMap<AssetDefinitionId, AssetDefinition>
asset_total_quantitiesSortedMap<AssetDefinitionId, Numeric>
logoOption<IpfsPath>
metadataMetadata
owned_byAccountId

DomainEvent

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
AccountAccountEvent0
AssetDefinitionAssetDefinitionEvent1
CreatedDomain2
DeletedDomainId3
MetadataInsertedMetadataChanged<DomainId>4
MetadataRemovedMetadataChanged<DomainId>5
OwnerChangedDomainOwnerChanged6

DomainEventFilter

Type: Struct

Declarations:

Field nameField value
id_matcherOption<DomainId>
event_setDomainEventSet

DomainEventSet

Type: Bitmap

Repr: u32

Masks:

Field nameField value
AnyAccount0x1
AnyAssetDefinition0x2
Created0x4
Deleted0x8
MetadataInserted0x10
MetadataRemoved0x20
OwnerChanged0x40

DomainId

Type: Struct

Declarations:

Field nameField value
nameName

DomainOwnerChanged

Type: Struct

Declarations:

Field nameField value
domain_idDomainId
new_ownerAccountId

Duration

Type: Tuple

Values: (u64, u32)

EventBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
PipelinePipelineEventBox0
DataDataEvent1
TimeTimeEvent2
ExecuteTriggerExecuteTriggerEvent3
TriggerCompletedTriggerCompletedEvent4

EventFilterBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
PipelinePipelineEventFilterBox0
DataDataEventFilter1
TimeTimeEventFilter2
ExecuteTriggerExecuteTriggerEventFilter3
TriggerCompletedTriggerCompletedEventFilter4

EventMessage

Type: Alias

To: EventBox

EventSubscriptionRequest

Type: Alias

To: Vec<EventFilterBox>

Executable

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
InstructionsVec<InstructionBox>0
WasmWasmSmartContract1

ExecuteTrigger

Type: Struct

Declarations:

Field nameField value
trigger_idTriggerId

ExecuteTriggerEvent

Type: Struct

Declarations:

Field nameField value
trigger_idTriggerId
authorityAccountId

ExecuteTriggerEventFilter

Type: Struct

Declarations:

Field nameField value
trigger_idOption<TriggerId>
authorityOption<AccountId>

ExecutionTime

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
PreCommit0
ScheduleSchedule1

Executor

Type: Struct

Declarations:

Field nameField value
wasmWasmSmartContract

ExecutorEvent

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
Upgraded0

ExecutorEventFilter

Type: Struct

Declarations:

Field nameField value
event_setExecutorEventSet

ExecutorEventSet

Type: Bitmap

Repr: u32

Masks:

Field nameField value
Upgraded0x1

Fail

Type: Struct

Declarations:

Field nameField value
messageString

FindAccountById

Type: Struct

Declarations:

Field nameField value
idAccountId

FindAccountKeyValueByIdAndKey

Type: Struct

Declarations:

Field nameField value
idAccountId
keyName

FindAccountsByDomainId

Type: Struct

Declarations:

Field nameField value
domain_idDomainId

FindAccountsByName

Type: Struct

Declarations:

Field nameField value
nameName

FindAccountsWithAsset

Type: Struct

Declarations:

Field nameField value
asset_definition_idAssetDefinitionId

FindAllAccounts

Type: Zero-Size Type (unit type, null type)

FindAllActiveTriggerIds

Type: Zero-Size Type (unit type, null type)

FindAllAssets

Type: Zero-Size Type (unit type, null type)

FindAllAssetsDefinitions

Type: Zero-Size Type (unit type, null type)

FindAllBlockHeaders

Type: Zero-Size Type (unit type, null type)

FindAllBlocks

Type: Zero-Size Type (unit type, null type)

FindAllDomains

Type: Zero-Size Type (unit type, null type)

FindAllParameters

Type: Zero-Size Type (unit type, null type)

FindAllPeers

Type: Zero-Size Type (unit type, null type)

FindAllRoleIds

Type: Zero-Size Type (unit type, null type)

FindAllRoles

Type: Zero-Size Type (unit type, null type)

FindAllTransactions

Type: Zero-Size Type (unit type, null type)

FindAssetById

Type: Struct

Declarations:

Field nameField value
idAssetId

FindAssetDefinitionById

Type: Struct

Declarations:

Field nameField value
idAssetDefinitionId

FindAssetDefinitionKeyValueByIdAndKey

Type: Struct

Declarations:

Field nameField value
idAssetDefinitionId
keyName

FindAssetKeyValueByIdAndKey

Type: Struct

Declarations:

Field nameField value
idAssetId
keyName

FindAssetQuantityById

Type: Struct

Declarations:

Field nameField value
idAssetId

FindAssetsByAccountId

Type: Struct

Declarations:

Field nameField value
account_idAccountId

FindAssetsByAssetDefinitionId

Type: Struct

Declarations:

Field nameField value
asset_definition_idAssetDefinitionId

FindAssetsByDomainId

Type: Struct

Declarations:

Field nameField value
domain_idDomainId

FindAssetsByDomainIdAndAssetDefinitionId

Type: Struct

Declarations:

Field nameField value
domain_idDomainId
asset_definition_idAssetDefinitionId

FindAssetsByName

Type: Struct

Declarations:

Field nameField value
nameName

FindBlockHeaderByHash

Type: Struct

Declarations:

Field nameField value
hashHashOf<SignedBlock>

FindDomainById

Type: Struct

Declarations:

Field nameField value
idDomainId

FindDomainKeyValueByIdAndKey

Type: Struct

Declarations:

Field nameField value
idDomainId
keyName

FindError

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
AssetAssetId0
AssetDefinitionAssetDefinitionId1
AccountAccountId2
DomainDomainId3
MetadataKeyName4
BlockHashOf<SignedBlock>5
TransactionHashOf<SignedTransaction>6
PeerPeerId7
TriggerTriggerId8
RoleRoleId9
PermissionTokenName10
ParameterParameterId11
PublicKeyPublicKey12

FindPermissionTokenSchema

Type: Zero-Size Type (unit type, null type)

FindPermissionTokensByAccountId

Type: Struct

Declarations:

Field nameField value
idAccountId

FindRoleByRoleId

Type: Struct

Declarations:

Field nameField value
idRoleId

FindRolesByAccountId

Type: Struct

Declarations:

Field nameField value
idAccountId

FindTotalAssetQuantityByAssetDefinitionId

Type: Struct

Declarations:

Field nameField value
idAssetDefinitionId

FindTransactionByHash

Type: Struct

Declarations:

Field nameField value
hashHashOf<SignedTransaction>

FindTransactionsByAccountId

Type: Struct

Declarations:

Field nameField value
account_idAccountId

FindTriggerById

Type: Struct

Declarations:

Field nameField value
idTriggerId

FindTriggerKeyValueByIdAndKey

Type: Struct

Declarations:

Field nameField value
idTriggerId
keyName

FindTriggersByDomainId

Type: Struct

Declarations:

Field nameField value
domain_idDomainId

ForwardCursor

Type: Struct

Declarations:

Field nameField value
query_idOption<String>
cursorOption<NonZero<u64>>

GenericPredicateBox<QueryOutputPredicate>

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
AndNonTrivial<GenericPredicateBox<QueryOutputPredicate>>0
OrNonTrivial<GenericPredicateBox<QueryOutputPredicate>>1
NotGenericPredicateBox<QueryOutputPredicate>2
RawQueryOutputPredicate3

Grant<PermissionToken, Account>

Type: Struct

Declarations:

Field nameField value
objectPermissionToken
destination_idAccountId

Grant<PermissionToken, Role>

Type: Struct

Declarations:

Field nameField value
objectPermissionToken
destination_idRoleId

Grant<RoleId, Account>

Type: Struct

Declarations:

Field nameField value
objectRoleId
destination_idAccountId

GrantBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
PermissionTokenGrant<PermissionToken, Account>0
RoleGrant<RoleId, Account>1
RolePermissionTokenGrant<PermissionToken, Role>2

Hash

Type: Alias

To: Array<u8, 32>

HashOf<MerkleTree<SignedTransaction>>

Type: Alias

To: Hash

HashOf<SignedBlock>

Type: Alias

To: Hash

HashOf<SignedTransaction>

Type: Alias

To: Hash

IdBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
DomainIdDomainId0
AccountIdAccountId1
AssetDefinitionIdAssetDefinitionId2
AssetIdAssetId3
PeerIdPeerId4
TriggerIdTriggerId5
RoleIdRoleId6
PermissionTokenIdName7
ParameterIdParameterId8

IdentifiableBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
NewDomainNewDomain0
NewAccountNewAccount1
NewAssetDefinitionNewAssetDefinition2
NewRoleNewRole3
PeerPeer4
DomainDomain5
AccountAccount6
AssetDefinitionAssetDefinition7
AssetAsset8
TriggerTrigger9
RoleRole10
ParameterParameter11

InstructionBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
RegisterRegisterBox0
UnregisterUnregisterBox1
MintMintBox2
BurnBurnBox3
TransferTransferBox4
SetKeyValueSetKeyValueBox5
RemoveKeyValueRemoveKeyValueBox6
GrantGrantBox7
RevokeRevokeBox8
ExecuteTriggerExecuteTrigger9
SetParameterSetParameter10
NewParameterNewParameter11
UpgradeUpgrade12
LogLog13
FailFail14

InstructionEvaluationError

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
UnsupportedInstructionType0
PermissionParameterString1
TypeTypeError2

InstructionExecutionError

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
EvaluateInstructionEvaluationError0
QueryQueryExecutionFail1
ConversionString2
FindFindError3
RepetitionRepetitionError4
MintabilityMintabilityError5
MathMathError6
MetadataMetadataError7
FailString8
InvalidParameterInvalidParameterError9
InvariantViolationString10

InstructionExecutionFail

Type: Struct

Declarations:

Field nameField value
instructionInstructionBox
reasonString

InstructionType

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
Register0
Unregister1
Mint2
Burn3
Transfer4
SetKeyValue5
RemoveKeyValue6
Grant7
Revoke8
ExecuteTrigger9
SetParameter10
NewParameter11
Upgrade12
Log13
Fail14

InvalidParameterError

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
WasmString0
NameLength1

IpfsPath

Type: Alias

To: String

Ipv4Addr

Type: Alias

To: Array<u8, 4>

Ipv6Addr

Type: Alias

To: Array<u16, 8>

JsonString

Type: Alias

To: String

LengthLimits

Type: Struct

Declarations:

Field nameField value
minu32
maxu32

Level

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
TRACE0
DEBUG1
INFO2
WARN3
ERROR4

Limits

Type: Struct

Declarations:

Field nameField value
capacityu32
max_entry_lenu32

Log

Type: Struct

Declarations:

Field nameField value
levelLevel
msgString

MathError

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
Overflow0
NotEnoughQuantity1
DivideByZero2
NegativeValue3
DomainViolation4
Unknown5
FixedPointConversionString6

MerkleTree<SignedTransaction>

Type: Vec

Value: HashOf<SignedTransaction>

Metadata

Type: Alias

To: SortedMap<Name, MetadataValueBox>

MetadataChanged<AccountId>

Type: Struct

Declarations:

Field nameField value
target_idAccountId
keyName
valueMetadataValueBox

MetadataChanged<AssetDefinitionId>

Type: Struct

Declarations:

Field nameField value
target_idAssetDefinitionId
keyName
valueMetadataValueBox

MetadataChanged<AssetId>

Type: Struct

Declarations:

Field nameField value
target_idAssetId
keyName
valueMetadataValueBox

MetadataChanged<DomainId>

Type: Struct

Declarations:

Field nameField value
target_idDomainId
keyName
valueMetadataValueBox

MetadataChanged<TriggerId>

Type: Struct

Declarations:

Field nameField value
target_idTriggerId
keyName
valueMetadataValueBox

MetadataError

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
EmptyPath0
EntryTooBigSizeError1
MaxCapacitySizeError2
MissingSegmentName3
InvalidSegmentName4

MetadataValueBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
Boolbool0
StringString1
NameName2
BytesVec<u8>3
NumericNumeric4
LimitedMetadataMetadata5
VecVec<MetadataValueBox>6

Mint<Numeric, Asset>

Type: Struct

Declarations:

Field nameField value
objectNumeric
destination_idAssetId

Mint<PublicKey, Account>

Type: Struct

Declarations:

Field nameField value
objectPublicKey
destination_idAccountId

Mint<SignatureCheckCondition, Account>

Type: Struct

Declarations:

Field nameField value
objectSignatureCheckCondition
destination_idAccountId

Mint<u32, Trigger>

Type: Struct

Declarations:

Field nameField value
objectu32
destination_idTriggerId

MintBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
AccountAccountMintBox0
AssetMint<Numeric, Asset>1
TriggerRepetitionsMint<u32, Trigger>2

MintabilityError

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
MintUnmintable0
ForbidMintOnMintable1

Mintable

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
Infinitely0
Once1
Not2

Mismatch<AssetValueType>

Type: Struct

Declarations:

Field nameField value
expectedAssetValueType
actualAssetValueType

Name

Type: Alias

To: String

NewAccount

Type: Struct

Declarations:

Field nameField value
idAccountId
signatoriesSortedVec<PublicKey>
metadataMetadata

NewAssetDefinition

Type: Struct

Declarations:

Field nameField value
idAssetDefinitionId
value_typeAssetValueType
mintableMintable
logoOption<IpfsPath>
metadataMetadata

NewDomain

Type: Struct

Declarations:

Field nameField value
idDomainId
logoOption<IpfsPath>
metadataMetadata

NewParameter

Type: Struct

Declarations:

Field nameField value
parameterParameter

NewRole

Type: Struct

Declarations:

Field nameField value
innerRole

NonTrivial<GenericPredicateBox<QueryOutputPredicate>>

Type: Alias

To: Vec<GenericPredicateBox<QueryOutputPredicate>>

NonZero<u32>

Type: Alias

To: u32

NonZero<u64>

Type: Alias

To: u64

Numeric

Type: Struct

Declarations:

Field nameField value
mantissaCompact<u128>
scaleCompact<u32>

NumericSpec

Type: Struct

Declarations:

Field nameField value
scaleOption<u32>

Option<AccountId>

Type: Option

Some: AccountId

Option<AssetDefinitionId>

Type: Option

Some: AssetDefinitionId

Option<AssetId>

Type: Option

Some: AssetId

Option<BlockStatus>

Type: Option

Some: BlockStatus

Option<DomainId>

Type: Option

Some: DomainId

Option<Duration>

Type: Option

Some: Duration

Option<HashOf<MerkleTree<SignedTransaction>>>

Type: Option

Some: HashOf<MerkleTree<SignedTransaction>>

Option<HashOf<SignedBlock>>

Type: Option

Some: HashOf<SignedBlock>

Option<HashOf<SignedTransaction>>

Type: Option

Some: HashOf<SignedTransaction>

Option<IpfsPath>

Type: Option

Some: IpfsPath

Option<NonZero<u32>>

Type: Option

Some: NonZero<u32>

Option<NonZero<u64>>

Type: Option

Some: NonZero<u64>

Option<Option<u64>>

Type: Option

Some: Option<u64>

Option<ParameterId>

Type: Option

Some: ParameterId

Option<PeerId>

Type: Option

Some: PeerId

Option<RoleId>

Type: Option

Some: RoleId

Option<String>

Type: Option

Some: String

Option<TimeInterval>

Type: Option

Some: TimeInterval

Option<TransactionRejectionReason>

Type: Option

Some: TransactionRejectionReason

Option<TransactionStatus>

Type: Option

Some: TransactionStatus

Option<TriggerCompletedOutcomeType>

Type: Option

Some: TriggerCompletedOutcomeType

Option<TriggerId>

Type: Option

Some: TriggerId

Option<u32>

Type: Option

Some: u32

Option<u64>

Type: Option

Some: u64

Parameter

Type: Struct

Declarations:

Field nameField value
idParameterId
valParameterValueBox

ParameterId

Type: Struct

Declarations:

Field nameField value
nameName

ParameterValueBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
TransactionLimitsTransactionLimits0
MetadataLimitsLimits1
LengthLimitsLengthLimits2
NumericNumeric3

Peer

Type: Struct

Declarations:

Field nameField value
idPeerId

PeerEvent

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
AddedPeerId0
RemovedPeerId1

PeerEventFilter

Type: Struct

Declarations:

Field nameField value
id_matcherOption<PeerId>
event_setPeerEventSet

PeerEventSet

Type: Bitmap

Repr: u32

Masks:

Field nameField value
Added0x1
Removed0x2

PeerId

Type: Struct

Declarations:

Field nameField value
addressSocketAddr
public_keyPublicKey

PermissionToken

Type: Struct

Declarations:

Field nameField value
definition_idName
payloadJsonString

PermissionTokenSchema

Type: Struct

Declarations:

Field nameField value
token_idsVec<Name>
schemaString

PermissionTokenSchemaUpdateEvent

Type: Struct

Declarations:

Field nameField value
old_schemaPermissionTokenSchema
new_schemaPermissionTokenSchema

PipelineEventBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
TransactionTransactionEvent0
BlockBlockEvent1

PipelineEventFilterBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
TransactionTransactionEventFilter0
BlockBlockEventFilter1

PublicKey

Type: Struct

Declarations:

Field nameField value
algorithmAlgorithm
payloadVec<u8>

QueryBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
FindAllAccountsFindAllAccounts0
FindAccountByIdFindAccountById1
FindAccountKeyValueByIdAndKeyFindAccountKeyValueByIdAndKey2
FindAccountsByNameFindAccountsByName3
FindAccountsByDomainIdFindAccountsByDomainId4
FindAccountsWithAssetFindAccountsWithAsset5
FindAllAssetsFindAllAssets6
FindAllAssetsDefinitionsFindAllAssetsDefinitions7
FindAssetByIdFindAssetById8
FindAssetDefinitionByIdFindAssetDefinitionById9
FindAssetsByNameFindAssetsByName10
FindAssetsByAccountIdFindAssetsByAccountId11
FindAssetsByAssetDefinitionIdFindAssetsByAssetDefinitionId12
FindAssetsByDomainIdFindAssetsByDomainId13
FindAssetsByDomainIdAndAssetDefinitionIdFindAssetsByDomainIdAndAssetDefinitionId14
FindAssetQuantityByIdFindAssetQuantityById15
FindTotalAssetQuantityByAssetDefinitionIdFindTotalAssetQuantityByAssetDefinitionId16
FindAssetKeyValueByIdAndKeyFindAssetKeyValueByIdAndKey17
FindAssetDefinitionKeyValueByIdAndKeyFindAssetDefinitionKeyValueByIdAndKey18
FindAllDomainsFindAllDomains19
FindDomainByIdFindDomainById20
FindDomainKeyValueByIdAndKeyFindDomainKeyValueByIdAndKey21
FindAllPeersFindAllPeers22
FindAllBlocksFindAllBlocks23
FindAllBlockHeadersFindAllBlockHeaders24
FindBlockHeaderByHashFindBlockHeaderByHash25
FindAllTransactionsFindAllTransactions26
FindTransactionsByAccountIdFindTransactionsByAccountId27
FindTransactionByHashFindTransactionByHash28
FindPermissionTokensByAccountIdFindPermissionTokensByAccountId29
FindPermissionTokenSchemaFindPermissionTokenSchema30
FindAllActiveTriggerIdsFindAllActiveTriggerIds31
FindTriggerByIdFindTriggerById32
FindTriggerKeyValueByIdAndKeyFindTriggerKeyValueByIdAndKey33
FindTriggersByDomainIdFindTriggersByDomainId34
FindAllRolesFindAllRoles35
FindAllRoleIdsFindAllRoleIds36
FindRoleByRoleIdFindRoleByRoleId37
FindRolesByAccountIdFindRolesByAccountId38
FindAllParametersFindAllParameters39

QueryExecutionFail

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
SignatureString0
FindFindError1
ConversionString2
UnknownCursor3
FetchSizeTooBig4

QueryOutputBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
IdIdBox0
IdentifiableIdentifiableBox1
TransactionTransactionQueryOutput2
PermissionTokenPermissionToken3
PermissionTokenSchemaPermissionTokenSchema4
LimitedMetadataMetadataValueBox5
NumericNumeric6
BlockHeaderBlockHeader7
BlockSignedBlock8
VecVec<QueryOutputBox>9

QueryOutputPredicate

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
IdentifiableStringPredicate0
ContainerContainer1
DisplayStringPredicate2
NumericalSemiRange3
TimeStampSemiInterval<u128>4
Pass5

QueryPayload

Type: Struct

Declarations:

Field nameField value
authorityAccountId
queryQueryBox
filterGenericPredicateBox<QueryOutputPredicate>

Register<Account>

Type: Struct

Declarations:

Field nameField value
objectNewAccount

Register<Asset>

Type: Struct

Declarations:

Field nameField value
objectAsset

Register<AssetDefinition>

Type: Struct

Declarations:

Field nameField value
objectNewAssetDefinition

Register<Domain>

Type: Struct

Declarations:

Field nameField value
objectNewDomain

Register<Peer>

Type: Struct

Declarations:

Field nameField value
objectPeer

Register<Role>

Type: Struct

Declarations:

Field nameField value
objectNewRole

Register<Trigger>

Type: Struct

Declarations:

Field nameField value
objectTrigger

RegisterBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
PeerRegister<Peer>0
DomainRegister<Domain>1
AccountRegister<Account>2
AssetDefinitionRegister<AssetDefinition>3
AssetRegister<Asset>4
RoleRegister<Role>5
TriggerRegister<Trigger>6

RemoveKeyValue<Account>

Type: Struct

Declarations:

Field nameField value
object_idAccountId
keyName

RemoveKeyValue<Asset>

Type: Struct

Declarations:

Field nameField value
object_idAssetId
keyName

RemoveKeyValue<AssetDefinition>

Type: Struct

Declarations:

Field nameField value
object_idAssetDefinitionId
keyName

RemoveKeyValue<Domain>

Type: Struct

Declarations:

Field nameField value
object_idDomainId
keyName

RemoveKeyValue<Trigger>

Type: Struct

Declarations:

Field nameField value
object_idTriggerId
keyName

RemoveKeyValueBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
DomainRemoveKeyValue<Domain>0
AccountRemoveKeyValue<Account>1
AssetDefinitionRemoveKeyValue<AssetDefinition>2
AssetRemoveKeyValue<Asset>3
TriggerRemoveKeyValue<Trigger>4

Repeats

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
Indefinitely0
Exactlyu321

RepetitionError

Type: Struct

Declarations:

Field nameField value
instruction_typeInstructionType
idIdBox

Revoke<PermissionToken, Account>

Type: Struct

Declarations:

Field nameField value
objectPermissionToken
destination_idAccountId

Revoke<PermissionToken, Role>

Type: Struct

Declarations:

Field nameField value
objectPermissionToken
destination_idRoleId

Revoke<RoleId, Account>

Type: Struct

Declarations:

Field nameField value
objectRoleId
destination_idAccountId

RevokeBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
PermissionTokenRevoke<PermissionToken, Account>0
RoleRevoke<RoleId, Account>1
RolePermissionTokenRevoke<PermissionToken, Role>2

Role

Type: Struct

Declarations:

Field nameField value
idRoleId
permissionsSortedVec<PermissionToken>

RoleEvent

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
CreatedRole0
DeletedRoleId1
PermissionRemovedRolePermissionChanged2
PermissionAddedRolePermissionChanged3

RoleEventFilter

Type: Struct

Declarations:

Field nameField value
id_matcherOption<RoleId>
event_setRoleEventSet

RoleEventSet

Type: Bitmap

Repr: u32

Masks:

Field nameField value
Created0x1
Deleted0x2
PermissionRemoved0x4
PermissionAdded0x8

RoleId

Type: Struct

Declarations:

Field nameField value
nameName

RolePermissionChanged

Type: Struct

Declarations:

Field nameField value
role_idRoleId
permission_token_idName

Schedule

Type: Struct

Declarations:

Field nameField value
startDuration
periodOption<Duration>

SemiInterval<Numeric>

Type: Struct

Declarations:

Field nameField value
startNumeric
limitNumeric

SemiInterval<u128>

Type: Struct

Declarations:

Field nameField value
startu128
limitu128

SemiRange

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
NumericSemiInterval<Numeric>0

SetKeyValue<Account>

Type: Struct

Declarations:

Field nameField value
object_idAccountId
keyName
valueMetadataValueBox

SetKeyValue<Asset>

Type: Struct

Declarations:

Field nameField value
object_idAssetId
keyName
valueMetadataValueBox

SetKeyValue<AssetDefinition>

Type: Struct

Declarations:

Field nameField value
object_idAssetDefinitionId
keyName
valueMetadataValueBox

SetKeyValue<Domain>

Type: Struct

Declarations:

Field nameField value
object_idDomainId
keyName
valueMetadataValueBox

SetKeyValue<Trigger>

Type: Struct

Declarations:

Field nameField value
object_idTriggerId
keyName
valueMetadataValueBox

SetKeyValueBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
DomainSetKeyValue<Domain>0
AccountSetKeyValue<Account>1
AssetDefinitionSetKeyValue<AssetDefinition>2
AssetSetKeyValue<Asset>3
TriggerSetKeyValue<Trigger>4

SetParameter

Type: Struct

Declarations:

Field nameField value
parameterParameter

Signature

Type: Struct

Declarations:

Field nameField value
public_keyPublicKey
payloadVec<u8>

SignatureCheckCondition

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
AnyAccountSignatureOrVec<PublicKey>0
AllAccountSignaturesAndVec<PublicKey>1

SignatureOf<BlockPayload>

Type: Alias

To: Signature

SignatureOf<QueryPayload>

Type: Alias

To: Signature

SignatureOf<TransactionPayload>

Type: Alias

To: Signature

SignaturesOf<BlockPayload>

Type: Struct

Declarations:

Field nameField value
signaturesSortedVec<SignatureOf<BlockPayload>>

SignaturesOf<TransactionPayload>

Type: Struct

Declarations:

Field nameField value
signaturesSortedVec<SignatureOf<TransactionPayload>>

SignedBlock

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
V1SignedBlockV11

SignedBlockV1

Type: Struct

Declarations:

Field nameField value
signaturesSignaturesOf<BlockPayload>
payloadBlockPayload

SignedQuery

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
V1SignedQueryV11

SignedQueryV1

Type: Struct

Declarations:

Field nameField value
signatureSignatureOf<QueryPayload>
payloadQueryPayload

SignedTransaction

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
V1SignedTransactionV11

SignedTransactionV1

Type: Struct

Declarations:

Field nameField value
signaturesSignaturesOf<TransactionPayload>
payloadTransactionPayload

SizeError

Type: Struct

Declarations:

Field nameField value
limitsLimits
actualu64

SocketAddr

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
Ipv4SocketAddrV40
Ipv6SocketAddrV61
HostSocketAddrHost2

SocketAddrHost

Type: Struct

Declarations:

Field nameField value
hostString
portu16

SocketAddrV4

Type: Struct

Declarations:

Field nameField value
ipIpv4Addr
portu16

SocketAddrV6

Type: Struct

Declarations:

Field nameField value
ipIpv6Addr
portu16

SortedMap<AccountId, Account>

Type: Map

Key: AccountId

Value: Account

SortedMap<AssetDefinitionId, AssetDefinition>

Type: Map

Key: AssetDefinitionId

Value: AssetDefinition

SortedMap<AssetDefinitionId, Numeric>

Type: Map

Key: AssetDefinitionId

Value: Numeric

SortedMap<AssetId, Asset>

Type: Map

Key: AssetId

Value: Asset

SortedMap<Name, MetadataValueBox>

Type: Map

Key: Name

Value: MetadataValueBox

SortedVec<PermissionToken>

Type: Vec

Value: PermissionToken

SortedVec<PublicKey>

Type: Vec

Value: PublicKey

SortedVec<SignatureOf<BlockPayload>>

Type: Vec

Value: SignatureOf<BlockPayload>

SortedVec<SignatureOf<TransactionPayload>>

Type: Vec

Value: SignatureOf<TransactionPayload>

String

Type: Alias

To: String

StringPredicate

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
ContainsString0
StartsWithString1
EndsWithString2
IsString3

TimeEvent

Type: Struct

Declarations:

Field nameField value
prev_intervalOption<TimeInterval>
intervalTimeInterval

TimeEventFilter

Type: Alias

To: ExecutionTime

TimeInterval

Type: Struct

Declarations:

Field nameField value
sinceDuration
lengthDuration

TransactionEvent

Type: Struct

Declarations:

Field nameField value
hashHashOf<SignedTransaction>
block_heightOption<u64>
statusTransactionStatus

TransactionEventFilter

Type: Struct

Declarations:

Field nameField value
hashOption<HashOf<SignedTransaction>>
block_heightOption<Option<u64>>
statusOption<TransactionStatus>

TransactionLimitError

Type: Struct

Declarations:

Field nameField value
reasonString

TransactionLimits

Type: Struct

Declarations:

Field nameField value
max_instruction_numberu64
max_wasm_size_bytesu64

TransactionPayload

Type: Struct

Declarations:

Field nameField value
chain_idChainId
authorityAccountId
creation_time_msu64
instructionsExecutable
time_to_live_msOption<NonZero<u64>>
nonceOption<NonZero<u32>>
metadataSortedMap<Name, MetadataValueBox>

TransactionQueryOutput

Type: Struct

Declarations:

Field nameField value
block_hashHashOf<SignedBlock>
transactionTransactionValue

TransactionRejectionReason

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
AccountDoesNotExistFindError0
LimitCheckTransactionLimitError1
ValidationValidationFail2
InstructionExecutionInstructionExecutionFail3
WasmExecutionWasmExecutionFail4

TransactionStatus

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
Queued0
Expired1
Approved2
RejectedTransactionRejectionReason3

TransactionValue

Type: Struct

Declarations:

Field nameField value
valueSignedTransaction
errorOption<TransactionRejectionReason>

Transfer<Account, AssetDefinitionId, Account>

Type: Struct

Declarations:

Field nameField value
source_idAccountId
objectAssetDefinitionId
destination_idAccountId

Transfer<Account, DomainId, Account>

Type: Struct

Declarations:

Field nameField value
source_idAccountId
objectDomainId
destination_idAccountId

Transfer<Asset, Metadata, Account>

Type: Struct

Declarations:

Field nameField value
source_idAssetId
objectMetadata
destination_idAccountId

Transfer<Asset, Numeric, Account>

Type: Struct

Declarations:

Field nameField value
source_idAssetId
objectNumeric
destination_idAccountId

TransferBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
DomainTransfer<Account, DomainId, Account>0
AssetDefinitionTransfer<Account, AssetDefinitionId, Account>1
AssetAssetTransferBox2

Trigger

Type: Struct

Declarations:

Field nameField value
idTriggerId
actionAction

TriggerCompletedEvent

Type: Struct

Declarations:

Field nameField value
trigger_idTriggerId
outcomeTriggerCompletedOutcome

TriggerCompletedEventFilter

Type: Struct

Declarations:

Field nameField value
trigger_idOption<TriggerId>
outcome_typeOption<TriggerCompletedOutcomeType>

TriggerCompletedOutcome

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
Success0
FailureString1

TriggerCompletedOutcomeType

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
Success0
Failure1

TriggerEvent

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
CreatedTriggerId0
DeletedTriggerId1
ExtendedTriggerNumberOfExecutionsChanged2
ShortenedTriggerNumberOfExecutionsChanged3
MetadataInsertedMetadataChanged<TriggerId>4
MetadataRemovedMetadataChanged<TriggerId>5

TriggerEventFilter

Type: Struct

Declarations:

Field nameField value
id_matcherOption<TriggerId>
event_setTriggerEventSet

TriggerEventSet

Type: Bitmap

Repr: u32

Masks:

Field nameField value
Created0x1
Deleted0x2
Extended0x4
Shortened0x8
MetadataInserted0x10
MetadataRemoved0x20

TriggerId

Type: Struct

Declarations:

Field nameField value
domain_idOption<DomainId>
nameName

TriggerNumberOfExecutionsChanged

Type: Struct

Declarations:

Field nameField value
trigger_idTriggerId
byu32

TriggeringEventFilterBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
PipelinePipelineEventFilterBox0
DataDataEventFilter1
TimeTimeEventFilter2
ExecuteTriggerExecuteTriggerEventFilter3

TypeError

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
AssetValueTypeMismatch<AssetValueType>0
NumericAssetValueTypeExpectedAssetValueType1
StoreAssetValueTypeExpectedAssetValueType2

Unregister<Account>

Type: Struct

Declarations:

Field nameField value
object_idAccountId

Unregister<Asset>

Type: Struct

Declarations:

Field nameField value
object_idAssetId

Unregister<AssetDefinition>

Type: Struct

Declarations:

Field nameField value
object_idAssetDefinitionId

Unregister<Domain>

Type: Struct

Declarations:

Field nameField value
object_idDomainId

Unregister<Peer>

Type: Struct

Declarations:

Field nameField value
object_idPeerId

Unregister<Role>

Type: Struct

Declarations:

Field nameField value
object_idRoleId

Unregister<Trigger>

Type: Struct

Declarations:

Field nameField value
object_idTriggerId

UnregisterBox

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
PeerUnregister<Peer>0
DomainUnregister<Domain>1
AccountUnregister<Account>2
AssetDefinitionUnregister<AssetDefinition>3
AssetUnregister<Asset>4
RoleUnregister<Role>5
TriggerUnregister<Trigger>6

Upgrade

Type: Struct

Declarations:

Field nameField value
executorExecutor

ValidationFail

Type: Enum

Variants:

Variant nameVariant valueDiscriminant
NotPermittedString0
InstructionFailedInstructionExecutionError1
QueryFailedQueryExecutionFail2
TooComplex3
InternalError4

Vec<EventBox>

Type: Vec

Value: EventBox

Vec<EventFilterBox>

Type: Vec

Value: EventFilterBox

Vec<GenericPredicateBox<QueryOutputPredicate>>

Type: Vec

Value: GenericPredicateBox<QueryOutputPredicate>

Vec<InstructionBox>

Type: Vec

Value: InstructionBox

Vec<MetadataValueBox>

Type: Vec

Value: MetadataValueBox

Vec<Name>

Type: Vec

Value: Name

Vec<PeerId>

Type: Vec

Value: PeerId

Vec<PublicKey>

Type: Vec

Value: PublicKey

Vec<QueryOutputBox>

Type: Vec

Value: QueryOutputBox

Vec<TransactionValue>

Type: Vec

Value: TransactionValue

Vec<u8>

Type: Vec

Value: u8

WasmExecutionFail

Type: Struct

Declarations:

Field nameField value
reasonString

WasmSmartContract

Type: Alias

To: Vec<u8>

bool

Type: Alias

To: bool

u128

Type: Int

Kind: FixedWidth

u16

Type: Int

Kind: FixedWidth

u32

Type: Int

Kind: FixedWidth

u64

Type: Int

Kind: FixedWidth

u8

Type: Int

Kind: FixedWidth

',1260),l=[r];function i(n,s,c,g,h,y){return a(),e("div",null,l)}const f=t(o,[["render",i]]);export{x as __pageData,f as default}; diff --git a/assets/reference_data-model-schema.md.Ncq8wG4o.lean.js b/assets/reference_data-model-schema.md.Ncq8wG4o.lean.js new file mode 100644 index 00000000..e801568f --- /dev/null +++ b/assets/reference_data-model-schema.md.Ncq8wG4o.lean.js @@ -0,0 +1 @@ +import{_ as t,c as e,o as a,V as d}from"./chunks/framework.B6c1f-8R.js";const x=JSON.parse('{"title":"Data Model Schema","description":"","frontmatter":{},"headers":[],"relativePath":"reference/data-model-schema.md","filePath":"reference/data-model-schema.md","lastUpdated":1727242778000}'),o={name:"reference/data-model-schema.md"},r=d("",1260),l=[r];function i(n,s,c,g,h,y){return a(),e("div",null,l)}const f=t(o,[["render",i]]);export{x as __pageData,f as default}; diff --git a/assets/reference_ffi.md.CSR1g8Hj.js b/assets/reference_ffi.md.CSR1g8Hj.js new file mode 100644 index 00000000..cc350144 --- /dev/null +++ b/assets/reference_ffi.md.CSR1g8Hj.js @@ -0,0 +1,16 @@ +import{_ as e,c as i,o as s,V as a}from"./chunks/framework.B6c1f-8R.js";const t="/iroha-2-docs/assets/ffi.CTI0y00c.png",y=JSON.parse('{"title":"Foreign Function Interfaces (FFI)","description":"","frontmatter":{},"headers":[],"relativePath":"reference/ffi.md","filePath":"reference/ffi.md","lastUpdated":1727242778000}'),n={name:"reference/ffi.md"},o=a(`

Foreign Function Interfaces (FFI)

To reduce the sizes of smartcontracts, we provide a dynamic library in the execution environment. We shall detail how to link against that library and use the functions at a later date, but for now, let's explore how to include functions and trait implementations into that library.

Why FFI

A function is a rather abstract entity, and while most languages agree on what a function should do, the way in which said functions are represented is very different. Moreover, in some languages (like Rust), the consequences of calling a function, and the things that it is allowed to do are different. Because one can use any language to create a WASM smartcontract, we need to level the playing field. This is where the concept of foreign function interface (FFI) comes in.

The main standard used today is the C application binary interface. It's simple, it's guaranteed to be available even in languages which can't compile to WASM, and it's stable. In principle, you could do everything manually, but Iroha provides you with a crate iroha_ffi which contains all you need to generate FFI-compliant functions out of your existing Rust API.

You can, of course, do this your way. The iroha_ffi crate merely generates the code that you would need to generate anyway. Writing the necessary boilerplate requires quite a bit of diligence and discipline. Every function call over the FFI boundary is unsafe with a potential to cause undefined behaviour. The method by which we managed to solve it, revolves around using robust repr(C) types.

INFO

The only exception are pointers. The null check and the validity cannot be enforced globally, so raw pointers (as always) are only used in exceptional cases. Given that we provide wrappers around almost every instance of an object in the Iroha data model, you shouldn't have to use raw pointers at all.

Example

Here is an example of generating a binding:

rust
#[derive(FfiType)]
+struct DaysSinceEquinox(u32);
+
+#[ffi_export]
+impl DaysSinceEquinox {
+    pub fn update_value(&mut self, a: &u8) {
+        self.0 = *a as u32;
+    }
+}

The example above will generate the following binding with DaysSinceEquinox represented as an opaque pointer:

rust
pub extern fn DaysSinceEquinox__update_value(handle: *mut DaysSinceEquinox, a: *const u8) -> FfiReturn {
+    // function implementation
+}

FFI Binding Generation

The iroha_ffi crate is used to generate functions that are callable via FFI. Given Rust structs and methods, they generate the unsafe code that you would need in order to cross the linking boundary.

A Rust type is converted into a robust repr(C) type that can cross the FFI boundary with FfiType::into_ffi. This goes the other way around as well: FFI ReprC type is converted into a Rust type via FfiType::try_from_ffi.

WARNING

Note that the opposite conversion is fallible and can cause undefined behaviour. While we can make the best effort to avoid the most obvious mistakes, you must ensure the program's correctness on your end.

The diagram below uses the creation of a new domain as an example to show the conversion process (more on the name mangling semantics in a separate section).

Untitled

The main traits that enable binding generation are ReprC, FfiType and FfiConvert

TraitDescription
ReprCThis trait represents a robust type that conforms to C ABI. The type can be safely shared across FFI boundaries.
FfiTypeThis trait defines a corresponding ReprC type for a given Rust type. The defined ReprC type is used in place of the Rust type in the API of the generated FFI function.
FfiConvertThis trait defines two methods into_ffi and try_from_ffi that are used to perform the conversion of the Rust type to or from ReprC type.

Note that there is no ownership transfer over FFI except for opaque pointer types. All other types that carry ownership, such as Vec<T>, are cloned.

Name Mangling

Note the use of double underscores in generated names of FFI objects:

  • For the inherent_fn method defined on the StructName struct, the FFI name would be StructName__inherent_fn.

  • For the MethodName method from the TraitName trait in the StructName struct, the FFI name would be StructName__TraitName__MethodName.

  • To set the field_name field in the StructName struct, the FFI function name would be StructName__set_field_name.

  • To get the field_name field in the StructName struct, the FFI function name would be StructName__field_name.

  • To get the mutable field_name field in the StructName struct, the FFI function name would be StrucuName__field_name_mut.

  • For the freestanding module_name::fn_name, the FFI name would be module_name::__fn_name.

  • For the traits that are not generic and allow sharing their implementation in the FFI (see Clone below), the FFI name would be module_name::__clone.

    rust
    impl Clone for Type1 {
    +    fn clone(&self) -> Self;
    +}
    +impl Clone for Type2 {
    +    fn clone(&self) -> Self;
    +}
`,24),h=[o];function l(r,d,p,c,k,u){return s(),i("div",null,h)}const f=e(n,[["render",l]]);export{y as __pageData,f as default}; diff --git a/assets/reference_ffi.md.CSR1g8Hj.lean.js b/assets/reference_ffi.md.CSR1g8Hj.lean.js new file mode 100644 index 00000000..1385e931 --- /dev/null +++ b/assets/reference_ffi.md.CSR1g8Hj.lean.js @@ -0,0 +1 @@ +import{_ as e,c as i,o as s,V as a}from"./chunks/framework.B6c1f-8R.js";const t="/iroha-2-docs/assets/ffi.CTI0y00c.png",y=JSON.parse('{"title":"Foreign Function Interfaces (FFI)","description":"","frontmatter":{},"headers":[],"relativePath":"reference/ffi.md","filePath":"reference/ffi.md","lastUpdated":1727242778000}'),n={name:"reference/ffi.md"},o=a("",24),h=[o];function l(r,d,p,c,k,u){return s(),i("div",null,h)}const f=e(n,[["render",l]]);export{y as __pageData,f as default}; diff --git a/assets/reference_glossary.md.Bvar2yPY.js b/assets/reference_glossary.md.Bvar2yPY.js new file mode 100644 index 00000000..9f585aca --- /dev/null +++ b/assets/reference_glossary.md.Bvar2yPY.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as i,V as r}from"./chunks/framework.B6c1f-8R.js";const m=JSON.parse('{"title":"Glossary","description":"","frontmatter":{},"headers":[],"relativePath":"reference/glossary.md","filePath":"reference/glossary.md","lastUpdated":1727242778000}'),t={name:"reference/glossary.md"},o=r('

Glossary

Here you can find definitions of all Iroha-related entities.

Blockchain ledgers

Blockchain ledgers are digital record-keeping systems that use blockchain technology to keep financial records. These are named after old-fashioned books that were used for financial records such as prices, news, and transaction information.

During medieval times, ledger books were open for public viewing and accuracy verification. This idea is reflected in the blockchain-based systems that can check the stored data for validity.

Peer

A peer in Iroha means an Iroha process instance to which other Iroha processes and client applications can connect. A single machine can host several Iroha peers. Peers are equal regarding their resources and capabilities, with an important exception: only one of the peers runs the genesis block at the bootstrapping stage of the Iroha network.

Other blockchains may refer to the same concept as a node or a validator.

A peer can be a process on its host system. It also can be contained in a Docker container and a Kubernetes pod.

Asset

In the context of blockchains, an asset is the representation of a valuable object on the blockchain.

Additional information on assets is available here.

Fungible assets

Such assets can be easily swapped for other assets of the same type because they are interchangeable.

As an example, all units of the same currency are equal in their value and can be used to purchase goods. Typically, fungible assets are identical in appearance, aside from the wear of banknotes and coins.

Non-fungible assets

Non-fungible assets are unique and valuable due to their specific characteristics and rarity; their value cannot be compared to other assets.

  • A painting's value can vary based on the artist, the time period it was painted, and the public's interest in it.
  • Two houses on the same street may have differing levels of maintenance.
  • Jewellery manufacturers typically offer a range of different designs.

Mintable assets

An asset is mintable if more of the same type can be issued.

Non-mintable assets

If the initial amount of an asset is specified once and doesn't change, it is considered non-mintable.

The Genesis block sets this information for the Iroha configuration.

Byzantine fault-tolerance (BFT)

The property of being able to properly function with a network containing a certain percentage of malicious actors. Iroha is capable of functioning with up to 33% malicious actors in its peer-to-peer network.

Iroha Components

Rust modules containing Iroha functionality.

Sumeragi (Emperor)

The Iroha module responsible for consensus.

Torii (Gate)

Module with the incoming request handling logic for the peer. It is used to receive, accept and route incoming instructions, and HTTP queries, as well as run-time configuration updates.

Kura (Warehouse)

Persistence-related logic. It handles storing the blocks, log rotation, block storage folder rotation, etc.

Kagami(Teacher and Exemplar and/or looking glass)

Generator for commonly used data. It can generate cryptographic key pairs, genesis blocks, documentation, etc.

Merkle tree (hash tree)

A data structure used to validate and verify the state at each block height. Iroha's current implementation is a binary tree. See Wikipedia for more details.

Smart contracts

Smart contracts are blockchain-based programs that run when a specific set of conditions is met. In Iroha smart contracts are implemented using core Iroha special instructions.

Triggers

An event type that allows invoking an Iroha special instruction at specific block commit, time (with some caveats), etc. More on triggers here.

Versioning

Each request is labelled with the API version to which it belongs. It allows a combination of different binary versions of Iroha client/peer software to interoperate, which in turn allows software upgrades in the Iroha network.

Hijiri (peer reputation system)

Iroha's reputation system. It allows prioritising communication with peers that have a good track-record, and reducing the harm that can be caused by malicious peers.

Iroha Modules

Third party extensions to Iroha that provide custom functionality.

Iroha Special Instructions (ISI)

A library of smart contracts provided with Iroha. These can be invoked via either transactions or registered event listeners. More on ISI here.

Utility Iroha Special Instructions

This set of isi contains logical instructions like If, I/O related like Notify and compositions like Sequence. They are mostly used as custom instructions.

Core Iroha Special Instructions

Special instructions provided with every Iroha deployment. These include some domain-specific as well as utility instructions.

Domain-specific Iroha Special Instructions

Instructions related to domain-specific activities: assets, accounts, domains, peer management). These provide the tools necessary to make changes to the World State View in a secure and safe manner.

Custom Iroha Special Instruction

Instructions provided in Iroha Modules, by clients or 3rd parties. These can only be built using the Core Instructions. Forking and modifying the Iroha source code is not recommended, as special instructions not agreed-upon by peers in an Iroha deployment will be treated as faults, thus peers running a modified instance will have their access revoked.

Iroha Query

A request to read the World State View without modifying said view. More on queries here.

View change

A process that takes place in case of a failed attempt at consensus. Usually this entails the election of a new Leader.

World state view (WSV)

In-memory representation of the current blockchain state. This includes all currently loaded blocks, with all of their contents, as well as peers elected for the current epoch.

Leader

In an iroha network, a peer is selected randomly and granted the special privilege of forming the next block. This privilege can be revoked in networks that achieve Byzantine fault-torelance via view change.

',66),s=[o];function n(l,h,c,d,u,p){return i(),a("div",null,s)}const b=e(t,[["render",n]]);export{m as __pageData,b as default}; diff --git a/assets/reference_glossary.md.Bvar2yPY.lean.js b/assets/reference_glossary.md.Bvar2yPY.lean.js new file mode 100644 index 00000000..d47f5088 --- /dev/null +++ b/assets/reference_glossary.md.Bvar2yPY.lean.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as i,V as r}from"./chunks/framework.B6c1f-8R.js";const m=JSON.parse('{"title":"Glossary","description":"","frontmatter":{},"headers":[],"relativePath":"reference/glossary.md","filePath":"reference/glossary.md","lastUpdated":1727242778000}'),t={name:"reference/glossary.md"},o=r("",66),s=[o];function n(l,h,c,d,u,p){return i(),a("div",null,s)}const b=e(t,[["render",n]]);export{m as __pageData,b as default}; diff --git a/assets/reference_instructions.md.BQavKnbm.js b/assets/reference_instructions.md.BQavKnbm.js new file mode 100644 index 00000000..eb331eb4 --- /dev/null +++ b/assets/reference_instructions.md.BQavKnbm.js @@ -0,0 +1 @@ +import{_ as a,E as r,c as o,m as e,J as s,V as n,o as i}from"./chunks/framework.B6c1f-8R.js";const I=JSON.parse('{"title":"Iroha Special Instructions","description":"","frontmatter":{},"headers":[],"relativePath":"reference/instructions.md","filePath":"reference/instructions.md","lastUpdated":1727242778000}'),c={name:"reference/instructions.md"},A=n('

Iroha Special Instructions

The following instructions are supported in Iroha 2:

InstructionDescriptions
Register/UnregisterGive an ID to a new entity on the blockchain.
Mint/BurnMint/burn assets, triggers, or permission tokens.
SetKeyValue/RemoveKeyValueUpdate blockchain object metadata.
NewParameter/SetParameterCreate/set a chain-wide config parameter.
Grant/RevokeGive or remove certain permissions from accounts.
TransferTransfer assets between accounts.
ExecuteTriggerExecute triggers.
If, Pair, SequenceUse to create composite instructions.
',3),u={class:"details custom-block"},l=e("summary",null,"Diagram: Iroha Special Instructions",-1);function d(B,x,h,g,m,f){const t=r("MermaidRenderWrap");return i(),o("div",null,[A,e("details",u,[l,s(t,{id:"mermaid_ed2856e2f3a15f4a487319a2418ef404bba5a0dac5df0f42a043a82e9151599b85f73422c959b6bc3b0a5bbb39538fba27abaddf4e4077d492e2301eec56d75f",text:"classDiagram%0A%0Adirection%20LR%0A%0Aclass%20Instruction%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20Register(RegisterBox)%0A%20%20%20%20Unregister(UnregisterBox)%0A%20%20%20%20Mint(MintBox)%0A%20%20%20%20Burn(BurnBox)%0A%20%20%20%20Transfer(TransferBox)%0A%20%20%20%20If(Box~If~)%0A%20%20%20%20Pair(Box~Pair~)%0A%20%20%20%20Sequence(SequenceBox)%0A%20%20%20%20Fail(FailBox)%0A%20%20%20%20SetKeyValue(SetKeyValueBox)%0A%20%20%20%20RemoveKeyValue(RemoveKeyValueBox)%0A%20%20%20%20Grant(GrantBox)%0A%20%20%20%20Revoke(RevokeBox)%0A%20%20%20%20ExecuteTrigger(ExecuteTriggerBox)%0A%7D%0A%0Aclass%20SetKeyValueBox%20%7B%0A%20%20%20%20object_id%3A%20EvaluatesTo~IdBox~%20%20%20%20%0A%20%20%20%20key%3A%20EvaluatesTo~Name~%20%20%20%20%0A%20%20%20%20value%3A%20EvaluatesTo~Value~%20%20%20%20%0A%7D%0A%0Aclass%20RemoveKeyValueBox%20%7B%0A%20%20%20%20object_id%3A%20EvaluatesTo~IdBox~%20%20%20%20%0A%20%20%20%20key%3A%20EvaluatesTo~Name~%20%20%20%20%0A%7D%0A%0A%0Aclass%20RegisterBox%20%7B%0A%20%20%20%20object%3A%20EvaluatesTo~RegistrableBox~%20%20%20%20%0A%7D%0A%0Aclass%20UnregisterBox%20%7B%0A%20%20%20%20object_id%3A%20EvaluatesTo~IdBox~%20%20%20%20%0A%7D%0A%0A%0Aclass%20MintBox%20%7B%0A%20%20%20%20object%3A%20EvaluatesTo~Value~%20%20%20%20%0A%20%20%20%20destination_id%3A%20EvaluatesTo~IdBox~%20%20%20%20%0A%7D%0A%0Aclass%20BurnBox%20%7B%0A%20%20%20%20object%3A%20EvaluatesTo~Value~%20%20%20%20%0A%20%20%20%20destination_id%3A%20EvaluatesTo~IdBox~%20%20%20%20%0A%7D%0A%0Aclass%20TransferBox%20%7B%0A%20%20%20%20source_id%3A%20EvaluatesTo~IdBox~%20%20%20%20%0A%20%20%20%20object%3A%20EvaluatesTo~Value~%20%20%20%20%0A%20%20%20%20destination_id%3A%20EvaluatesTo~IdBox~%20%20%20%20%0A%7D%0A%0A%0Aclass%20SequenceBox%20%7B%0A%20%20%20%20instructions%3A%20Vec~Instruction~%20%20%20%20%0A%7D%0A%0Aclass%20GrantBox%20%7B%0A%20%20%20%20object%3A%20EvaluatesTo~Value~%20%20%20%20%0A%20%20%20%20destination_id%3A%20EvaluatesTo~IdBox~%20%20%20%20%0A%7D%0A%0Aclass%20RevokeBox%20%7B%0A%20%20%20%20object%3A%20EvaluatesTo~Value~%20%20%20%20%0A%20%20%20%20destination_id%3A%20EvaluatesTo~IdBox~%20%20%20%20%0A%7D%0A%0Aclass%20ExecuteTriggerBox%20%7B%0A%20%20%20%20trigger_id%3A%20TriggerId%0A%7D%0A%0Aclass%20SetKeyValue~SetKeyValueBox~%0Aclass%20RemoveKeyValue~RemoveKeyValueBox~%0Aclass%20Register~RegisterBox~%0Aclass%20Unregister~UnregisterBox~%0Aclass%20Mint~MintBox~%0Aclass%20Burn~BurnBox~%0Aclass%20Transfer~TransferBox~%0Aclass%20Grant~GrantBox~%0Aclass%20Revoke~RevokeBox~%0A%0A%0AInstruction%20--%3E%20SetKeyValue%0AInstruction%20--%3E%20RemoveKeyValue%0AInstruction%20--%3E%20Register%0AInstruction%20--%3E%20Unregister%0AInstruction%20--%3E%20Mint%0AInstruction%20--%3E%20Burn%0AInstruction%20--%3E%20Transfer%0AInstruction%20--%3E%20Grant%0AInstruction%20--%3E%20Revoke%0AInstruction%20--%3E%20ExecuteTrigger%0AInstruction%20--%3E%20Sequence%0A%0ASetKeyValue%20..%20SetKeyValueBox%0ARemoveKeyValue%20..%20RemoveKeyValueBox%0ARegister%20..%20RegisterBox%0AUnregister%20..%20UnregisterBox%0AMint%20..%20MintBox%0ABurn%20..%20BurnBox%0ATransfer%20..%20TransferBox%0AGrant%20..%20GrantBox%0ARevoke%20..%20RevokeBox%0AExecuteTrigger%20..%20ExecuteTriggerBox%0ASequence%20..%20SequenceBox%0A%0Aclass%20If%20%7B%0A%20%20%20%20condition%3A%20EvaluatesTo~bool~%20%20%20%20%0A%20%20%20%20then%3A%20Instruction%20%20%20%20%0A%20%20%20%20otherwise%3A%20Option~Instruction~%20%20%20%20%0A%7D%0A%0Aclass%20Pair%20%7B%0A%20%20%20%20left_instruction%3A%20Instruction%20%20%20%20%0A%20%20%20%20right_instruction%3A%20Instruction%20%20%20%20%0A%7D%0A%0AInstruction%20--%3E%20If%0AInstruction%20--%3E%20Pair"})])])}const E=a(c,[["render",d]]);export{I as __pageData,E as default}; diff --git a/assets/reference_instructions.md.BQavKnbm.lean.js b/assets/reference_instructions.md.BQavKnbm.lean.js new file mode 100644 index 00000000..baf33b41 --- /dev/null +++ b/assets/reference_instructions.md.BQavKnbm.lean.js @@ -0,0 +1 @@ +import{_ as a,E as r,c as o,m as e,J as s,V as n,o as i}from"./chunks/framework.B6c1f-8R.js";const I=JSON.parse('{"title":"Iroha Special Instructions","description":"","frontmatter":{},"headers":[],"relativePath":"reference/instructions.md","filePath":"reference/instructions.md","lastUpdated":1727242778000}'),c={name:"reference/instructions.md"},A=n("",3),u={class:"details custom-block"},l=e("summary",null,"Diagram: Iroha Special Instructions",-1);function d(B,x,h,g,m,f){const t=r("MermaidRenderWrap");return i(),o("div",null,[A,e("details",u,[l,s(t,{id:"mermaid_ed2856e2f3a15f4a487319a2418ef404bba5a0dac5df0f42a043a82e9151599b85f73422c959b6bc3b0a5bbb39538fba27abaddf4e4077d492e2301eec56d75f",text:"classDiagram%0A%0Adirection%20LR%0A%0Aclass%20Instruction%20%7B%0A%20%20%20%20%3C%3Cenumeration%3E%3E%0A%20%20%20%20Register(RegisterBox)%0A%20%20%20%20Unregister(UnregisterBox)%0A%20%20%20%20Mint(MintBox)%0A%20%20%20%20Burn(BurnBox)%0A%20%20%20%20Transfer(TransferBox)%0A%20%20%20%20If(Box~If~)%0A%20%20%20%20Pair(Box~Pair~)%0A%20%20%20%20Sequence(SequenceBox)%0A%20%20%20%20Fail(FailBox)%0A%20%20%20%20SetKeyValue(SetKeyValueBox)%0A%20%20%20%20RemoveKeyValue(RemoveKeyValueBox)%0A%20%20%20%20Grant(GrantBox)%0A%20%20%20%20Revoke(RevokeBox)%0A%20%20%20%20ExecuteTrigger(ExecuteTriggerBox)%0A%7D%0A%0Aclass%20SetKeyValueBox%20%7B%0A%20%20%20%20object_id%3A%20EvaluatesTo~IdBox~%20%20%20%20%0A%20%20%20%20key%3A%20EvaluatesTo~Name~%20%20%20%20%0A%20%20%20%20value%3A%20EvaluatesTo~Value~%20%20%20%20%0A%7D%0A%0Aclass%20RemoveKeyValueBox%20%7B%0A%20%20%20%20object_id%3A%20EvaluatesTo~IdBox~%20%20%20%20%0A%20%20%20%20key%3A%20EvaluatesTo~Name~%20%20%20%20%0A%7D%0A%0A%0Aclass%20RegisterBox%20%7B%0A%20%20%20%20object%3A%20EvaluatesTo~RegistrableBox~%20%20%20%20%0A%7D%0A%0Aclass%20UnregisterBox%20%7B%0A%20%20%20%20object_id%3A%20EvaluatesTo~IdBox~%20%20%20%20%0A%7D%0A%0A%0Aclass%20MintBox%20%7B%0A%20%20%20%20object%3A%20EvaluatesTo~Value~%20%20%20%20%0A%20%20%20%20destination_id%3A%20EvaluatesTo~IdBox~%20%20%20%20%0A%7D%0A%0Aclass%20BurnBox%20%7B%0A%20%20%20%20object%3A%20EvaluatesTo~Value~%20%20%20%20%0A%20%20%20%20destination_id%3A%20EvaluatesTo~IdBox~%20%20%20%20%0A%7D%0A%0Aclass%20TransferBox%20%7B%0A%20%20%20%20source_id%3A%20EvaluatesTo~IdBox~%20%20%20%20%0A%20%20%20%20object%3A%20EvaluatesTo~Value~%20%20%20%20%0A%20%20%20%20destination_id%3A%20EvaluatesTo~IdBox~%20%20%20%20%0A%7D%0A%0A%0Aclass%20SequenceBox%20%7B%0A%20%20%20%20instructions%3A%20Vec~Instruction~%20%20%20%20%0A%7D%0A%0Aclass%20GrantBox%20%7B%0A%20%20%20%20object%3A%20EvaluatesTo~Value~%20%20%20%20%0A%20%20%20%20destination_id%3A%20EvaluatesTo~IdBox~%20%20%20%20%0A%7D%0A%0Aclass%20RevokeBox%20%7B%0A%20%20%20%20object%3A%20EvaluatesTo~Value~%20%20%20%20%0A%20%20%20%20destination_id%3A%20EvaluatesTo~IdBox~%20%20%20%20%0A%7D%0A%0Aclass%20ExecuteTriggerBox%20%7B%0A%20%20%20%20trigger_id%3A%20TriggerId%0A%7D%0A%0Aclass%20SetKeyValue~SetKeyValueBox~%0Aclass%20RemoveKeyValue~RemoveKeyValueBox~%0Aclass%20Register~RegisterBox~%0Aclass%20Unregister~UnregisterBox~%0Aclass%20Mint~MintBox~%0Aclass%20Burn~BurnBox~%0Aclass%20Transfer~TransferBox~%0Aclass%20Grant~GrantBox~%0Aclass%20Revoke~RevokeBox~%0A%0A%0AInstruction%20--%3E%20SetKeyValue%0AInstruction%20--%3E%20RemoveKeyValue%0AInstruction%20--%3E%20Register%0AInstruction%20--%3E%20Unregister%0AInstruction%20--%3E%20Mint%0AInstruction%20--%3E%20Burn%0AInstruction%20--%3E%20Transfer%0AInstruction%20--%3E%20Grant%0AInstruction%20--%3E%20Revoke%0AInstruction%20--%3E%20ExecuteTrigger%0AInstruction%20--%3E%20Sequence%0A%0ASetKeyValue%20..%20SetKeyValueBox%0ARemoveKeyValue%20..%20RemoveKeyValueBox%0ARegister%20..%20RegisterBox%0AUnregister%20..%20UnregisterBox%0AMint%20..%20MintBox%0ABurn%20..%20BurnBox%0ATransfer%20..%20TransferBox%0AGrant%20..%20GrantBox%0ARevoke%20..%20RevokeBox%0AExecuteTrigger%20..%20ExecuteTriggerBox%0ASequence%20..%20SequenceBox%0A%0Aclass%20If%20%7B%0A%20%20%20%20condition%3A%20EvaluatesTo~bool~%20%20%20%20%0A%20%20%20%20then%3A%20Instruction%20%20%20%20%0A%20%20%20%20otherwise%3A%20Option~Instruction~%20%20%20%20%0A%7D%0A%0Aclass%20Pair%20%7B%0A%20%20%20%20left_instruction%3A%20Instruction%20%20%20%20%0A%20%20%20%20right_instruction%3A%20Instruction%20%20%20%20%0A%7D%0A%0AInstruction%20--%3E%20If%0AInstruction%20--%3E%20Pair"})])])}const E=a(c,[["render",d]]);export{I as __pageData,E as default}; diff --git a/assets/reference_naming.md.Braqk8fU.js b/assets/reference_naming.md.Braqk8fU.js new file mode 100644 index 00000000..6406e81c --- /dev/null +++ b/assets/reference_naming.md.Braqk8fU.js @@ -0,0 +1 @@ +import{_ as e,c as o,o as n,V as a}from"./chunks/framework.B6c1f-8R.js";const h=JSON.parse('{"title":"Naming Conventions","description":"","frontmatter":{},"headers":[],"relativePath":"reference/naming.md","filePath":"reference/naming.md","lastUpdated":1727242778000}'),c={name:"reference/naming.md"},t=a('

Naming Conventions

When you are naming accounts, domains, or assets, you have to keep in mind the following conventions used in Iroha 2:

  1. There is a number of reserved characters that are used for specific types of constructs:

    • @ is reserved for account@domain constructs
    • # is reserved for asset#domain constructs
    • $ is reserved for trigger$domain constructs
    • % is reserved for validator%account constructs
  2. The maximum number of characters (including UTF-8 characters) a name can have is limited by two factors: [0, u32::MAX] and the currently allocated stack space.

',3),r=[t];function i(s,d,l,m,u,_){return n(),o("div",null,r)}const p=e(c,[["render",i]]);export{h as __pageData,p as default}; diff --git a/assets/reference_naming.md.Braqk8fU.lean.js b/assets/reference_naming.md.Braqk8fU.lean.js new file mode 100644 index 00000000..da880b42 --- /dev/null +++ b/assets/reference_naming.md.Braqk8fU.lean.js @@ -0,0 +1 @@ +import{_ as e,c as o,o as n,V as a}from"./chunks/framework.B6c1f-8R.js";const h=JSON.parse('{"title":"Naming Conventions","description":"","frontmatter":{},"headers":[],"relativePath":"reference/naming.md","filePath":"reference/naming.md","lastUpdated":1727242778000}'),c={name:"reference/naming.md"},t=a("",3),r=[t];function i(s,d,l,m,u,_){return n(),o("div",null,r)}const p=e(c,[["render",i]]);export{h as __pageData,p as default}; diff --git a/assets/reference_permissions.md.BVVaIEI3.js b/assets/reference_permissions.md.BVVaIEI3.js new file mode 100644 index 00000000..5f172503 --- /dev/null +++ b/assets/reference_permissions.md.BVVaIEI3.js @@ -0,0 +1,15 @@ +import{_ as s,c as i,o as t,V as e}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Permissions","description":"","frontmatter":{},"headers":[],"relativePath":"reference/permissions.md","filePath":"reference/permissions.md","lastUpdated":1727242778000}'),a={name:"reference/permissions.md"},n=e(`

Permissions

This section provides details about pre-configured permission tokens in Iroha 2. For more general information on permission tokens and permission groups (roles), refer to the Permissions chapter in Guide.

Permission Tokens

The following permission tokens are pre-configured in Iroha 2:

Permission TokenCategoryOperation
[CanUnregisterDomain]DomainAllows to unregister a domain
[CanSetKeyValueInDomain]DomainAllows to add domain's metadata key value
[CanRemoveKeyValueInDomain]DomainAllows to remove domain's metadata key value
[CanUnregisterAccount]AccountAllows to unregister an account
[CanMintUserPublicKeys]AccountAllows to add a public key to an account
[CanBurnUserPublicKeys]AccountAllows to remove a public key from an account
[CanMintUserSignatureCheckConditions]AccountAllows to set check conditions for a signature
[CanSetKeyValueInUserAccount]AccountAllows to add user's metadata key value
[CanRemoveKeyValueInUserAccount]AccountAllows to remove user's metadata key value
[CanRegisterAssetsWithDefinition]AssetAllows to register a new asset with this definition
[CanUnregisterAssetsWithDefinition]AssetAllows to unregister a new asset with this definition
[CanUnregisterUserAsset]AssetAllows to remove asset from a user
[CanMintAssetsWithDefinition]AssetAllows to mint quantity of assets with this definition
[CanBurnAssetsWithDefinition]AssetAllows to burn quantity of assets with this definition
[CanTransferAssetsWithDefinition]AssetAllows to transfer quantity of assets with this definition
[CanBurnUserAsset]AssetAllows to burn user's asset quantity
[CanTransferUserAsset]AssetAllows to transfer user's asset quantity
[CanSetKeyValueInUserAsset]AssetAllows to set key value to user's asset metadata
[CanRemoveKeyValueInUserAsset]AssetAllows to remove key value from user's asset metadata
[CanSetKeyValueInAssetDefinition]Asset DefinitionAllows to add key value to metadata for this asset definition
[CanRemoveKeyValueInAssetDefinition]Asset DefinitionAllows to remove key value from metadata for this asset definition
[CanUnregisterAssetDefinition]Asset DefinitionAllows to unregister this asset definition

INFO

The way permissions work in Iroha 2 is subject to change. Only an owner of the subject can grant permissions for the subject.

By default, all assets and accounts defined in the genesis block configuration file are created by genesis@genesis account. This means that alice@wonderland is not the owner of rose#wonderland and cannot grant permission for rose#wonderland.

To avoid this you can:

  1. Edit the genesis.json file to only include the creation of alice@wonderland, and then redeploy Iroha 2.
  2. Create a subject (e.g., an asset definition) on behalf of alice@wonderland, and then give another account the permission to manage this subject.

General example

With this example, the owner-account can give permission for its subject to another account. The example is based on the following pre-conditions: The subject is created by the owner-account The recipient account is created

rust
// Define the asset definition owner
+let asset_definition_owner = AccountId::from_str("alice@wonderland").unwrap();
+// Define the asset definition id which was created by the owner
+let asset_definition_id = AssetDefinitionId::from_str("coolAsset#wonderland").unwrap();
+// Define the account which we want to give the permission
+let recipient_account = AccountId::from_str("actor@wonderland").unwrap();
+// Create a token that we chose. And define its structure according to \`iroha_executor\\smart_contract\\executor\\src\\default.rs\`
+let can_mint_asset_with_definition_token = PermissionToken::new(
+"CanMintAssetsWithDefinition".parse().unwrap(),
+&json!({ "asset_definition_id": asset_definition_id }),
+);
+// Create a permission expression (Grant\\Revoke)
+let permission_expression = GrantExpr::new(can_mint_asset_with_definition_token, recipients_account);
+// Submit the transaction with the permission expression
+iroha_client.submit_blocking(permission_expression).unwrap();
`,9),d=[n];function o(r,h,l,p,k,c){return t(),i("div",null,d)}const y=s(a,[["render",o]]);export{g as __pageData,y as default}; diff --git a/assets/reference_permissions.md.BVVaIEI3.lean.js b/assets/reference_permissions.md.BVVaIEI3.lean.js new file mode 100644 index 00000000..cd7964a3 --- /dev/null +++ b/assets/reference_permissions.md.BVVaIEI3.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as t,V as e}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Permissions","description":"","frontmatter":{},"headers":[],"relativePath":"reference/permissions.md","filePath":"reference/permissions.md","lastUpdated":1727242778000}'),a={name:"reference/permissions.md"},n=e("",9),d=[n];function o(r,h,l,p,k,c){return t(),i("div",null,d)}const y=s(a,[["render",o]]);export{g as __pageData,y as default}; diff --git a/assets/reference_queries.md.BS7G0mCP.js b/assets/reference_queries.md.BS7G0mCP.js new file mode 100644 index 00000000..04adede4 --- /dev/null +++ b/assets/reference_queries.md.BS7G0mCP.js @@ -0,0 +1,15 @@ +import{_ as n,E as o,c as l,m as e,J as s,V as i,a as t,o as r}from"./chunks/framework.B6c1f-8R.js";const Z=JSON.parse('{"title":"Queries","description":"","frontmatter":{},"headers":[],"relativePath":"reference/queries.md","filePath":"reference/queries.md","lastUpdated":1727242778000}'),d={name:"reference/queries.md"},c=i('

Queries

In the following section we mirror the module structure of the queries and present to you what they do. You can learn

INFO

The results of queries can be sorted, paginated and filtered peer-side all at once.

Conventions

Expand to learn about the conventions used in the descriptions below
  1. In the Details section of each query, we use gets, returns, searches with the following precise meanings:

    NotationMeaning
    getsThe query already has the data readily available and the data is trivial. Use these queries at will.
    returns or findsThe query has the data readily available, just as with gets, but the data is not trivial. You can still use these queries, but be mindful of the performance impact.
    searchesFor this query, the data must be actively collected and neither the return type nor the collection process is cheap. Use with great care.
  2. The queries are provided with just one data type as input, and parameterised by the type of the output.

  3. For the FindZByXAndY queries, their descriptions have a Parameters and a Returns section. The parameters can either be single or multiple types, while the output is almost always either one type, or a Vec<Type> kind of construction:

    NotationMeaning
    Parameters: (X, Y)In Rust source code, you need to construct the query as let query = FindZByXAndY::new(x: X, y: Y);, where x and y are variables of type X and Y respectively. In the reference below we provide you with information about each type.
    Returns: Vec<Z>The return value is a collection of more than one element of type Z. Depending on the SDK implementation this can be a type native to the language (e.g. JavaScript) or a thin wrapper around the Rust Vec structure.

Role

An optional feature. By default, it is present on all Iroha 2 deployments when they're compiled in the private blockchain configuration.

You can learn more about roles in a dedicated section.

FindAllRoles

',9),h=e("li",null,[e("p",null,[e("strong",null,"Returns"),t(": "),e("code",null,"Vec")])],-1),u=e("p",null,[e("strong",null,"Details"),t(": Returns all roles registered as "),e("em",null,"global"),t(" (as opposed to "),e("em",null,"domain-scoped"),t(") in the blockchain.")],-1),p=i('

FindAllRoleIds

  • Returns: Vec<Roles>

  • Details: Returns IDs of all the roles registered as global (as opposed to domain-scoped) in the blockchain.

    Note that it does not return its values, which contain permission tokens, only IDs.

FindRoleByRoleId

  • Parameters: RoleId

  • Returns: Vec<Roles>

  • Details: Returns the role that has the provided role ID.

    For example, given the name of the role admin, it will return all of the admin-level permission tokens.

FindRolesByAccountId

  • Parameters: AccountId

  • Returns: Vec<RoleId>

  • Details: Returns all of the role IDs that are attached to the given account.

    Note that unlike FindAllRoles, it does not return the roles themselves.

Permission

A semi-optional feature. You have permissions in both public and private blockchains but the use cases are different:

  • In a public blockchain, most accounts have the same common-sense permissions.
  • In a private blockchain, most accounts are assumed not to be able to do anything outside of their own account or domain unless explicitly granted said permission.

We talk about permissions in more detail in a dedicated chapter.

FindAllPermissionTokenDefinitions

  • Returns: Vec<PermissionTokenDefinition>

  • Details: Finds all registered permission token definitions.

FindPermissionTokensByAccountId

  • Parameters: AccountId

  • Returns: Vec<PermissionToken>

  • Details: Returns all of the permission tokens granted to the specified account.

Account

Most queries in Iroha pertain to accounts. At the moment this is the most diverse set of queries.

FindAllAccounts

',17),g=e("li",null,[e("p",null,[e("strong",null,"Returns"),t(": "),e("code",null,"Vec")])],-1),m=e("p",null,[e("strong",null,"Details"),t(": Finds all accounts registered globally in the blockchain.")],-1),k=i('

FindAccountById

  • Parameters: AccountId

  • Returns: Account

  • Details: Returns the full account information corresponding to the given AccountId.

FindAccountKeyValueByIdAndKey

  • Parameters: (AccountId, Name)

  • Returns: Value

  • Details: Returns the value keyed by the provided Name for the given account.

    This is done by querying the metadata attached to the given account.

FindAccountsByName

  • Parameters: Name

  • Returns: Vec<Account>

  • Details: Returns all of the accounts that have the given Name.

    This is particularly useful if you remember the name of the account, but do not, for example, recall the domain name in which it was registered.

FindAccountsByDomainId

',7),y=e("li",null,[e("p",null,[e("strong",null,"Parameters"),t(": "),e("code",null,"DomainId")])],-1),f=e("li",null,[e("p",null,[e("strong",null,"Returns"),t(": "),e("code",null,"Vec")])],-1),b=e("p",null,[e("strong",null,"Details"),t(": Returns all accounts that belong to a specific domain.")],-1),_=e("p",null,[t("Note that this returns the full accounts and not the "),e("code",null,"AccountId"),t(" collection.")],-1),A=i('

FindAccountsWithAsset

  • Parameters: AccountId

  • Returns: Vec<Account>

  • Details: Returns all accounts that have the given asset.

Asset

Assets include simple numbers, but also a special type of key-to-value map that is used as a secure data storage for privileged information.

FindAllAssets

',5),q=e("li",null,[e("p",null,[e("strong",null,"Returns"),t(": "),e("code",null,"Vec")])],-1),F=e("p",null,[e("strong",null,"Details"),t(": Returns all known assets by value.")],-1),I=e("div",{class:"info custom-block"},[e("p",{class:"custom-block-title"},"INFO"),e("p",null,[t("You should note that this is not the same as "),e("code",null,"AssetDefinition"),t(". If you have one asset called e.g. "),e("code",null,"tea#wonderland"),t(" that belongs to every account on the blockchain, you will receive the aggregated value across all accounts, but not the information such as the type of the asset.")])],-1),T=e("h3",{id:"findallassetdefinitions",tabindex:"-1"},[e("code",null,"FindAllAssetDefinitions"),t(),e("a",{class:"header-anchor",href:"#findallassetdefinitions","aria-label":'Permalink to "`FindAllAssetDefinitions`"'},"​")],-1),P=e("li",null,[e("p",null,[e("strong",null,"Returns"),t(": "),e("code",null,"Vec")])],-1),v=e("p",null,[e("strong",null,"Details"),t(": Returns all known asset definitions by value.")],-1),D=e("div",{class:"tip custom-block"},[e("p",{class:"custom-block-title"},"TIP"),e("p",null,"To reduce the load on the network, we store the definition of an asset separate from its instances. So if you want to know if an asset is mintable or what type is stored in it, you need to query the asset definition, rather than the asset itself.")],-1),R=i('

FindAssetById

  • Parameters: AssetId

  • Returns: Asset

  • Details: Returns the aggregated data about the asset usage across the network.

FindAssetsByName

  • Parameters: Name

  • Returns: Vec<Asset>

  • Details: Searches the network for all assets that match the given name.

FindAssetsByAccountId

  • Parameters: AccountId

  • Returns: Vec<Asset>

  • Details: Returns all of the assets that belong to a given account.

FindAssetsByAssetDefinitionId

  • Parameters: AssetDefinitionId

  • Returns: Vec<Asset>

  • Details: Searches for all of the assets that have the given definition ID.

',8),E=i('

FindAssetsByDomainId

  • Parameters: DomainId

  • Returns: Vec<Asset>

  • Details: Returns all assets that are registered in the given domain.

',2),B=i('

FindAssetsByDomainIdAndAssetDefinitionId

  • Parameters: (DomainId, AssetDefinitionId)

  • Returns: Vec<Asset>

  • Details: Searches the domain for assets that have the given definition ID.

FindAssetQuantityById

  • Parameters: AssetId

  • Returns: NumericValue

  • Details: Returns the asset quantity.

    Note that this query assumes that the asset given by the identifier is of type AssetValue::Quantity.

    WARNING

    This query can fail.

FindAssetKeyValueByIdAndKey

  • Parameters: (AssetId, Name)

  • Returns: Value

  • Details: Gets the value keyed by the given name in the metadata of the asset corresponding to the given identifier.

FindAssetDefinitionKeyValueByIdAndKey

  • Parameters: (AssetDefinitionId, Name)

  • Returns: Value

  • Details: Gets the value keyed by the given name in the metadata of the asset definition corresponding to the given identifier.

FindTotalAssetQuantityByAssetDefinitionId

  • Parameters: AssetDefinitionId

  • Returns: NumericValue

  • Details: Finds the total asset quantity for the given asset definition. For the Store asset value, finds the sum of asset quantities through all accounts that hold the specified asset.

Block

FindAllBlocks

  • Returns: Vec<VersionedCommittedBlock>
  • Details: Returns all blocks in the blockchain.

FindAllBlockHeaders

  • Returns: Vec<BlockHeader>
  • Details: Returns all block headers for blocks in the blockchain.

FindBlockHeaderByHash

  • Parameters: Hash
  • Returns: BlockHeader
  • Details: Gets the block header that matches the hash that was provided.

Domain

The domain is the basic unit of organisation in an Iroha blockchain. Accounts and assets must be registered inside a domain, triggers are usually scoped by domain, and most queries have the domain as a possible input.

FindAllDomains

  • Returns: Vec<Domain>

  • Details: Returns all of the known registered domains.

    WARNING

    This query returns the full contents of the world state view as of execution. This query should be used sparingly and for debugging purposes only.

FindDomainById

',22),V=e("li",null,[e("p",null,[e("strong",null,"Parameters"),t(": "),e("code",null,"DomainId")])],-1),x=e("li",null,[e("p",null,[e("strong",null,"Returns"),t(": "),e("code",null,"Domain")])],-1),w=e("p",null,[e("strong",null,"Details"),t(": Gets the domain corresponding to the given identifier.")],-1),C=i(`

FindDomainKeyValueByIdAndKey

  • Parameters: (DomainId, Name)

  • Returns: Value

  • Details: Returns the value keyed by the given name in the domain corresponding to the given identifier.

Peer

A peer is the basic unit of storage and validation. In common parlance we may conflate the node and the peer binary running on the node, but in this case we specifically mean the peer binary as a server with its specific configuration.

FindAllPeers

  • Returns: Vec<Peer>

  • Details: Returns all known peers identified by their key and accompanied by the address of the API endpoint of each.

FindAllParameters

  • Returns: Vec<Parameter>

    rust
    pub enum Parameter {
    +    /// Maximum amount of Faulty Peers in the system.
    +    MaximumFaultyPeersAmount(u32),
    +    /// Maximum time for a leader to create a block.
    +    BlockTime(u128),
    +    /// Maximum time for a proxy tail to send commit message.
    +    CommitTime(u128),
    +    /// Time to wait for a transaction Receipt.
    +    TransactionReceiptTime(u128),
    +}
  • Details: Returns the parameters used by all peers in the network.

    This is useful for debugging if any of the peers are incorrectly configured and causing view changes.

Transaction

It is often necessary to query the state of specific transactions, especially for use in blockchain explorers and for user-facing applications.

FindTransactionsByAccountId

`,11),N=i(`
  • Parameters: AccountId

  • Returns: Vec<TransactionValue>

    rust
    pub enum TransactionValue {
    +    /// Committed transaction
    +    Transaction(Box<VersionedSignedTransaction>),
    +    /// Rejected transaction with reason of rejection
    +    RejectedTransaction(Box<VersionedRejectedTransaction>),
    +}
  • `,2),S=e("p",null,[e("strong",null,"Details"),t(": Returns the full set of transactions that an account has submitted throughout the existence of the blockchain.")],-1),K=i('

    FindTransactionByHash

    • Parameters: Hash

    • Returns: TransactionValue

    • Details: Returns the transaction by hash.

    Trigger

    Iroha is an event-driven architecture. Every modification of the world state emits a corresponding event that can be captured by appropriate event listeners called filters.

    INFO

    Note that Iroha shut downs all listeners on panic.

    FindAllActiveTriggerIds

    • Returns: Vec<TriggerId>

    • Details: Finds all currently active triggers, that is, triggers that have not expired at the time of the query.

    ',7),H=i('

    FindTriggerById

    • Parameters: TriggerId

    • Returns: Trigger

    • Details: Finds the trigger with the given ID.

    FindTriggerKeyValueByIdAndKey

    • Parameters: (TriggerId, Name)

    • Returns: Trigger

    • Details: Finds the value corresponding to the key in the metadata of the trigger with the given ID.

    FindTriggersByDomainId

    • Parameters: DomainId

    • Returns: Vec<Trigger>

    • Details: Finds all domain triggers for the given domain ID.

    ',6);function Q(Y,M,W,j,G,X){const a=o("WarningFatQuery");return r(),l("div",null,[c,e("ul",null,[h,e("li",null,[u,s(a)])]),p,e("ul",null,[g,e("li",null,[m,s(a)])]),k,e("ul",null,[y,f,e("li",null,[b,_,s(a)])]),A,e("ul",null,[q,e("li",null,[F,s(a),I])]),T,e("ul",null,[P,e("li",null,[v,s(a),D])]),R,s(a),E,s(a),B,e("ul",null,[V,x,e("li",null,[w,s(a)])]),C,e("ul",null,[N,e("li",null,[S,s(a)])]),K,s(a),H])}const $=n(d,[["render",Q]]);export{Z as __pageData,$ as default}; diff --git a/assets/reference_queries.md.BS7G0mCP.lean.js b/assets/reference_queries.md.BS7G0mCP.lean.js new file mode 100644 index 00000000..a17ca69a --- /dev/null +++ b/assets/reference_queries.md.BS7G0mCP.lean.js @@ -0,0 +1 @@ +import{_ as n,E as o,c as l,m as e,J as s,V as i,a as t,o as r}from"./chunks/framework.B6c1f-8R.js";const Z=JSON.parse('{"title":"Queries","description":"","frontmatter":{},"headers":[],"relativePath":"reference/queries.md","filePath":"reference/queries.md","lastUpdated":1727242778000}'),d={name:"reference/queries.md"},c=i("",9),h=e("li",null,[e("p",null,[e("strong",null,"Returns"),t(": "),e("code",null,"Vec")])],-1),u=e("p",null,[e("strong",null,"Details"),t(": Returns all roles registered as "),e("em",null,"global"),t(" (as opposed to "),e("em",null,"domain-scoped"),t(") in the blockchain.")],-1),p=i("",17),g=e("li",null,[e("p",null,[e("strong",null,"Returns"),t(": "),e("code",null,"Vec")])],-1),m=e("p",null,[e("strong",null,"Details"),t(": Finds all accounts registered globally in the blockchain.")],-1),k=i("",7),y=e("li",null,[e("p",null,[e("strong",null,"Parameters"),t(": "),e("code",null,"DomainId")])],-1),f=e("li",null,[e("p",null,[e("strong",null,"Returns"),t(": "),e("code",null,"Vec")])],-1),b=e("p",null,[e("strong",null,"Details"),t(": Returns all accounts that belong to a specific domain.")],-1),_=e("p",null,[t("Note that this returns the full accounts and not the "),e("code",null,"AccountId"),t(" collection.")],-1),A=i("",5),q=e("li",null,[e("p",null,[e("strong",null,"Returns"),t(": "),e("code",null,"Vec")])],-1),F=e("p",null,[e("strong",null,"Details"),t(": Returns all known assets by value.")],-1),I=e("div",{class:"info custom-block"},[e("p",{class:"custom-block-title"},"INFO"),e("p",null,[t("You should note that this is not the same as "),e("code",null,"AssetDefinition"),t(". If you have one asset called e.g. "),e("code",null,"tea#wonderland"),t(" that belongs to every account on the blockchain, you will receive the aggregated value across all accounts, but not the information such as the type of the asset.")])],-1),T=e("h3",{id:"findallassetdefinitions",tabindex:"-1"},[e("code",null,"FindAllAssetDefinitions"),t(),e("a",{class:"header-anchor",href:"#findallassetdefinitions","aria-label":'Permalink to "`FindAllAssetDefinitions`"'},"​")],-1),P=e("li",null,[e("p",null,[e("strong",null,"Returns"),t(": "),e("code",null,"Vec")])],-1),v=e("p",null,[e("strong",null,"Details"),t(": Returns all known asset definitions by value.")],-1),D=e("div",{class:"tip custom-block"},[e("p",{class:"custom-block-title"},"TIP"),e("p",null,"To reduce the load on the network, we store the definition of an asset separate from its instances. So if you want to know if an asset is mintable or what type is stored in it, you need to query the asset definition, rather than the asset itself.")],-1),R=i("",8),E=i("",2),B=i("",22),V=e("li",null,[e("p",null,[e("strong",null,"Parameters"),t(": "),e("code",null,"DomainId")])],-1),x=e("li",null,[e("p",null,[e("strong",null,"Returns"),t(": "),e("code",null,"Domain")])],-1),w=e("p",null,[e("strong",null,"Details"),t(": Gets the domain corresponding to the given identifier.")],-1),C=i("",11),N=i("",2),S=e("p",null,[e("strong",null,"Details"),t(": Returns the full set of transactions that an account has submitted throughout the existence of the blockchain.")],-1),K=i("",7),H=i("",6);function Q(Y,M,W,j,G,X){const a=o("WarningFatQuery");return r(),l("div",null,[c,e("ul",null,[h,e("li",null,[u,s(a)])]),p,e("ul",null,[g,e("li",null,[m,s(a)])]),k,e("ul",null,[y,f,e("li",null,[b,_,s(a)])]),A,e("ul",null,[q,e("li",null,[F,s(a),I])]),T,e("ul",null,[P,e("li",null,[v,s(a),D])]),R,s(a),E,s(a),B,e("ul",null,[V,x,e("li",null,[w,s(a)])]),C,e("ul",null,[N,e("li",null,[S,s(a)])]),K,s(a),H])}const $=n(d,[["render",Q]]);export{Z as __pageData,$ as default}; diff --git a/assets/reference_torii-endpoints.md.C7pQt57Z.js b/assets/reference_torii-endpoints.md.C7pQt57Z.js new file mode 100644 index 00000000..0f7d0abd --- /dev/null +++ b/assets/reference_torii-endpoints.md.C7pQt57Z.js @@ -0,0 +1,93 @@ +import{_ as s,c as e,o as t,V as i}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Torii Endpoints","description":"","frontmatter":{},"headers":[],"relativePath":"reference/torii-endpoints.md","filePath":"reference/torii-endpoints.md","lastUpdated":1727242778000}'),a={name:"reference/torii-endpoints.md"},n=i(`

    Torii Endpoints

    About Parity SCALE Codec

    Messages for certain TORII operations are encoded with the Parity SCALE Codec (SCALE) commonly used with the Parity Substrate blockchain framework, and other blockchains utilizing it.

    For more information on SCALE, see the Substrate Documentation: Type encoding (SCALE) article and its official GitHub repository.

    Torii (Japanese: 鳥居 — Shinto shrine gateway) is the Iroha 2 module in charge of handling HTTP and WebSocket requests. It is the main API for interacting with Iroha 2. Such interactions include sending transactions, making queries, listening for blocks stream, etc.

    API Version

    INFO

    This operation requires the specific Iroha node being requested to be compiled with the telemetry feature enabled.

    • Protocol: HTTP
    • Method: GET
    • Encoding: JSON
    • Endpoint: /api_version

    Requests

    A GET request to the endpoint.

    Responses

    CodeResponseDescription
    200OKReturns the current version of the API used by the requested Iroha 2 node as a JSON string.

    Example:

    json
    "1"

    INFO

    The API version is retrieved from and is the same as the version of the genesis block, which means that at least a minimal subnet of four peers must be running, and the genesis block must already be submitted at the time of the request.

    Blocks Stream

    • Protocols: HTTP upgraded to WebSocket
    • Encoding: SCALE
    • Endpoint: /block/stream

    Handshake

    Since the /block/stream endpoint handles continuous two-way data exchange, a WebSocket handshake between the client and server must first be performed to initiate communication with this endpoint.

    Data Exchange

    After establishing a WebSocket connection, the client must send a BlockSubscriptionRequest request with the starting block number provided (i.e., the height value). Then, upon sending the confirmation and BlockMessage messages, the server starts streaming all of the blocks, beginning with the block specified with height up to the most recent one, and then continues to stream new blocks as they are added to the blockchain.

    Configuration / Retrieve

    • Protocol: HTTP
    • Method: GET
    • Encoding: JSON
    • Endpoint: /configuration

    Requests

    A GET request to the endpoint.

    Responses

    CodeResponseDescription
    200OKReturns a subset of configuration parameters serialized into JSON format.

    Example:

    json
    {
    +  "logger": {
    +    "level": "TRACE"
    +  }
    +}

    INFO

    The subset of configuration parameters returned by this operation is equal to the one accepted by the Configuration / Update operation, i.e., it only contains the logger.level parameter as of now.

    Configuration / Update

    • Protocol: HTTP
    • Method: POST
    • Encoding: JSON
    • Endpoint: /configuration

    Requests

    This endpoint expects a subset of configuration parameters serialized into JSON format. Currently, it only supports dynamic updating of the logger.level parameter.

    INFO

    The list of all accepted values is currently unavailable and will be a part of the configuration reference that is still WIP.

    Until then, to get assistance with the acceptable values and their definitions, consult Receive Support for ways to contact us.

    The progress on the configuration reference can be tracked in the following GitHub issue:
    iroha-2-docs > Issue #392: Tracking issue for Configuration Reference as per RFC.

    Example:

    json
    {
    +  "logger": {
    +    "level": "DEBUG"
    +  }
    +}

    Responses

    CodeResponseDescription
    202AcceptedThe request to update the configuration is accepted and is due to be processed.

    Guarantees

    A successful configuration update does not guarantee that the configuration is indeed updated. While a follow-up Configuration / Retrieve request will return updated values, the actual update is performed asynchronously.

    Events

    • Protocols: HTTP upgraded to WebSocket
    • Encoding: SCALE
    • Endpoint: /events

    Transaction Events

    The status of a transaction event can be one of the following:

    • Validating — The transaction has been successfully submitted and is currently being validated by peers.
    • Committed — The transaction has been successfully validated and is committed to the blockchain.
    • Rejected — The transaction has been rejected by at least one peer and is not committed to the blockchain.

    All transactions are designated with the Validating status upon creation, which later proceeds to either Committed or Rejected. However, due to the distributed nature of the network, some peers might receive events out of order (e.g., Committed before Validating).

    Some peers in the network may be offline for the validation round. If a client connects to them while they are offline, the peers might not respond with the Validating status. But when the offline peers come back online they will automatically synchronize the blocks. These peers are then guaranteed to respond with either Committed or Rejected status, depending on the information found in the block.

    Handshake

    Since the /events endpoint handles continuous two-way data exchange, a WebSocket handshake between the client and server must first be performed to initiate communication with this endpoint.

    Data Exchange

    After establishing a WebSocket connection, the client must send an EventSubscriptionRequest request, after which the server sends an EventMessage response.

    Health

    • Protocol: HTTP
    • Method: GET
    • Encoding: JSON
    • Endpoint: /health

    Requests

    A GET request to the endpoint.

    Responses

    CodeResponseDescription
    200Health StatusReturns the current status of the peer submitting the request.

    Example:

    json
    "Healthy"

    Metrics

    INFO

    This operation requires the Iroha 2 network to be established with the telemetry feature enabled.

    • Protocol: HTTP
    • Method: GET
    • Encoding: JSON
    • Endpoint: /metrics

    Responses

    CodeResponseDescription
    200MetricsReturns a report on 8 out of 10 Prometheus metrics.

    Example:

    Example 200 Metrics response
    bash
    # HELP accounts User accounts registered at this time
    +# TYPE accounts gauge
    +accounts{domain="genesis"} 1
    +accounts{domain="wonderland"} 1
    +# HELP block_height Current block height
    +# TYPE block_height counter
    +block_height 1
    +# HELP connected_peers Total number of currently connected peers
    +# TYPE connected_peers gauge
    +connected_peers 0
    +# HELP domains Total number of domains
    +# TYPE domains gauge
    +domains 2
    +# HELP tx_amount average amount involved in a transaction on this peer
    +# TYPE tx_amount histogram
    +tx_amount_bucket{le="0.005"} 0
    +tx_amount_bucket{le="0.01"} 0
    +tx_amount_bucket{le="0.025"} 0
    +tx_amount_bucket{le="0.05"} 0
    +tx_amount_bucket{le="0.1"} 0
    +tx_amount_bucket{le="0.25"} 0
    +tx_amount_bucket{le="0.5"} 0
    +tx_amount_bucket{le="1"} 0
    +tx_amount_bucket{le="2.5"} 0
    +tx_amount_bucket{le="5"} 0
    +tx_amount_bucket{le="10"} 0
    +tx_amount_bucket{le="+Inf"} 2
    +tx_amount_sum 26
    +tx_amount_count 2
    +# HELP txs Transactions committed
    +# TYPE txs counter
    +txs{type="accepted"} 1
    +txs{type="rejected"} 0
    +txs{type="total"} 1
    +# HELP uptime_since_genesis_ms Network up-time, from creation of the genesis block
    +# TYPE uptime_since_genesis_ms gauge
    +uptime_since_genesis_ms 54572974
    +# HELP view_changes Number of view_changes in the current round
    +# TYPE view_changes gauge
    +view_changes 0

    INFO

    To learn more about metrics, see Metrics.

    Pending Transactions

    • Protocol: HTTP
    • Method: GET
    • Encoding: SCALE
    • Endpoint: /pending_transactions

    Requests

    A GET request to the endpoint.

    Responses

    CodeResponseDescription
    200OKReturns a list of pending transactions as SignedTransaction objects encoded with SCALE; must be decoded by the client.

    Query

    • Protocol: HTTP
    • Method: POST
    • Encoding: SCALE
    • Endpoint: /query

    Requests

    This endpoint expects requests with two shapes:

    Start a query:

    OR

    Get the next batch of a previously started query:

    • Parameters:
      • cursor - specifies a cursor previously returned as part of query response

    Request

    Responses

    CodeResponseBodyDescription
    200SuccessBatchedResponse<QueryOutputBox>Successful query request
    400Conversion ErrorQueryExecutionFail::Conversion(String)Invalid asset query for the actual asset type
    400Cursor ErrorQueryExecutionFail::UnknownCursorAn invalid cursor was provided in the batch request
    400FetchSizeTooBig ErrorQueryExecutionFail::FetchSizeTooBigFetch size specified in the query request is too large
    400InvalidSingularParameters ErrorQueryExecutionFail::InvalidSingularParametersSpecified query parameters are not applicable to the (singular) query type
    401Signature ErrorQueryExecutionFail::Signature(String)The signature on the query is incorrect
    403Permission ErrorQueryExecutionFail::Permission(String)The user does not have permission to execute this query
    404Find ErrorQueryExecutionFail::Find(FindError)The queried object was not found

    INFO

    The 200 Success response returns results that are ordered by id, which use Rust's PartialOrd and Ord traits.

    Account Not Found 404

    Whether each prerequisite object was found and FindError:

    DomainAccountFindError
    N-FindError::Domain(DomainId)
    YNFindError::Account(AccountId)

    Asset Not Found 404

    Whether each prerequisite object was found and FindError:

    DomainAccountAsset DefinitionAssetFindError
    N---FindError::Domain(DomainId)
    YN--FindError::Account(AccountId)
    Y-N-FindError::AssetDefinition(AssetDefinitionId)
    YYYNFindError::Asset(AssetId)

    Schema

    INFO

    This operation requires the Iroha 2 network to be established with the schema feature enabled.

    • Protocol: HTTP
    • Method: GET
    • Encoding: JSON
    • Endpoint: /schema

    Requests

    A GET request to the endpoint.

    Responses

    CodeResponseDescription
    200OKReturns the Rust data structures and types of the entire Data Model Schema as JSON objects.

    Status

    INFO

    This operation requires the Iroha 2 network to be established with the telemetry feature enabled.

    • Protocol: HTTP
    • Method: GET
    • Encoding: JSON or SCALE
    • Endpoint: /status

    Requests

    A GET request to the endpoint.

    This endpoint also accepts the following:

    • Header: Specifies the encoding of the retrieved data.
      Can be set to one of the following:
      • Accept: application/x-parity-scale — the retrieved data is encoded with SCALE.
      • Accept: application/json — the retrieved data is encoded with JSON.

    If no header is specified in the request, the Accept: application/json header is used by default.

    Responses

    CodeResponseDescription
    200Iroha StatusReturns the Iroha network status report encoded as specified in the header of the request.

    The response body has the following structure:

    rust
    struct Status {
    +    /// Number of connected peers, except for the reporting peer itself
    +    peers: u64,
    +    /// Number of committed blocks
    +    blocks: u64,
    +    /// Number of accepted transactions
    +    txs_accepted: u64,
    +    /// Number of rejected transactions
    +    txs_rejected: u64,
    +    /// Uptime since genesis block creation
    +    uptime: Uptime,
    +    /// Number of view changes in the current round
    +    view_changes: u64,
    +    /// Number of the transactions in the queue
    +    queue_size: u64,
    +}
    +
    +struct Uptime {
    +    secs: u64,
    +    nanos: u32
    +}
    Examples

    The following examples represent the same data:

    json
    {
    +  "peers": 4,
    +  "blocks": 5,
    +  "txs_accepted": 31,
    +  "txs_rejected": 3,
    +  "uptime": {
    +    "secs": 5,
    +    "nanos": 937000000
    +  },
    +  "view_changes": 2,
    +  "queue_size": 18
    +}
    10 14 7C 0C 14 40 7C D9 37 08 48

    JSON Precision Lost

    Almost all fields in the Status structure are 64-bit integers, and they are encoded in JSON as-is. Since native JSON's number type according to the specification effectively is f64, the precision might be lost on deserialization, for example, in JavaScript's JSON.parse.

    For more details, see the related GitHub issue.

    Compact Form in SCALE

    Fields with u64 type are serialized in the Compact form.

    Sub-routing

    It is also possible to retrieve the data of a specific struct group or variable within it by adding their path to the endpoint address. The sub-routed values are only returned in the JSON format.

    Examples:

    json
    {
    +  "peers": 4,
    +  "blocks": 5,
    +  "txs_accepted": 31,
    +  "txs_rejected": 3,
    +  "uptime": {
    +    "secs": 5,
    +    "nanos": 937000000
    +  },
    +  "view_changes": 2,
    +  "queue_size": 18
    +}
    json
    4
    json
    {
    +  "secs": 5,
    +  "nanos": 937000000
    +}
    json
    5

    Transaction

    • Protocol: HTTP
    • Method: POST
    • Encoding: SCALE
    • Endpoint: /transaction

    Requests

    This endpoint expects the following data:

    Responses

    CodeResponseDescription
    200Transaction AcceptedTransaction has been accepted, but is not yet guaranteed to have passed consensus.
    400Transaction Rejected (Malformed)Transaction is rejected due to being malformed.
    401Transaction Rejected (Improperly signed)Transaction is rejected due to being improperly signed.
    `,123),o=[n];function l(r,h,d,p,c,k){return t(),e("div",null,o)}const E=s(a,[["render",l]]);export{g as __pageData,E as default}; diff --git a/assets/reference_torii-endpoints.md.C7pQt57Z.lean.js b/assets/reference_torii-endpoints.md.C7pQt57Z.lean.js new file mode 100644 index 00000000..8f67f16c --- /dev/null +++ b/assets/reference_torii-endpoints.md.C7pQt57Z.lean.js @@ -0,0 +1 @@ +import{_ as s,c as e,o as t,V as i}from"./chunks/framework.B6c1f-8R.js";const g=JSON.parse('{"title":"Torii Endpoints","description":"","frontmatter":{},"headers":[],"relativePath":"reference/torii-endpoints.md","filePath":"reference/torii-endpoints.md","lastUpdated":1727242778000}'),a={name:"reference/torii-endpoints.md"},n=i("",123),o=[n];function l(r,h,d,p,c,k){return t(),e("div",null,o)}const E=s(a,[["render",l]]);export{g as __pageData,E as default}; diff --git a/assets/sample-vue-app.DgCFT7gr.gif b/assets/sample-vue-app.DgCFT7gr.gif new file mode 100644 index 00000000..05578e52 Binary files /dev/null and b/assets/sample-vue-app.DgCFT7gr.gif differ diff --git a/assets/style.D9TtTyLU.css b/assets/style.D9TtTyLU.css new file mode 100644 index 00000000..b31f007e --- /dev/null +++ b/assets/style.D9TtTyLU.css @@ -0,0 +1 @@ +.domains-example-scope[data-v-099be746] .aliceblue rect{stroke:#3b82f6cc!important;stroke-width:4!important}.domains-example-scope[data-v-099be746] .pink rect{stroke:#f63264cc!important;stroke-width:4!important}svg[data-status=ok][data-v-dad59778]{color:var(--vp-c-green-1)}svg[data-status=failed][data-v-dad59778]{color:var(--vp-c-red-1)}svg[data-status=no-data][data-v-dad59778]{color:var(--vp-c-yellow-1)}.inline-icon[data-v-dad59778]{display:inline;vertical-align:middle}.border[data-v-ba4f590a]{border-color:var(--vp-c-border)}td.status-cell[data-v-ba4f590a]{font-size:1.3em;padding:0}td.status-cell svg[data-v-ba4f590a]{margin-left:auto;margin-right:auto}.v-btn-primary{border-radius:.5rem;background-color:var(--vp-c-brand-2);padding:.375rem .75rem;font-size:.875rem;line-height:1.25rem;--un-text-opacity:1;color:rgb(255 255 255 / var(--un-text-opacity));font-weight:500;--un-shadow:0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12);box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow)}.dark .v-btn-primary{background-color:var(--vp-c-brand-3)}.v-btn-primary:not(:disabled):hover{background-color:var(--vp-c-brand-1)}.dark .v-btn-primary:not(:disabled):hover{background-color:var(--vp-c-brand-2)}.v-btn-primary:disabled{cursor:not-allowed;opacity:.5;--un-shadow:0 0 var(--un-shadow-color, rgb(0 0 0 / 0));box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow)}.feedback-card[data-v-701191ba]{background:var(--vp-c-bg);border-radius:8px;width:calc(100vw - 32px);max-width:420px;max-height:calc(100vh - 32px);border:1px solid var(--vp-c-border)}.feedback-card_header[data-v-701191ba]{border-bottom:1px solid var(--vp-c-border);padding:16px}.feedback-card_title[data-v-701191ba]{font-size:16px;font-weight:bolder}.feedback-card_check[data-v-701191ba]{color:var(--vp-custom-block-tip-text)}textarea[data-v-701191ba],input[data-v-701191ba]{font-family:var(--vp-font-family-base);background:var(--vp-c-bg-soft);font-size:14px;border-radius:4px;padding:16px;width:100%}textarea[data-v-701191ba]::placeholder,input[data-v-701191ba]::placeholder{color:var(--vp-c-text-2)!important;opacity:1}#share-feedback-description[data-v-701191ba]{color:var(--vp-c-text-2)}.field-label[data-v-701191ba]{font-size:12px;font-weight:bolder;display:block;margin-bottom:8px}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/iroha-2-docs/assets/inter-roman-cyrillic.CMhn1ESj.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/iroha-2-docs/assets/inter-roman-cyrillic-ext.DxP3Awbn.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/iroha-2-docs/assets/inter-roman-greek.JvnBZ4YD.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/iroha-2-docs/assets/inter-roman-greek-ext.D0mI3NpI.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/iroha-2-docs/assets/inter-roman-latin.Bu8hRsVA.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/iroha-2-docs/assets/inter-roman-latin-ext.ZlYT4o7i.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/iroha-2-docs/assets/inter-roman-vietnamese.ClpjcLMQ.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/iroha-2-docs/assets/inter-italic-cyrillic.D6csxwjC.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/iroha-2-docs/assets/inter-italic-cyrillic-ext.5XJwZIOp.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/iroha-2-docs/assets/inter-italic-greek.9J96vYpw.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/iroha-2-docs/assets/inter-italic-greek-ext.CHOfFY1k.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/iroha-2-docs/assets/inter-italic-latin.DbsTr1gm.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/iroha-2-docs/assets/inter-italic-latin-ext.BGcWXLrn.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/iroha-2-docs/assets/inter-italic-vietnamese.DHNAd7Wr.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Chinese Quotes;src:local("PingFang SC Regular"),local("PingFang SC"),local("SimHei"),local("Source Han Sans SC");unicode-range:U+2018,U+2019,U+201C,U+201D}:root{--vp-c-white: #ffffff;--vp-c-black: #000000;--vp-c-neutral: var(--vp-c-black);--vp-c-neutral-inverse: var(--vp-c-white)}.dark{--vp-c-neutral: var(--vp-c-white);--vp-c-neutral-inverse: var(--vp-c-black)}:root{--vp-c-gray-1: #dddde3;--vp-c-gray-2: #e4e4e9;--vp-c-gray-3: #ebebef;--vp-c-gray-soft: rgba(142, 150, 170, .14);--vp-c-indigo-1: #3451b2;--vp-c-indigo-2: #3a5ccc;--vp-c-indigo-3: #5672cd;--vp-c-indigo-soft: rgba(100, 108, 255, .14);--vp-c-purple-1: #6f42c1;--vp-c-purple-2: #7e4cc9;--vp-c-purple-3: #8e5cd9;--vp-c-purple-soft: rgba(159, 122, 234, .14);--vp-c-green-1: #18794e;--vp-c-green-2: #299764;--vp-c-green-3: #30a46c;--vp-c-green-soft: rgba(16, 185, 129, .14);--vp-c-yellow-1: #915930;--vp-c-yellow-2: #946300;--vp-c-yellow-3: #9f6a00;--vp-c-yellow-soft: rgba(234, 179, 8, .14);--vp-c-red-1: #b8272c;--vp-c-red-2: #d5393e;--vp-c-red-3: #e0575b;--vp-c-red-soft: rgba(244, 63, 94, .14);--vp-c-sponsor: #db2777}.dark{--vp-c-gray-1: #515c67;--vp-c-gray-2: #414853;--vp-c-gray-3: #32363f;--vp-c-gray-soft: rgba(101, 117, 133, .16);--vp-c-indigo-1: #a8b1ff;--vp-c-indigo-2: #5c73e7;--vp-c-indigo-3: #3e63dd;--vp-c-indigo-soft: rgba(100, 108, 255, .16);--vp-c-purple-1: #c8abfa;--vp-c-purple-2: #a879e6;--vp-c-purple-3: #8e5cd9;--vp-c-purple-soft: rgba(159, 122, 234, .16);--vp-c-green-1: #3dd68c;--vp-c-green-2: #30a46c;--vp-c-green-3: #298459;--vp-c-green-soft: rgba(16, 185, 129, .16);--vp-c-yellow-1: #f9b44e;--vp-c-yellow-2: #da8b17;--vp-c-yellow-3: #a46a0a;--vp-c-yellow-soft: rgba(234, 179, 8, .16);--vp-c-red-1: #f66f81;--vp-c-red-2: #f14158;--vp-c-red-3: #b62a3c;--vp-c-red-soft: rgba(244, 63, 94, .16)}:root{--vp-c-bg: #ffffff;--vp-c-bg-alt: #f6f6f7;--vp-c-bg-elv: #ffffff;--vp-c-bg-soft: #f6f6f7}.dark{--vp-c-bg: #1b1b1f;--vp-c-bg-alt: #161618;--vp-c-bg-elv: #202127;--vp-c-bg-soft: #202127}:root{--vp-c-border: #c2c2c4;--vp-c-divider: #e2e2e3;--vp-c-gutter: #e2e2e3}.dark{--vp-c-border: #3c3f44;--vp-c-divider: #2e2e32;--vp-c-gutter: #000000}:root{--vp-c-text-1: rgba(60, 60, 67);--vp-c-text-2: rgba(60, 60, 67, .78);--vp-c-text-3: rgba(60, 60, 67, .56)}.dark{--vp-c-text-1: rgba(255, 255, 245, .86);--vp-c-text-2: rgba(235, 235, 245, .6);--vp-c-text-3: rgba(235, 235, 245, .38)}:root{--vp-c-default-1: var(--vp-c-gray-1);--vp-c-default-2: var(--vp-c-gray-2);--vp-c-default-3: var(--vp-c-gray-3);--vp-c-default-soft: var(--vp-c-gray-soft);--vp-c-brand-1: var(--vp-c-indigo-1);--vp-c-brand-2: var(--vp-c-indigo-2);--vp-c-brand-3: var(--vp-c-indigo-3);--vp-c-brand-soft: var(--vp-c-indigo-soft);--vp-c-brand: var(--vp-c-brand-1);--vp-c-tip-1: var(--vp-c-brand-1);--vp-c-tip-2: var(--vp-c-brand-2);--vp-c-tip-3: var(--vp-c-brand-3);--vp-c-tip-soft: var(--vp-c-brand-soft);--vp-c-note-1: var(--vp-c-brand-1);--vp-c-note-2: var(--vp-c-brand-2);--vp-c-note-3: var(--vp-c-brand-3);--vp-c-note-soft: var(--vp-c-brand-soft);--vp-c-success-1: var(--vp-c-green-1);--vp-c-success-2: var(--vp-c-green-2);--vp-c-success-3: var(--vp-c-green-3);--vp-c-success-soft: var(--vp-c-green-soft);--vp-c-important-1: var(--vp-c-purple-1);--vp-c-important-2: var(--vp-c-purple-2);--vp-c-important-3: var(--vp-c-purple-3);--vp-c-important-soft: var(--vp-c-purple-soft);--vp-c-warning-1: var(--vp-c-yellow-1);--vp-c-warning-2: var(--vp-c-yellow-2);--vp-c-warning-3: var(--vp-c-yellow-3);--vp-c-warning-soft: var(--vp-c-yellow-soft);--vp-c-danger-1: var(--vp-c-red-1);--vp-c-danger-2: var(--vp-c-red-2);--vp-c-danger-3: var(--vp-c-red-3);--vp-c-danger-soft: var(--vp-c-red-soft);--vp-c-caution-1: var(--vp-c-red-1);--vp-c-caution-2: var(--vp-c-red-2);--vp-c-caution-3: var(--vp-c-red-3);--vp-c-caution-soft: var(--vp-c-red-soft)}:root{--vp-font-family-base: "Chinese Quotes", "Inter var", "Inter", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Helvetica, Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--vp-font-family-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}:root{--vp-shadow-1: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--vp-shadow-2: 0 3px 12px rgba(0, 0, 0, .07), 0 1px 4px rgba(0, 0, 0, .07);--vp-shadow-3: 0 12px 32px rgba(0, 0, 0, .1), 0 2px 6px rgba(0, 0, 0, .08);--vp-shadow-4: 0 14px 44px rgba(0, 0, 0, .12), 0 3px 9px rgba(0, 0, 0, .12);--vp-shadow-5: 0 18px 56px rgba(0, 0, 0, .16), 0 4px 12px rgba(0, 0, 0, .16)}:root{--vp-z-index-footer: 10;--vp-z-index-local-nav: 20;--vp-z-index-nav: 30;--vp-z-index-layout-top: 40;--vp-z-index-backdrop: 50;--vp-z-index-sidebar: 60}@media (min-width: 960px){:root{--vp-z-index-sidebar: 25}}:root{--vp-icon-copy: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2'/%3E%3C/svg%3E");--vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2m-6 9 2 2 4-4'/%3E%3C/svg%3E")}:root{--vp-layout-max-width: 1440px}:root{--vp-header-anchor-symbol: "#"}:root{--vp-code-line-height: 1.7;--vp-code-font-size: .875em;--vp-code-color: var(--vp-c-brand-1);--vp-code-link-color: var(--vp-c-brand-1);--vp-code-link-hover-color: var(--vp-c-brand-2);--vp-code-bg: var(--vp-c-default-soft);--vp-code-block-color: var(--vp-c-text-2);--vp-code-block-bg: var(--vp-c-bg-alt);--vp-code-block-divider-color: var(--vp-c-gutter);--vp-code-lang-color: var(--vp-c-text-3);--vp-code-line-highlight-color: var(--vp-c-default-soft);--vp-code-line-number-color: var(--vp-c-text-3);--vp-code-line-diff-add-color: var(--vp-c-success-soft);--vp-code-line-diff-add-symbol-color: var(--vp-c-success-1);--vp-code-line-diff-remove-color: var(--vp-c-danger-soft);--vp-code-line-diff-remove-symbol-color: var(--vp-c-danger-1);--vp-code-line-warning-color: var(--vp-c-warning-soft);--vp-code-line-error-color: var(--vp-c-danger-soft);--vp-code-copy-code-border-color: var(--vp-c-divider);--vp-code-copy-code-bg: var(--vp-c-bg-soft);--vp-code-copy-code-hover-border-color: var(--vp-c-divider);--vp-code-copy-code-hover-bg: var(--vp-c-bg);--vp-code-copy-code-active-text: var(--vp-c-text-2);--vp-code-copy-copied-text-content: "Copied";--vp-code-tab-divider: var(--vp-code-block-divider-color);--vp-code-tab-text-color: var(--vp-c-text-2);--vp-code-tab-bg: var(--vp-code-block-bg);--vp-code-tab-hover-text-color: var(--vp-c-text-1);--vp-code-tab-active-text-color: var(--vp-c-text-1);--vp-code-tab-active-bar-color: var(--vp-c-brand-1)}:root{--vp-button-brand-border: transparent;--vp-button-brand-text: var(--vp-c-white);--vp-button-brand-bg: var(--vp-c-brand-3);--vp-button-brand-hover-border: transparent;--vp-button-brand-hover-text: var(--vp-c-white);--vp-button-brand-hover-bg: var(--vp-c-brand-2);--vp-button-brand-active-border: transparent;--vp-button-brand-active-text: var(--vp-c-white);--vp-button-brand-active-bg: var(--vp-c-brand-1);--vp-button-alt-border: transparent;--vp-button-alt-text: var(--vp-c-text-1);--vp-button-alt-bg: var(--vp-c-default-3);--vp-button-alt-hover-border: transparent;--vp-button-alt-hover-text: var(--vp-c-text-1);--vp-button-alt-hover-bg: var(--vp-c-default-2);--vp-button-alt-active-border: transparent;--vp-button-alt-active-text: var(--vp-c-text-1);--vp-button-alt-active-bg: var(--vp-c-default-1);--vp-button-sponsor-border: var(--vp-c-text-2);--vp-button-sponsor-text: var(--vp-c-text-2);--vp-button-sponsor-bg: transparent;--vp-button-sponsor-hover-border: var(--vp-c-sponsor);--vp-button-sponsor-hover-text: var(--vp-c-sponsor);--vp-button-sponsor-hover-bg: transparent;--vp-button-sponsor-active-border: var(--vp-c-sponsor);--vp-button-sponsor-active-text: var(--vp-c-sponsor);--vp-button-sponsor-active-bg: transparent}:root{--vp-custom-block-font-size: 14px;--vp-custom-block-code-font-size: 13px;--vp-custom-block-info-border: transparent;--vp-custom-block-info-text: var(--vp-c-text-1);--vp-custom-block-info-bg: var(--vp-c-default-soft);--vp-custom-block-info-code-bg: var(--vp-c-default-soft);--vp-custom-block-note-border: transparent;--vp-custom-block-note-text: var(--vp-c-text-1);--vp-custom-block-note-bg: var(--vp-c-default-soft);--vp-custom-block-note-code-bg: var(--vp-c-default-soft);--vp-custom-block-tip-border: transparent;--vp-custom-block-tip-text: var(--vp-c-text-1);--vp-custom-block-tip-bg: var(--vp-c-tip-soft);--vp-custom-block-tip-code-bg: var(--vp-c-tip-soft);--vp-custom-block-important-border: transparent;--vp-custom-block-important-text: var(--vp-c-text-1);--vp-custom-block-important-bg: var(--vp-c-important-soft);--vp-custom-block-important-code-bg: var(--vp-c-important-soft);--vp-custom-block-warning-border: transparent;--vp-custom-block-warning-text: var(--vp-c-text-1);--vp-custom-block-warning-bg: var(--vp-c-warning-soft);--vp-custom-block-warning-code-bg: var(--vp-c-warning-soft);--vp-custom-block-danger-border: transparent;--vp-custom-block-danger-text: var(--vp-c-text-1);--vp-custom-block-danger-bg: var(--vp-c-danger-soft);--vp-custom-block-danger-code-bg: var(--vp-c-danger-soft);--vp-custom-block-caution-border: transparent;--vp-custom-block-caution-text: var(--vp-c-text-1);--vp-custom-block-caution-bg: var(--vp-c-caution-soft);--vp-custom-block-caution-code-bg: var(--vp-c-caution-soft);--vp-custom-block-details-border: var(--vp-custom-block-info-border);--vp-custom-block-details-text: var(--vp-custom-block-info-text);--vp-custom-block-details-bg: var(--vp-custom-block-info-bg);--vp-custom-block-details-code-bg: var(--vp-custom-block-info-code-bg)}:root{--vp-input-border-color: var(--vp-c-border);--vp-input-bg-color: var(--vp-c-bg-alt);--vp-input-switch-bg-color: var(--vp-c-default-soft)}:root{--vp-nav-height: 64px;--vp-nav-bg-color: var(--vp-c-bg);--vp-nav-screen-bg-color: var(--vp-c-bg);--vp-nav-logo-height: 24px}.hide-nav{--vp-nav-height: 0px}.hide-nav .VPSidebar{--vp-nav-height: 22px}:root{--vp-local-nav-bg-color: var(--vp-c-bg)}:root{--vp-sidebar-width: 272px;--vp-sidebar-bg-color: var(--vp-c-bg-alt)}:root{--vp-backdrop-bg-color: rgba(0, 0, 0, .6)}:root{--vp-home-hero-name-color: var(--vp-c-brand-1);--vp-home-hero-name-background: transparent;--vp-home-hero-image-background-image: none;--vp-home-hero-image-filter: none}:root{--vp-badge-info-border: transparent;--vp-badge-info-text: var(--vp-c-text-2);--vp-badge-info-bg: var(--vp-c-default-soft);--vp-badge-tip-border: transparent;--vp-badge-tip-text: var(--vp-c-tip-1);--vp-badge-tip-bg: var(--vp-c-tip-soft);--vp-badge-warning-border: transparent;--vp-badge-warning-text: var(--vp-c-warning-1);--vp-badge-warning-bg: var(--vp-c-warning-soft);--vp-badge-danger-border: transparent;--vp-badge-danger-text: var(--vp-c-danger-1);--vp-badge-danger-bg: var(--vp-c-danger-soft)}:root{--vp-carbon-ads-text-color: var(--vp-c-text-1);--vp-carbon-ads-poweredby-color: var(--vp-c-text-2);--vp-carbon-ads-bg-color: var(--vp-c-bg-soft);--vp-carbon-ads-hover-text-color: var(--vp-c-brand-1);--vp-carbon-ads-hover-poweredby-color: var(--vp-c-text-1)}:root{--vp-local-search-bg: var(--vp-c-bg);--vp-local-search-result-bg: var(--vp-c-bg);--vp-local-search-result-border: var(--vp-c-divider);--vp-local-search-result-selected-bg: var(--vp-c-bg);--vp-local-search-result-selected-border: var(--vp-c-brand-1);--vp-local-search-highlight-bg: var(--vp-c-brand-1);--vp-local-search-highlight-text: var(--vp-c-neutral-inverse)}@media (prefers-reduced-motion: reduce){*,:before,:after{animation-delay:-1ms!important;animation-duration:1ms!important;animation-iteration-count:1!important;background-attachment:initial!important;scroll-behavior:auto!important;transition-duration:0s!important;transition-delay:0s!important}}*,:before,:after{box-sizing:border-box}html{line-height:1.4;font-size:16px;-webkit-text-size-adjust:100%}html.dark{color-scheme:dark}body{margin:0;width:100%;min-width:320px;min-height:100vh;line-height:24px;font-family:var(--vp-font-family-base);font-size:16px;font-weight:400;color:var(--vp-c-text-1);background-color:var(--vp-c-bg);font-synthesis:style;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}main{display:block}h1,h2,h3,h4,h5,h6{margin:0;line-height:24px;font-size:16px;font-weight:400}p{margin:0}strong,b{font-weight:600}a,area,button,[role=button],input,label,select,summary,textarea{touch-action:manipulation}a{color:inherit;text-decoration:inherit}ol,ul{list-style:none;margin:0;padding:0}blockquote{margin:0}pre,code,kbd,samp{font-family:var(--vp-font-family-mono)}img,svg,video,canvas,audio,iframe,embed,object{display:block}figure{margin:0}img,video{max-width:100%;height:auto}button,input,optgroup,select,textarea{border:0;padding:0;line-height:inherit;color:inherit}button{padding:0;font-family:inherit;background-color:transparent;background-image:none}button:enabled,[role=button]:enabled{cursor:pointer}button:focus,button:focus-visible{outline:1px dotted;outline:4px auto -webkit-focus-ring-color}button:focus:not(:focus-visible){outline:none!important}input:focus,textarea:focus,select:focus{outline:none}table{border-collapse:collapse}input{background-color:transparent}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:var(--vp-c-text-3)}input::-ms-input-placeholder,textarea::-ms-input-placeholder{color:var(--vp-c-text-3)}input::placeholder,textarea::placeholder{color:var(--vp-c-text-3)}input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=number]{-moz-appearance:textfield}textarea{resize:vertical}select{-webkit-appearance:none}fieldset{margin:0;padding:0}h1,h2,h3,h4,h5,h6,li,p{overflow-wrap:break-word}vite-error-overlay{z-index:9999}mjx-container{display:inline-block;margin:auto 2px -2px}mjx-container>svg{margin:auto}.visually-hidden{position:absolute;width:1px;height:1px;white-space:nowrap;clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden}.custom-block{border:1px solid transparent;border-radius:8px;padding:16px 16px 8px;line-height:24px;font-size:var(--vp-custom-block-font-size);color:var(--vp-c-text-2)}.custom-block.info{border-color:var(--vp-custom-block-info-border);color:var(--vp-custom-block-info-text);background-color:var(--vp-custom-block-info-bg)}.custom-block.info a,.custom-block.info code{color:var(--vp-c-brand-1)}.custom-block.info a:hover,.custom-block.info a:hover>code{color:var(--vp-c-brand-2)}.custom-block.info code{background-color:var(--vp-custom-block-info-code-bg)}.custom-block.note{border-color:var(--vp-custom-block-note-border);color:var(--vp-custom-block-note-text);background-color:var(--vp-custom-block-note-bg)}.custom-block.note a,.custom-block.note code{color:var(--vp-c-brand-1)}.custom-block.note a:hover,.custom-block.note a:hover>code{color:var(--vp-c-brand-2)}.custom-block.note code{background-color:var(--vp-custom-block-note-code-bg)}.custom-block.tip{border-color:var(--vp-custom-block-tip-border);color:var(--vp-custom-block-tip-text);background-color:var(--vp-custom-block-tip-bg)}.custom-block.tip a,.custom-block.tip code{color:var(--vp-c-tip-1)}.custom-block.tip a:hover,.custom-block.tip a:hover>code{color:var(--vp-c-tip-2)}.custom-block.tip code{background-color:var(--vp-custom-block-tip-code-bg)}.custom-block.important{border-color:var(--vp-custom-block-important-border);color:var(--vp-custom-block-important-text);background-color:var(--vp-custom-block-important-bg)}.custom-block.important a,.custom-block.important code{color:var(--vp-c-important-1)}.custom-block.important a:hover,.custom-block.important a:hover>code{color:var(--vp-c-important-2)}.custom-block.important code{background-color:var(--vp-custom-block-important-code-bg)}.custom-block.warning{border-color:var(--vp-custom-block-warning-border);color:var(--vp-custom-block-warning-text);background-color:var(--vp-custom-block-warning-bg)}.custom-block.warning a,.custom-block.warning code{color:var(--vp-c-warning-1)}.custom-block.warning a:hover,.custom-block.warning a:hover>code{color:var(--vp-c-warning-2)}.custom-block.warning code{background-color:var(--vp-custom-block-warning-code-bg)}.custom-block.danger{border-color:var(--vp-custom-block-danger-border);color:var(--vp-custom-block-danger-text);background-color:var(--vp-custom-block-danger-bg)}.custom-block.danger a,.custom-block.danger code{color:var(--vp-c-danger-1)}.custom-block.danger a:hover,.custom-block.danger a:hover>code{color:var(--vp-c-danger-2)}.custom-block.danger code{background-color:var(--vp-custom-block-danger-code-bg)}.custom-block.caution{border-color:var(--vp-custom-block-caution-border);color:var(--vp-custom-block-caution-text);background-color:var(--vp-custom-block-caution-bg)}.custom-block.caution a,.custom-block.caution code{color:var(--vp-c-caution-1)}.custom-block.caution a:hover,.custom-block.caution a:hover>code{color:var(--vp-c-caution-2)}.custom-block.caution code{background-color:var(--vp-custom-block-caution-code-bg)}.custom-block.details{border-color:var(--vp-custom-block-details-border);color:var(--vp-custom-block-details-text);background-color:var(--vp-custom-block-details-bg)}.custom-block.details a{color:var(--vp-c-brand-1)}.custom-block.details a:hover,.custom-block.details a:hover>code{color:var(--vp-c-brand-2)}.custom-block.details code{background-color:var(--vp-custom-block-details-code-bg)}.custom-block-title{font-weight:600}.custom-block p+p{margin:8px 0}.custom-block.details summary{margin:0 0 8px;font-weight:700;cursor:pointer;-webkit-user-select:none;user-select:none}.custom-block.details summary+p{margin:8px 0}.custom-block a{color:inherit;font-weight:600;text-decoration:underline;text-underline-offset:2px;transition:opacity .25s}.custom-block a:hover{opacity:.75}.custom-block code{font-size:var(--vp-custom-block-code-font-size)}.custom-block.custom-block th,.custom-block.custom-block blockquote>p{font-size:var(--vp-custom-block-font-size);color:inherit}.dark .vp-code span{color:var(--shiki-dark, inherit)}html:not(.dark) .vp-code span{color:var(--shiki-light, inherit)}.vp-code-group{margin-top:16px}.vp-code-group .tabs{position:relative;display:flex;margin-right:-24px;margin-left:-24px;padding:0 12px;background-color:var(--vp-code-tab-bg);overflow-x:auto;overflow-y:hidden;box-shadow:inset 0 -1px var(--vp-code-tab-divider)}@media (min-width: 640px){.vp-code-group .tabs{margin-right:0;margin-left:0;border-radius:8px 8px 0 0}}.vp-code-group .tabs input{position:fixed;opacity:0;pointer-events:none}.vp-code-group .tabs label{position:relative;display:inline-block;border-bottom:1px solid transparent;padding:0 12px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-code-tab-text-color);white-space:nowrap;cursor:pointer;transition:color .25s}.vp-code-group .tabs label:after{position:absolute;right:8px;bottom:-1px;left:8px;z-index:1;height:2px;border-radius:2px;content:"";background-color:transparent;transition:background-color .25s}.vp-code-group label:hover{color:var(--vp-code-tab-hover-text-color)}.vp-code-group input:checked+label{color:var(--vp-code-tab-active-text-color)}.vp-code-group input:checked+label:after{background-color:var(--vp-code-tab-active-bar-color)}.vp-code-group div[class*=language-],.vp-block{display:none;margin-top:0!important;border-top-left-radius:0!important;border-top-right-radius:0!important}.vp-code-group div[class*=language-].active,.vp-block.active{display:block}.vp-block{padding:20px 24px}.vp-doc h1,.vp-doc h2,.vp-doc h3,.vp-doc h4,.vp-doc h5,.vp-doc h6{position:relative;font-weight:600;outline:none}.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:28px}.vp-doc h2{margin:48px 0 16px;border-top:1px solid var(--vp-c-divider);padding-top:24px;letter-spacing:-.02em;line-height:32px;font-size:24px}.vp-doc h3{margin:32px 0 0;letter-spacing:-.01em;line-height:28px;font-size:20px}.vp-doc .header-anchor{position:absolute;top:0;left:0;margin-left:-.87em;font-weight:500;-webkit-user-select:none;user-select:none;opacity:0;text-decoration:none;transition:color .25s,opacity .25s}.vp-doc .header-anchor:before{content:var(--vp-header-anchor-symbol)}.vp-doc h1:hover .header-anchor,.vp-doc h1 .header-anchor:focus,.vp-doc h2:hover .header-anchor,.vp-doc h2 .header-anchor:focus,.vp-doc h3:hover .header-anchor,.vp-doc h3 .header-anchor:focus,.vp-doc h4:hover .header-anchor,.vp-doc h4 .header-anchor:focus,.vp-doc h5:hover .header-anchor,.vp-doc h5 .header-anchor:focus,.vp-doc h6:hover .header-anchor,.vp-doc h6 .header-anchor:focus{opacity:1}@media (min-width: 768px){.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:32px}}.vp-doc h2 .header-anchor{top:24px}.vp-doc p,.vp-doc summary{margin:16px 0}.vp-doc p{line-height:28px}.vp-doc blockquote{margin:16px 0;border-left:2px solid var(--vp-c-divider);padding-left:16px;transition:border-color .5s}.vp-doc blockquote>p{margin:0;font-size:16px;color:var(--vp-c-text-2);transition:color .5s}.vp-doc a{font-weight:500;color:var(--vp-c-brand-1);text-decoration:underline;text-underline-offset:2px;transition:color .25s,opacity .25s}.vp-doc a:hover{color:var(--vp-c-brand-2)}.vp-doc strong{font-weight:600}.vp-doc ul,.vp-doc ol{padding-left:1.25rem;margin:16px 0}.vp-doc ul{list-style:disc}.vp-doc ol{list-style:decimal}.vp-doc li+li{margin-top:8px}.vp-doc li>ol,.vp-doc li>ul{margin:8px 0 0}.vp-doc table{display:block;border-collapse:collapse;margin:20px 0;overflow-x:auto}.vp-doc tr{background-color:var(--vp-c-bg);border-top:1px solid var(--vp-c-divider);transition:background-color .5s}.vp-doc tr:nth-child(2n){background-color:var(--vp-c-bg-soft)}.vp-doc th,.vp-doc td{border:1px solid var(--vp-c-divider);padding:8px 16px}.vp-doc th{text-align:left;font-size:14px;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-doc td{font-size:14px}.vp-doc hr{margin:16px 0;border:none;border-top:1px solid var(--vp-c-divider)}.vp-doc .custom-block{margin:16px 0}.vp-doc .custom-block p{margin:8px 0;line-height:24px}.vp-doc .custom-block p:first-child{margin:0}.vp-doc .custom-block div[class*=language-]{margin:8px 0;border-radius:8px}.vp-doc .custom-block div[class*=language-] code{font-weight:400;background-color:transparent}.vp-doc .custom-block .vp-code-group .tabs{margin:0;border-radius:8px 8px 0 0}.vp-doc :not(pre,h1,h2,h3,h4,h5,h6)>code{font-size:var(--vp-code-font-size);color:var(--vp-code-color)}.vp-doc :not(pre)>code{border-radius:4px;padding:3px 6px;background-color:var(--vp-code-bg);transition:color .25s,background-color .5s}.vp-doc a>code{color:var(--vp-code-link-color)}.vp-doc a:hover>code{color:var(--vp-code-link-hover-color)}.vp-doc h1>code,.vp-doc h2>code,.vp-doc h3>code{font-size:.9em}.vp-doc div[class*=language-],.vp-block{position:relative;margin:16px -24px;background-color:var(--vp-code-block-bg);overflow-x:auto;transition:background-color .5s}@media (min-width: 640px){.vp-doc div[class*=language-],.vp-block{border-radius:8px;margin:16px 0}}@media (max-width: 639px){.vp-doc li div[class*=language-]{border-radius:8px 0 0 8px}}.vp-doc div[class*=language-]+div[class*=language-],.vp-doc div[class$=-api]+div[class*=language-],.vp-doc div[class*=language-]+div[class$=-api]>div[class*=language-]{margin-top:-8px}.vp-doc [class*=language-] pre,.vp-doc [class*=language-] code{direction:ltr;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}.vp-doc [class*=language-] pre{position:relative;z-index:1;margin:0;padding:20px 0;background:transparent;overflow-x:auto}.vp-doc [class*=language-] code{display:block;padding:0 24px;width:fit-content;min-width:100%;line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-block-color);transition:color .5s}.vp-doc [class*=language-] code .highlighted{background-color:var(--vp-code-line-highlight-color);transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .highlighted.error{background-color:var(--vp-code-line-error-color)}.vp-doc [class*=language-] code .highlighted.warning{background-color:var(--vp-code-line-warning-color)}.vp-doc [class*=language-] code .diff{transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .diff:before{position:absolute;left:10px}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){filter:blur(.095rem);opacity:.4;transition:filter .35s,opacity .35s}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){opacity:.7;transition:filter .35s,opacity .35s}.vp-doc [class*=language-]:hover .has-focused-lines .line:not(.has-focus){filter:blur(0);opacity:1}.vp-doc [class*=language-] code .diff.remove{background-color:var(--vp-code-line-diff-remove-color);opacity:.7}.vp-doc [class*=language-] code .diff.remove:before{content:"-";color:var(--vp-code-line-diff-remove-symbol-color)}.vp-doc [class*=language-] code .diff.add{background-color:var(--vp-code-line-diff-add-color)}.vp-doc [class*=language-] code .diff.add:before{content:"+";color:var(--vp-code-line-diff-add-symbol-color)}.vp-doc div[class*=language-].line-numbers-mode{padding-left:32px}.vp-doc .line-numbers-wrapper{position:absolute;top:0;bottom:0;left:0;z-index:3;border-right:1px solid var(--vp-code-block-divider-color);padding-top:20px;width:32px;text-align:center;font-family:var(--vp-font-family-mono);line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-line-number-color);transition:border-color .5s,color .5s}.vp-doc [class*=language-]>button.copy{direction:ltr;position:absolute;top:12px;right:12px;z-index:3;border:1px solid var(--vp-code-copy-code-border-color);border-radius:4px;width:40px;height:40px;background-color:var(--vp-code-copy-code-bg);opacity:0;cursor:pointer;background-image:var(--vp-icon-copy);background-position:50%;background-size:20px;background-repeat:no-repeat;transition:border-color .25s,background-color .25s,opacity .25s}.vp-doc [class*=language-]:hover>button.copy,.vp-doc [class*=language-]>button.copy:focus{opacity:1}.vp-doc [class*=language-]>button.copy:hover,.vp-doc [class*=language-]>button.copy.copied{border-color:var(--vp-code-copy-code-hover-border-color);background-color:var(--vp-code-copy-code-hover-bg)}.vp-doc [class*=language-]>button.copy.copied,.vp-doc [class*=language-]>button.copy:hover.copied{border-radius:0 4px 4px 0;background-color:var(--vp-code-copy-code-hover-bg);background-image:var(--vp-icon-copied)}.vp-doc [class*=language-]>button.copy.copied:before,.vp-doc [class*=language-]>button.copy:hover.copied:before{position:relative;top:-1px;transform:translate(calc(-100% - 1px));display:flex;justify-content:center;align-items:center;border:1px solid var(--vp-code-copy-code-hover-border-color);border-right:0;border-radius:4px 0 0 4px;padding:0 10px;width:fit-content;height:40px;text-align:center;font-size:12px;font-weight:500;color:var(--vp-code-copy-code-active-text);background-color:var(--vp-code-copy-code-hover-bg);white-space:nowrap;content:var(--vp-code-copy-copied-text-content)}.vp-doc [class*=language-]>span.lang{position:absolute;top:2px;right:8px;z-index:2;font-size:12px;font-weight:500;color:var(--vp-code-lang-color);transition:color .4s,opacity .4s}.vp-doc [class*=language-]:hover>button.copy+span.lang,.vp-doc [class*=language-]>button.copy:focus+span.lang{opacity:0}.vp-doc .VPTeamMembers{margin-top:24px}.vp-doc .VPTeamMembers.small.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}.vp-doc .VPTeamMembers.small.count-2 .container,.vp-doc .VPTeamMembers.small.count-3 .container{max-width:100%!important}.vp-doc .VPTeamMembers.medium.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}:is(.vp-external-link-icon,.vp-doc a[href*="://"],.vp-doc a[target=_blank]):not(.no-icon):after{display:inline-block;margin-top:-1px;margin-left:4px;width:11px;height:11px;background:currentColor;color:var(--vp-c-text-3);flex-shrink:0;--icon: url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath d='M0 0h24v24H0V0z' fill='none' /%3E%3Cpath d='M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5H9z' /%3E%3C/svg%3E");-webkit-mask-image:var(--icon);mask-image:var(--icon)}.vp-external-link-icon:after{content:""}.external-link-icon-enabled :is(.vp-doc a[href*="://"],.vp-doc a[target=_blank]):after{content:"";color:currentColor}.vp-sponsor{border-radius:16px;overflow:hidden}.vp-sponsor.aside{border-radius:12px}.vp-sponsor-section+.vp-sponsor-section{margin-top:4px}.vp-sponsor-tier{margin-bottom:4px;text-align:center;letter-spacing:1px;line-height:24px;width:100%;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-sponsor.normal .vp-sponsor-tier{padding:13px 0 11px;font-size:14px}.vp-sponsor.aside .vp-sponsor-tier{padding:9px 0 7px;font-size:12px}.vp-sponsor-grid+.vp-sponsor-tier{margin-top:4px}.vp-sponsor-grid{display:flex;flex-wrap:wrap;gap:4px}.vp-sponsor-grid.xmini .vp-sponsor-grid-link{height:64px}.vp-sponsor-grid.xmini .vp-sponsor-grid-image{max-width:64px;max-height:22px}.vp-sponsor-grid.mini .vp-sponsor-grid-link{height:72px}.vp-sponsor-grid.mini .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.small .vp-sponsor-grid-link{height:96px}.vp-sponsor-grid.small .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.medium .vp-sponsor-grid-link{height:112px}.vp-sponsor-grid.medium .vp-sponsor-grid-image{max-width:120px;max-height:36px}.vp-sponsor-grid.big .vp-sponsor-grid-link{height:184px}.vp-sponsor-grid.big .vp-sponsor-grid-image{max-width:192px;max-height:56px}.vp-sponsor-grid[data-vp-grid="2"] .vp-sponsor-grid-item{width:calc((100% - 4px)/2)}.vp-sponsor-grid[data-vp-grid="3"] .vp-sponsor-grid-item{width:calc((100% - 4px * 2) / 3)}.vp-sponsor-grid[data-vp-grid="4"] .vp-sponsor-grid-item{width:calc((100% - 12px)/4)}.vp-sponsor-grid[data-vp-grid="5"] .vp-sponsor-grid-item{width:calc((100% - 16px)/5)}.vp-sponsor-grid[data-vp-grid="6"] .vp-sponsor-grid-item{width:calc((100% - 4px * 5) / 6)}.vp-sponsor-grid-item{flex-shrink:0;width:100%;background-color:var(--vp-c-bg-soft);transition:background-color .25s}.vp-sponsor-grid-item:hover{background-color:var(--vp-c-default-soft)}.vp-sponsor-grid-item:hover .vp-sponsor-grid-image{filter:grayscale(0) invert(0)}.vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.dark .vp-sponsor-grid-item:hover{background-color:var(--vp-c-white)}.dark .vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.vp-sponsor-grid-link{display:flex}.vp-sponsor-grid-box{display:flex;justify-content:center;align-items:center;width:100%}.vp-sponsor-grid-image{max-width:100%;filter:grayscale(1);transition:filter .25s}.dark .vp-sponsor-grid-image{filter:grayscale(1) invert(1)}.VPBadge{display:inline-block;margin-left:2px;border:1px solid transparent;border-radius:12px;padding:0 10px;line-height:22px;font-size:12px;font-weight:500;transform:translateY(-2px)}.VPBadge.small{padding:0 6px;line-height:18px;font-size:10px;transform:translateY(-8px)}.VPDocFooter .VPBadge{display:none}.vp-doc h1>.VPBadge{margin-top:4px;vertical-align:top}.vp-doc h2>.VPBadge{margin-top:3px;padding:0 8px;vertical-align:top}.vp-doc h3>.VPBadge{vertical-align:middle}.vp-doc h4>.VPBadge,.vp-doc h5>.VPBadge,.vp-doc h6>.VPBadge{vertical-align:middle;line-height:18px}.VPBadge.info{border-color:var(--vp-badge-info-border);color:var(--vp-badge-info-text);background-color:var(--vp-badge-info-bg)}.VPBadge.tip{border-color:var(--vp-badge-tip-border);color:var(--vp-badge-tip-text);background-color:var(--vp-badge-tip-bg)}.VPBadge.warning{border-color:var(--vp-badge-warning-border);color:var(--vp-badge-warning-text);background-color:var(--vp-badge-warning-bg)}.VPBadge.danger{border-color:var(--vp-badge-danger-border);color:var(--vp-badge-danger-text);background-color:var(--vp-badge-danger-bg)}.VPBackdrop[data-v-eab8694c]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:var(--vp-z-index-backdrop);background:var(--vp-backdrop-bg-color);transition:opacity .5s}.VPBackdrop.fade-enter-from[data-v-eab8694c],.VPBackdrop.fade-leave-to[data-v-eab8694c]{opacity:0}.VPBackdrop.fade-leave-active[data-v-eab8694c]{transition-duration:.25s}@media (min-width: 1280px){.VPBackdrop[data-v-eab8694c]{display:none}}.NotFound[data-v-20cd492c]{padding:64px 24px 96px;text-align:center}@media (min-width: 768px){.NotFound[data-v-20cd492c]{padding:96px 32px 168px}}.code[data-v-20cd492c]{line-height:64px;font-size:64px;font-weight:600}.title[data-v-20cd492c]{padding-top:12px;letter-spacing:2px;line-height:20px;font-size:20px;font-weight:700}.divider[data-v-20cd492c]{margin:24px auto 18px;width:64px;height:1px;background-color:var(--vp-c-divider)}.quote[data-v-20cd492c]{margin:0 auto;max-width:256px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.action[data-v-20cd492c]{padding-top:20px}.link[data-v-20cd492c]{display:inline-block;border:1px solid var(--vp-c-brand-1);border-radius:16px;padding:3px 16px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:border-color .25s,color .25s}.link[data-v-20cd492c]:hover{border-color:var(--vp-c-brand-2);color:var(--vp-c-brand-2)}.root[data-v-12d62b85]{position:relative;z-index:1}.nested[data-v-12d62b85]{padding-right:16px;padding-left:16px}.outline-link[data-v-12d62b85]{display:block;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .5s}.outline-link[data-v-12d62b85]:hover,.outline-link.active[data-v-12d62b85]{color:var(--vp-c-text-1);transition:color .25s}.outline-link.nested[data-v-12d62b85]{padding-left:13px}.VPDocAsideOutline[data-v-4c932924]{display:none}.VPDocAsideOutline.has-outline[data-v-4c932924]{display:block}.content[data-v-4c932924]{position:relative;border-left:1px solid var(--vp-c-divider);padding-left:16px;font-size:13px;font-weight:500}.outline-marker[data-v-4c932924]{position:absolute;top:32px;left:-1px;z-index:0;opacity:0;width:2px;border-radius:2px;height:18px;background-color:var(--vp-c-brand-1);transition:top .25s cubic-bezier(0,1,.5,1),background-color .5s,opacity .25s}.outline-title[data-v-4c932924]{line-height:32px;font-size:14px;font-weight:600}.VPDocAside[data-v-8d28afd0]{display:flex;flex-direction:column;flex-grow:1}.spacer[data-v-8d28afd0]{flex-grow:1}.VPDocAside[data-v-8d28afd0] .spacer+.VPDocAsideSponsors,.VPDocAside[data-v-8d28afd0] .spacer+.VPDocAsideCarbonAds{margin-top:24px}.VPDocAside[data-v-8d28afd0] .VPDocAsideSponsors+.VPDocAsideCarbonAds{margin-top:16px}.VPLastUpdated[data-v-7a71ca77]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 640px){.VPLastUpdated[data-v-7a71ca77]{line-height:32px;font-size:14px;font-weight:500}}.VPDocFooter[data-v-3ac27828]{margin-top:64px}.edit-info[data-v-3ac27828]{padding-bottom:18px}@media (min-width: 640px){.edit-info[data-v-3ac27828]{display:flex;justify-content:space-between;align-items:center;padding-bottom:14px}}.edit-link-button[data-v-3ac27828]{display:flex;align-items:center;border:0;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.edit-link-button[data-v-3ac27828]:hover{color:var(--vp-c-brand-2)}.edit-link-icon[data-v-3ac27828]{margin-right:8px;width:14px;height:14px;fill:currentColor}.prev-next[data-v-3ac27828]{border-top:1px solid var(--vp-c-divider);padding-top:24px;display:grid;grid-row-gap:8px}@media (min-width: 640px){.prev-next[data-v-3ac27828]{grid-template-columns:repeat(2,1fr);grid-column-gap:16px}}.pager-link[data-v-3ac27828]{display:block;border:1px solid var(--vp-c-divider);border-radius:8px;padding:11px 16px 13px;width:100%;height:100%;transition:border-color .25s}.pager-link[data-v-3ac27828]:hover{border-color:var(--vp-c-brand-1)}.pager-link.next[data-v-3ac27828]{margin-left:auto;text-align:right}.desc[data-v-3ac27828]{display:block;line-height:20px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.title[data-v-3ac27828]{display:block;line-height:20px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.VPDoc[data-v-a8702f5f]{padding:32px 24px 96px;width:100%}@media (min-width: 768px){.VPDoc[data-v-a8702f5f]{padding:48px 32px 128px}}@media (min-width: 960px){.VPDoc[data-v-a8702f5f]{padding:48px 32px 0}.VPDoc:not(.has-sidebar) .container[data-v-a8702f5f]{display:flex;justify-content:center;max-width:992px}.VPDoc:not(.has-sidebar) .content[data-v-a8702f5f]{max-width:752px}}@media (min-width: 1280px){.VPDoc .container[data-v-a8702f5f]{display:flex;justify-content:center}.VPDoc .aside[data-v-a8702f5f]{display:block}}@media (min-width: 1440px){.VPDoc:not(.has-sidebar) .content[data-v-a8702f5f]{max-width:784px}.VPDoc:not(.has-sidebar) .container[data-v-a8702f5f]{max-width:1104px}}.container[data-v-a8702f5f]{margin:0 auto;width:100%}.aside[data-v-a8702f5f]{position:relative;display:none;order:2;flex-grow:1;padding-left:32px;width:100%;max-width:256px}.left-aside[data-v-a8702f5f]{order:1;padding-left:unset;padding-right:32px}.aside-container[data-v-a8702f5f]{position:fixed;top:0;padding-top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + var(--vp-doc-top-height, 0px) + 48px);width:224px;height:100vh;overflow-x:hidden;overflow-y:auto;scrollbar-width:none}.aside-container[data-v-a8702f5f]::-webkit-scrollbar{display:none}.aside-curtain[data-v-a8702f5f]{position:fixed;bottom:0;z-index:10;width:224px;height:32px;background:linear-gradient(transparent,var(--vp-c-bg) 70%)}.aside-content[data-v-a8702f5f]{display:flex;flex-direction:column;min-height:calc(100vh - (var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px));padding-bottom:32px}.content[data-v-a8702f5f]{position:relative;margin:0 auto;width:100%}@media (min-width: 960px){.content[data-v-a8702f5f]{padding:0 32px 128px}}@media (min-width: 1280px){.content[data-v-a8702f5f]{order:1;margin:0;min-width:640px}}.content-container[data-v-a8702f5f]{margin:0 auto}.VPDoc.has-aside .content-container[data-v-a8702f5f]{max-width:688px}.VPButton[data-v-63241e40]{display:inline-block;border:1px solid transparent;text-align:center;font-weight:600;white-space:nowrap;transition:color .25s,border-color .25s,background-color .25s}.VPButton[data-v-63241e40]:active{transition:color .1s,border-color .1s,background-color .1s}.VPButton.medium[data-v-63241e40]{border-radius:20px;padding:0 20px;line-height:38px;font-size:14px}.VPButton.big[data-v-63241e40]{border-radius:24px;padding:0 24px;line-height:46px;font-size:16px}.VPButton.brand[data-v-63241e40]{border-color:var(--vp-button-brand-border);color:var(--vp-button-brand-text);background-color:var(--vp-button-brand-bg)}.VPButton.brand[data-v-63241e40]:hover{border-color:var(--vp-button-brand-hover-border);color:var(--vp-button-brand-hover-text);background-color:var(--vp-button-brand-hover-bg)}.VPButton.brand[data-v-63241e40]:active{border-color:var(--vp-button-brand-active-border);color:var(--vp-button-brand-active-text);background-color:var(--vp-button-brand-active-bg)}.VPButton.alt[data-v-63241e40]{border-color:var(--vp-button-alt-border);color:var(--vp-button-alt-text);background-color:var(--vp-button-alt-bg)}.VPButton.alt[data-v-63241e40]:hover{border-color:var(--vp-button-alt-hover-border);color:var(--vp-button-alt-hover-text);background-color:var(--vp-button-alt-hover-bg)}.VPButton.alt[data-v-63241e40]:active{border-color:var(--vp-button-alt-active-border);color:var(--vp-button-alt-active-text);background-color:var(--vp-button-alt-active-bg)}.VPButton.sponsor[data-v-63241e40]{border-color:var(--vp-button-sponsor-border);color:var(--vp-button-sponsor-text);background-color:var(--vp-button-sponsor-bg)}.VPButton.sponsor[data-v-63241e40]:hover{border-color:var(--vp-button-sponsor-hover-border);color:var(--vp-button-sponsor-hover-text);background-color:var(--vp-button-sponsor-hover-bg)}.VPButton.sponsor[data-v-63241e40]:active{border-color:var(--vp-button-sponsor-active-border);color:var(--vp-button-sponsor-active-text);background-color:var(--vp-button-sponsor-active-bg)}html:not(.dark) .VPImage.dark[data-v-cb1eaea6]{display:none}.dark .VPImage.light[data-v-cb1eaea6]{display:none}.VPHero[data-v-b8540496]{margin-top:calc((var(--vp-nav-height) + var(--vp-layout-top-height, 0px)) * -1);padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px) 24px 48px}@media (min-width: 640px){.VPHero[data-v-b8540496]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 48px 64px}}@media (min-width: 960px){.VPHero[data-v-b8540496]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 64px 64px}}.container[data-v-b8540496]{display:flex;flex-direction:column;margin:0 auto;max-width:1152px}@media (min-width: 960px){.container[data-v-b8540496]{flex-direction:row}}.main[data-v-b8540496]{position:relative;z-index:10;order:2;flex-grow:1;flex-shrink:0}.VPHero.has-image .container[data-v-b8540496]{text-align:center}@media (min-width: 960px){.VPHero.has-image .container[data-v-b8540496]{text-align:left}}@media (min-width: 960px){.main[data-v-b8540496]{order:1;width:calc((100% / 3) * 2)}.VPHero.has-image .main[data-v-b8540496]{max-width:592px}}.name[data-v-b8540496],.text[data-v-b8540496]{max-width:392px;letter-spacing:-.4px;line-height:40px;font-size:32px;font-weight:700;white-space:pre-wrap}.VPHero.has-image .name[data-v-b8540496],.VPHero.has-image .text[data-v-b8540496]{margin:0 auto}.name[data-v-b8540496]{color:var(--vp-home-hero-name-color)}.clip[data-v-b8540496]{background:var(--vp-home-hero-name-background);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:var(--vp-home-hero-name-color)}@media (min-width: 640px){.name[data-v-b8540496],.text[data-v-b8540496]{max-width:576px;line-height:56px;font-size:48px}}@media (min-width: 960px){.name[data-v-b8540496],.text[data-v-b8540496]{line-height:64px;font-size:56px}.VPHero.has-image .name[data-v-b8540496],.VPHero.has-image .text[data-v-b8540496]{margin:0}}.tagline[data-v-b8540496]{padding-top:8px;max-width:392px;line-height:28px;font-size:18px;font-weight:500;white-space:pre-wrap;color:var(--vp-c-text-2)}.VPHero.has-image .tagline[data-v-b8540496]{margin:0 auto}@media (min-width: 640px){.tagline[data-v-b8540496]{padding-top:12px;max-width:576px;line-height:32px;font-size:20px}}@media (min-width: 960px){.tagline[data-v-b8540496]{line-height:36px;font-size:24px}.VPHero.has-image .tagline[data-v-b8540496]{margin:0}}.actions[data-v-b8540496]{display:flex;flex-wrap:wrap;margin:-6px;padding-top:24px}.VPHero.has-image .actions[data-v-b8540496]{justify-content:center}@media (min-width: 640px){.actions[data-v-b8540496]{padding-top:32px}}@media (min-width: 960px){.VPHero.has-image .actions[data-v-b8540496]{justify-content:flex-start}}.action[data-v-b8540496]{flex-shrink:0;padding:6px}.image[data-v-b8540496]{order:1;margin:-76px -24px -48px}@media (min-width: 640px){.image[data-v-b8540496]{margin:-108px -24px -48px}}@media (min-width: 960px){.image[data-v-b8540496]{flex-grow:1;order:2;margin:0;min-height:100%}}.image-container[data-v-b8540496]{position:relative;margin:0 auto;width:320px;height:320px}@media (min-width: 640px){.image-container[data-v-b8540496]{width:392px;height:392px}}@media (min-width: 960px){.image-container[data-v-b8540496]{display:flex;justify-content:center;align-items:center;width:100%;height:100%;transform:translate(-32px,-32px)}}.image-bg[data-v-b8540496]{position:absolute;top:50%;left:50%;border-radius:50%;width:192px;height:192px;background-image:var(--vp-home-hero-image-background-image);filter:var(--vp-home-hero-image-filter);transform:translate(-50%,-50%)}@media (min-width: 640px){.image-bg[data-v-b8540496]{width:256px;height:256px}}@media (min-width: 960px){.image-bg[data-v-b8540496]{width:320px;height:320px}}[data-v-b8540496] .image-src{position:absolute;top:50%;left:50%;max-width:192px;max-height:192px;transform:translate(-50%,-50%)}@media (min-width: 640px){[data-v-b8540496] .image-src{max-width:256px;max-height:256px}}@media (min-width: 960px){[data-v-b8540496] .image-src{max-width:320px;max-height:320px}}.VPFeature[data-v-8870a6fd]{display:block;border:1px solid var(--vp-c-bg-soft);border-radius:12px;height:100%;background-color:var(--vp-c-bg-soft);transition:border-color .25s,background-color .25s}.VPFeature.link[data-v-8870a6fd]:hover{border-color:var(--vp-c-brand-1)}.box[data-v-8870a6fd]{display:flex;flex-direction:column;padding:24px;height:100%}.box[data-v-8870a6fd]>.VPImage{margin-bottom:20px}.icon[data-v-8870a6fd]{display:flex;justify-content:center;align-items:center;margin-bottom:20px;border-radius:6px;background-color:var(--vp-c-default-soft);width:48px;height:48px;font-size:24px;transition:background-color .25s}.title[data-v-8870a6fd]{line-height:24px;font-size:16px;font-weight:600}.details[data-v-8870a6fd]{flex-grow:1;padding-top:8px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.link-text[data-v-8870a6fd]{padding-top:8px}.link-text-value[data-v-8870a6fd]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.link-text-icon[data-v-8870a6fd]{display:inline-block;margin-left:6px;width:14px;height:14px;fill:currentColor}.VPFeatures[data-v-36653953]{position:relative;padding:0 24px}@media (min-width: 640px){.VPFeatures[data-v-36653953]{padding:0 48px}}@media (min-width: 960px){.VPFeatures[data-v-36653953]{padding:0 64px}}.container[data-v-36653953]{margin:0 auto;max-width:1152px}.items[data-v-36653953]{display:flex;flex-wrap:wrap;margin:-8px}.item[data-v-36653953]{padding:8px;width:100%}@media (min-width: 640px){.item.grid-2[data-v-36653953],.item.grid-4[data-v-36653953],.item.grid-6[data-v-36653953]{width:50%}}@media (min-width: 768px){.item.grid-2[data-v-36653953],.item.grid-4[data-v-36653953]{width:50%}.item.grid-3[data-v-36653953],.item.grid-6[data-v-36653953]{width:calc(100% / 3)}}@media (min-width: 960px){.item.grid-4[data-v-36653953]{width:25%}}.VPHome[data-v-a55404ac]{padding-bottom:96px}.VPHome[data-v-a55404ac] .VPHomeSponsors{margin-top:112px;margin-bottom:-128px}@media (min-width: 768px){.VPHome[data-v-a55404ac]{padding-bottom:128px}}.VPContent[data-v-bed13fc1]{flex-grow:1;flex-shrink:0;margin:var(--vp-layout-top-height, 0px) auto 0;width:100%}.VPContent.is-home[data-v-bed13fc1]{width:100%;max-width:100%}.VPContent.has-sidebar[data-v-bed13fc1]{margin:0}@media (min-width: 960px){.VPContent[data-v-bed13fc1]{padding-top:var(--vp-nav-height)}.VPContent.has-sidebar[data-v-bed13fc1]{margin:var(--vp-layout-top-height, 0px) 0 0;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPContent.has-sidebar[data-v-bed13fc1]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.VPFooter[data-v-e6702d68]{position:relative;z-index:var(--vp-z-index-footer);border-top:1px solid var(--vp-c-gutter);padding:32px 24px;background-color:var(--vp-c-bg)}.VPFooter.has-sidebar[data-v-e6702d68]{display:none}.VPFooter[data-v-e6702d68] a{text-decoration-line:underline;text-underline-offset:2px;transition:color .25s}.VPFooter[data-v-e6702d68] a:hover{color:var(--vp-c-text-1)}@media (min-width: 768px){.VPFooter[data-v-e6702d68]{padding:32px}}.container[data-v-e6702d68]{margin:0 auto;max-width:var(--vp-layout-max-width);text-align:center}.message[data-v-e6702d68],.copyright[data-v-e6702d68]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.VPLocalNavOutlineDropdown[data-v-6839e2e2]{padding:12px 20px 11px}@media (min-width: 960px){.VPLocalNavOutlineDropdown[data-v-6839e2e2]{padding:12px 36px 11px}}.VPLocalNavOutlineDropdown button[data-v-6839e2e2]{display:block;font-size:12px;font-weight:500;line-height:24px;color:var(--vp-c-text-2);transition:color .5s;position:relative}.VPLocalNavOutlineDropdown button[data-v-6839e2e2]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPLocalNavOutlineDropdown button.open[data-v-6839e2e2]{color:var(--vp-c-text-1)}@media (min-width: 960px){.VPLocalNavOutlineDropdown button[data-v-6839e2e2]{font-size:14px}}.icon[data-v-6839e2e2]{display:inline-block;vertical-align:middle;margin-left:2px;width:14px;height:14px;fill:currentColor}.open>.icon[data-v-6839e2e2]{transform:rotate(90deg)}.items[data-v-6839e2e2]{position:absolute;top:40px;right:16px;left:16px;display:grid;gap:1px;border:1px solid var(--vp-c-border);border-radius:8px;background-color:var(--vp-c-gutter);max-height:calc(var(--vp-vh, 100vh) - 86px);overflow:hidden auto;box-shadow:var(--vp-shadow-3)}@media (min-width: 960px){.items[data-v-6839e2e2]{right:auto;left:calc(var(--vp-sidebar-width) + 32px);width:320px}}.header[data-v-6839e2e2]{background-color:var(--vp-c-bg-soft)}.top-link[data-v-6839e2e2]{display:block;padding:0 16px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.outline[data-v-6839e2e2]{padding:8px 0;background-color:var(--vp-c-bg-soft)}.flyout-enter-active[data-v-6839e2e2]{transition:all .2s ease-out}.flyout-leave-active[data-v-6839e2e2]{transition:all .15s ease-in}.flyout-enter-from[data-v-6839e2e2],.flyout-leave-to[data-v-6839e2e2]{opacity:0;transform:translateY(-16px)}.VPLocalNav[data-v-e1a8fe1a]{position:sticky;top:0;left:0;z-index:var(--vp-z-index-local-nav);border-bottom:1px solid var(--vp-c-gutter);padding-top:var(--vp-layout-top-height, 0px);width:100%;background-color:var(--vp-local-nav-bg-color)}.VPLocalNav.fixed[data-v-e1a8fe1a]{position:fixed}@media (min-width: 960px){.VPLocalNav[data-v-e1a8fe1a]{top:var(--vp-nav-height)}.VPLocalNav.has-sidebar[data-v-e1a8fe1a]{padding-left:var(--vp-sidebar-width)}.VPLocalNav.empty[data-v-e1a8fe1a]{display:none}}@media (min-width: 1280px){.VPLocalNav[data-v-e1a8fe1a]{display:none}}@media (min-width: 1440px){.VPLocalNav.has-sidebar[data-v-e1a8fe1a]{padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.container[data-v-e1a8fe1a]{display:flex;justify-content:space-between;align-items:center}.menu[data-v-e1a8fe1a]{display:flex;align-items:center;padding:12px 24px 11px;line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.menu[data-v-e1a8fe1a]:hover{color:var(--vp-c-text-1);transition:color .25s}@media (min-width: 768px){.menu[data-v-e1a8fe1a]{padding:0 32px}}@media (min-width: 960px){.menu[data-v-e1a8fe1a]{display:none}}.menu-icon[data-v-e1a8fe1a]{margin-right:8px;width:16px;height:16px;fill:currentColor}.VPOutlineDropdown[data-v-e1a8fe1a]{padding:12px 24px 11px}@media (min-width: 768px){.VPOutlineDropdown[data-v-e1a8fe1a]{padding:12px 32px 11px}}.VPSwitch[data-v-9f4da114]{position:relative;border-radius:11px;display:block;width:40px;height:22px;flex-shrink:0;border:1px solid var(--vp-input-border-color);background-color:var(--vp-input-switch-bg-color);transition:border-color .25s!important}.VPSwitch[data-v-9f4da114]:hover{border-color:var(--vp-c-brand-1)}.check[data-v-9f4da114]{position:absolute;top:1px;left:1px;width:18px;height:18px;border-radius:50%;background-color:var(--vp-c-neutral-inverse);box-shadow:var(--vp-shadow-1);transition:transform .25s!important}.icon[data-v-9f4da114]{position:relative;display:block;width:18px;height:18px;border-radius:50%;overflow:hidden}.icon[data-v-9f4da114] svg{position:absolute;top:3px;left:3px;width:12px;height:12px;fill:var(--vp-c-text-2)}.dark .icon[data-v-9f4da114] svg{fill:var(--vp-c-text-1);transition:opacity .25s!important}.sun[data-v-2685bbb5]{opacity:1}.moon[data-v-2685bbb5],.dark .sun[data-v-2685bbb5]{opacity:0}.dark .moon[data-v-2685bbb5]{opacity:1}.dark .VPSwitchAppearance[data-v-2685bbb5] .check{transform:translate(18px)}.VPNavBarAppearance[data-v-ba4bea8e]{display:none}@media (min-width: 1280px){.VPNavBarAppearance[data-v-ba4bea8e]{display:flex;align-items:center}}.VPMenuGroup+.VPMenuLink[data-v-4ed5728d]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.link[data-v-4ed5728d]{display:block;border-radius:6px;padding:0 12px;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);white-space:nowrap;transition:background-color .25s,color .25s}.link[data-v-4ed5728d]:hover{color:var(--vp-c-brand-1);background-color:var(--vp-c-default-soft)}.link.active[data-v-4ed5728d]{color:var(--vp-c-brand-1)}.VPMenuGroup[data-v-dcb0eb15]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.VPMenuGroup[data-v-dcb0eb15]:first-child{margin-top:0;border-top:0;padding-top:0}.VPMenuGroup+.VPMenuGroup[data-v-dcb0eb15]{margin-top:12px;border-top:1px solid var(--vp-c-divider)}.title[data-v-dcb0eb15]{padding:0 12px;line-height:32px;font-size:14px;font-weight:600;color:var(--vp-c-text-2);white-space:nowrap;transition:color .25s}.VPMenu[data-v-70f7bea4]{border-radius:12px;padding:12px;min-width:128px;border:1px solid var(--vp-c-divider);background-color:var(--vp-c-bg-elv);box-shadow:var(--vp-shadow-3);transition:background-color .5s;max-height:calc(100vh - var(--vp-nav-height));overflow-y:auto}.VPMenu[data-v-70f7bea4] .group{margin:0 -12px;padding:0 12px 12px}.VPMenu[data-v-70f7bea4] .group+.group{border-top:1px solid var(--vp-c-divider);padding:11px 12px 12px}.VPMenu[data-v-70f7bea4] .group:last-child{padding-bottom:0}.VPMenu[data-v-70f7bea4] .group+.item{border-top:1px solid var(--vp-c-divider);padding:11px 16px 0}.VPMenu[data-v-70f7bea4] .item{padding:0 16px;white-space:nowrap}.VPMenu[data-v-70f7bea4] .label{flex-grow:1;line-height:28px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.VPMenu[data-v-70f7bea4] .action{padding-left:24px}.VPFlyout[data-v-d96262ab]{position:relative}.VPFlyout[data-v-d96262ab]:hover{color:var(--vp-c-brand-1);transition:color .25s}.VPFlyout:hover .text[data-v-d96262ab]{color:var(--vp-c-text-2)}.VPFlyout:hover .icon[data-v-d96262ab]{fill:var(--vp-c-text-2)}.VPFlyout.active .text[data-v-d96262ab]{color:var(--vp-c-brand-1)}.VPFlyout.active:hover .text[data-v-d96262ab]{color:var(--vp-c-brand-2)}.VPFlyout:hover .menu[data-v-d96262ab],.button[aria-expanded=true]+.menu[data-v-d96262ab]{opacity:1;visibility:visible;transform:translateY(0)}.button[aria-expanded=false]+.menu[data-v-d96262ab]{opacity:0;visibility:hidden;transform:translateY(0)}.button[data-v-d96262ab]{display:flex;align-items:center;padding:0 12px;height:var(--vp-nav-height);color:var(--vp-c-text-1);transition:color .5s}.text[data-v-d96262ab]{display:flex;align-items:center;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.option-icon[data-v-d96262ab]{margin-right:0;width:16px;height:16px;fill:currentColor}.text-icon[data-v-d96262ab]{margin-left:4px;width:14px;height:14px;fill:currentColor}.icon[data-v-d96262ab]{width:20px;height:20px;fill:currentColor;transition:fill .25s}.menu[data-v-d96262ab]{position:absolute;top:calc(var(--vp-nav-height) / 2 + 20px);right:0;opacity:0;visibility:hidden;transition:opacity .25s,visibility .25s,transform .25s}.VPSocialLink[data-v-adfe1698]{display:flex;justify-content:center;align-items:center;width:36px;height:36px;color:var(--vp-c-text-2);transition:color .5s}.VPSocialLink[data-v-adfe1698]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPSocialLink[data-v-adfe1698]>svg{width:20px;height:20px;fill:currentColor}.VPSocialLinks[data-v-211dec16]{display:flex;justify-content:center}.VPNavBarExtra[data-v-ee189185]{display:none;margin-right:-12px}@media (min-width: 768px){.VPNavBarExtra[data-v-ee189185]{display:block}}@media (min-width: 1280px){.VPNavBarExtra[data-v-ee189185]{display:none}}.trans-title[data-v-ee189185]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.item.appearance[data-v-ee189185],.item.social-links[data-v-ee189185]{display:flex;align-items:center;padding:0 12px}.item.appearance[data-v-ee189185]{min-width:176px}.appearance-action[data-v-ee189185]{margin-right:-2px}.social-links-list[data-v-ee189185]{margin:-4px -8px}.VPNavBarHamburger[data-v-4146a2ef]{display:flex;justify-content:center;align-items:center;width:48px;height:var(--vp-nav-height)}@media (min-width: 768px){.VPNavBarHamburger[data-v-4146a2ef]{display:none}}.container[data-v-4146a2ef]{position:relative;width:16px;height:14px;overflow:hidden}.VPNavBarHamburger:hover .top[data-v-4146a2ef]{top:0;left:0;transform:translate(4px)}.VPNavBarHamburger:hover .middle[data-v-4146a2ef]{top:6px;left:0;transform:translate(0)}.VPNavBarHamburger:hover .bottom[data-v-4146a2ef]{top:12px;left:0;transform:translate(8px)}.VPNavBarHamburger.active .top[data-v-4146a2ef]{top:6px;transform:translate(0) rotate(225deg)}.VPNavBarHamburger.active .middle[data-v-4146a2ef]{top:6px;transform:translate(16px)}.VPNavBarHamburger.active .bottom[data-v-4146a2ef]{top:6px;transform:translate(0) rotate(135deg)}.VPNavBarHamburger.active:hover .top[data-v-4146a2ef],.VPNavBarHamburger.active:hover .middle[data-v-4146a2ef],.VPNavBarHamburger.active:hover .bottom[data-v-4146a2ef]{background-color:var(--vp-c-text-2);transition:top .25s,background-color .25s,transform .25s}.top[data-v-4146a2ef],.middle[data-v-4146a2ef],.bottom[data-v-4146a2ef]{position:absolute;width:16px;height:2px;background-color:var(--vp-c-text-1);transition:top .25s,background-color .5s,transform .25s}.top[data-v-4146a2ef]{top:0;left:0;transform:translate(0)}.middle[data-v-4146a2ef]{top:6px;left:0;transform:translate(8px)}.bottom[data-v-4146a2ef]{top:12px;left:0;transform:translate(4px)}.VPNavBarMenuLink[data-v-07e86fd5]{display:flex;align-items:center;padding:0 12px;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.VPNavBarMenuLink.active[data-v-07e86fd5],.VPNavBarMenuLink[data-v-07e86fd5]:hover{color:var(--vp-c-brand-1)}.VPNavBarMenu[data-v-0c4c2f33]{display:none}@media (min-width: 768px){.VPNavBarMenu[data-v-0c4c2f33]{display:flex}}/*! @docsearch/css 3.5.2 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */:root{--docsearch-primary-color:#5468ff;--docsearch-text-color:#1c1e21;--docsearch-spacing:12px;--docsearch-icon-stroke-width:1.4;--docsearch-highlight-color:var(--docsearch-primary-color);--docsearch-muted-color:#969faf;--docsearch-container-background:rgba(101,108,133,.8);--docsearch-logo-color:#5468ff;--docsearch-modal-width:560px;--docsearch-modal-height:600px;--docsearch-modal-background:#f5f6f7;--docsearch-modal-shadow:inset 1px 1px 0 0 hsla(0,0%,100%,.5),0 3px 8px 0 #555a64;--docsearch-searchbox-height:56px;--docsearch-searchbox-background:#ebedf0;--docsearch-searchbox-focus-background:#fff;--docsearch-searchbox-shadow:inset 0 0 0 2px var(--docsearch-primary-color);--docsearch-hit-height:56px;--docsearch-hit-color:#444950;--docsearch-hit-active-color:#fff;--docsearch-hit-background:#fff;--docsearch-hit-shadow:0 1px 3px 0 #d4d9e1;--docsearch-key-gradient:linear-gradient(-225deg,#d5dbe4,#f8f8f8);--docsearch-key-shadow:inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 2px 1px rgba(30,35,90,.4);--docsearch-footer-height:44px;--docsearch-footer-background:#fff;--docsearch-footer-shadow:0 -1px 0 0 #e0e3e8,0 -3px 6px 0 rgba(69,98,155,.12)}html[data-theme=dark]{--docsearch-text-color:#f5f6f7;--docsearch-container-background:rgba(9,10,17,.8);--docsearch-modal-background:#15172a;--docsearch-modal-shadow:inset 1px 1px 0 0 #2c2e40,0 3px 8px 0 #000309;--docsearch-searchbox-background:#090a11;--docsearch-searchbox-focus-background:#000;--docsearch-hit-color:#bec3c9;--docsearch-hit-shadow:none;--docsearch-hit-background:#090a11;--docsearch-key-gradient:linear-gradient(-26.5deg,#565872,#31355b);--docsearch-key-shadow:inset 0 -2px 0 0 #282d55,inset 0 0 1px 1px #51577d,0 2px 2px 0 rgba(3,4,9,.3);--docsearch-footer-background:#1e2136;--docsearch-footer-shadow:inset 0 1px 0 0 rgba(73,76,106,.5),0 -4px 8px 0 rgba(0,0,0,.2);--docsearch-logo-color:#fff;--docsearch-muted-color:#7f8497}.DocSearch-Button{align-items:center;background:var(--docsearch-searchbox-background);border:0;border-radius:40px;color:var(--docsearch-muted-color);cursor:pointer;display:flex;font-weight:500;height:36px;justify-content:space-between;margin:0 0 0 16px;padding:0 8px;-webkit-user-select:none;user-select:none}.DocSearch-Button:active,.DocSearch-Button:focus,.DocSearch-Button:hover{background:var(--docsearch-searchbox-focus-background);box-shadow:var(--docsearch-searchbox-shadow);color:var(--docsearch-text-color);outline:none}.DocSearch-Button-Container{align-items:center;display:flex}.DocSearch-Search-Icon{stroke-width:1.6}.DocSearch-Button .DocSearch-Search-Icon{color:var(--docsearch-text-color)}.DocSearch-Button-Placeholder{font-size:1rem;padding:0 12px 0 6px}.DocSearch-Button-Keys{display:flex;min-width:calc(40px + .8em)}.DocSearch-Button-Key{align-items:center;background:var(--docsearch-key-gradient);border-radius:3px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);display:flex;height:18px;justify-content:center;margin-right:.4em;position:relative;padding:0 0 2px;border:0;top:-1px;width:20px}@media (max-width:768px){.DocSearch-Button-Keys,.DocSearch-Button-Placeholder{display:none}}.DocSearch--active{overflow:hidden!important}.DocSearch-Container,.DocSearch-Container *{box-sizing:border-box}.DocSearch-Container{background-color:var(--docsearch-container-background);height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:200}.DocSearch-Container a{text-decoration:none}.DocSearch-Link{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;font:inherit;margin:0;padding:0}.DocSearch-Modal{background:var(--docsearch-modal-background);border-radius:6px;box-shadow:var(--docsearch-modal-shadow);flex-direction:column;margin:60px auto auto;max-width:var(--docsearch-modal-width);position:relative}.DocSearch-SearchBar{display:flex;padding:var(--docsearch-spacing) var(--docsearch-spacing) 0}.DocSearch-Form{align-items:center;background:var(--docsearch-searchbox-focus-background);border-radius:4px;box-shadow:var(--docsearch-searchbox-shadow);display:flex;height:var(--docsearch-searchbox-height);margin:0;padding:0 var(--docsearch-spacing);position:relative;width:100%}.DocSearch-Input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:0;color:var(--docsearch-text-color);flex:1;font:inherit;font-size:1.2em;height:100%;outline:none;padding:0 0 0 8px;width:80%}.DocSearch-Input::placeholder{color:var(--docsearch-muted-color);opacity:1}.DocSearch-Input::-webkit-search-cancel-button,.DocSearch-Input::-webkit-search-decoration,.DocSearch-Input::-webkit-search-results-button,.DocSearch-Input::-webkit-search-results-decoration{display:none}.DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel,.DocSearch-Reset{margin:0;padding:0}.DocSearch-MagnifierLabel,.DocSearch-Reset{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}.DocSearch-Container--Stalled .DocSearch-MagnifierLabel,.DocSearch-LoadingIndicator{display:none}.DocSearch-Container--Stalled .DocSearch-LoadingIndicator{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Reset{animation:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;right:0;stroke-width:var(--docsearch-icon-stroke-width)}}.DocSearch-Reset{animation:fade-in .1s ease-in forwards;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;padding:2px;right:0;stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Reset[hidden]{display:none}.DocSearch-Reset:hover{color:var(--docsearch-highlight-color)}.DocSearch-LoadingIndicator svg,.DocSearch-MagnifierLabel svg{height:24px;width:24px}.DocSearch-Cancel{display:none}.DocSearch-Dropdown{max-height:calc(var(--docsearch-modal-height) - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height));min-height:var(--docsearch-spacing);overflow-y:auto;overflow-y:overlay;padding:0 var(--docsearch-spacing);scrollbar-color:var(--docsearch-muted-color) var(--docsearch-modal-background);scrollbar-width:thin}.DocSearch-Dropdown::-webkit-scrollbar{width:12px}.DocSearch-Dropdown::-webkit-scrollbar-track{background:transparent}.DocSearch-Dropdown::-webkit-scrollbar-thumb{background-color:var(--docsearch-muted-color);border:3px solid var(--docsearch-modal-background);border-radius:20px}.DocSearch-Dropdown ul{list-style:none;margin:0;padding:0}.DocSearch-Label{font-size:.75em;line-height:1.6em}.DocSearch-Help,.DocSearch-Label{color:var(--docsearch-muted-color)}.DocSearch-Help{font-size:.9em;margin:0;-webkit-user-select:none;user-select:none}.DocSearch-Title{font-size:1.2em}.DocSearch-Logo a{display:flex}.DocSearch-Logo svg{color:var(--docsearch-logo-color);margin-left:8px}.DocSearch-Hits:last-of-type{margin-bottom:24px}.DocSearch-Hits mark{background:none;color:var(--docsearch-highlight-color)}.DocSearch-HitsFooter{color:var(--docsearch-muted-color);display:flex;font-size:.85em;justify-content:center;margin-bottom:var(--docsearch-spacing);padding:var(--docsearch-spacing)}.DocSearch-HitsFooter a{border-bottom:1px solid;color:inherit}.DocSearch-Hit{border-radius:4px;display:flex;padding-bottom:4px;position:relative}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--deleting{transition:none}}.DocSearch-Hit--deleting{opacity:0;transition:all .25s linear}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--favoriting{transition:none}}.DocSearch-Hit--favoriting{transform:scale(0);transform-origin:top center;transition:all .25s linear;transition-delay:.25s}.DocSearch-Hit a{background:var(--docsearch-hit-background);border-radius:4px;box-shadow:var(--docsearch-hit-shadow);display:block;padding-left:var(--docsearch-spacing);width:100%}.DocSearch-Hit-source{background:var(--docsearch-modal-background);color:var(--docsearch-highlight-color);font-size:.85em;font-weight:600;line-height:32px;margin:0 -4px;padding:8px 4px 0;position:sticky;top:0;z-index:10}.DocSearch-Hit-Tree{color:var(--docsearch-muted-color);height:var(--docsearch-hit-height);opacity:.5;stroke-width:var(--docsearch-icon-stroke-width);width:24px}.DocSearch-Hit[aria-selected=true] a{background-color:var(--docsearch-highlight-color)}.DocSearch-Hit[aria-selected=true] mark{text-decoration:underline}.DocSearch-Hit-Container{align-items:center;color:var(--docsearch-hit-color);display:flex;flex-direction:row;height:var(--docsearch-hit-height);padding:0 var(--docsearch-spacing) 0 0}.DocSearch-Hit-icon{height:20px;width:20px}.DocSearch-Hit-action,.DocSearch-Hit-icon{color:var(--docsearch-muted-color);stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Hit-action{align-items:center;display:flex;height:22px;width:22px}.DocSearch-Hit-action svg{display:block;height:18px;width:18px}.DocSearch-Hit-action+.DocSearch-Hit-action{margin-left:6px}.DocSearch-Hit-action-button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:inherit;cursor:pointer;padding:2px}svg.DocSearch-Hit-Select-Icon{display:none}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Select-Icon{display:block}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:#0003;transition:background-color .1s ease-in}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{transition:none}}.DocSearch-Hit-action-button:focus path,.DocSearch-Hit-action-button:hover path{fill:#fff}.DocSearch-Hit-content-wrapper{display:flex;flex:1 1 auto;flex-direction:column;font-weight:500;justify-content:center;line-height:1.2em;margin:0 8px;overflow-x:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:80%}.DocSearch-Hit-title{font-size:.9em}.DocSearch-Hit-path{color:var(--docsearch-muted-color);font-size:.75em}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-action,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-icon,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-path,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-text,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-title,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Tree,.DocSearch-Hit[aria-selected=true] mark{color:var(--docsearch-hit-active-color)!important}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:#0003;transition:none}}.DocSearch-ErrorScreen,.DocSearch-NoResults,.DocSearch-StartScreen{font-size:.9em;margin:0 auto;padding:36px 0;text-align:center;width:80%}.DocSearch-Screen-Icon{color:var(--docsearch-muted-color);padding-bottom:12px}.DocSearch-NoResults-Prefill-List{display:inline-block;padding-bottom:24px;text-align:left}.DocSearch-NoResults-Prefill-List ul{display:inline-block;padding:8px 0 0}.DocSearch-NoResults-Prefill-List li{list-style-position:inside;list-style-type:"» "}.DocSearch-Prefill{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:1em;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;font-size:1em;font-weight:700;padding:0}.DocSearch-Prefill:focus,.DocSearch-Prefill:hover{outline:none;text-decoration:underline}.DocSearch-Footer{align-items:center;background:var(--docsearch-footer-background);border-radius:0 0 8px 8px;box-shadow:var(--docsearch-footer-shadow);display:flex;flex-direction:row-reverse;flex-shrink:0;height:var(--docsearch-footer-height);justify-content:space-between;padding:0 var(--docsearch-spacing);position:relative;-webkit-user-select:none;user-select:none;width:100%;z-index:300}.DocSearch-Commands{color:var(--docsearch-muted-color);display:flex;list-style:none;margin:0;padding:0}.DocSearch-Commands li{align-items:center;display:flex}.DocSearch-Commands li:not(:last-of-type){margin-right:.8em}.DocSearch-Commands-Key{align-items:center;background:var(--docsearch-key-gradient);border-radius:2px;box-shadow:var(--docsearch-key-shadow);display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 1px;color:var(--docsearch-muted-color);border:0;width:20px}@media (max-width:768px){:root{--docsearch-spacing:10px;--docsearch-footer-height:40px}.DocSearch-Dropdown{height:100%}.DocSearch-Container{height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);position:absolute}.DocSearch-Footer{border-radius:0;bottom:0;position:absolute}.DocSearch-Hit-content-wrapper{display:flex;position:relative;width:80%}.DocSearch-Modal{border-radius:0;box-shadow:none;height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);margin:0;max-width:100%;width:100%}.DocSearch-Dropdown{max-height:calc(var(--docsearch-vh, 1vh)*100 - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height))}.DocSearch-Cancel{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;flex:none;font:inherit;font-size:1em;font-weight:500;margin-left:var(--docsearch-spacing);outline:none;overflow:hidden;padding:0;-webkit-user-select:none;user-select:none;white-space:nowrap}.DocSearch-Commands,.DocSearch-Hit-Tree{display:none}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}[class*=DocSearch]{--docsearch-primary-color: var(--vp-c-brand-1);--docsearch-highlight-color: var(--docsearch-primary-color);--docsearch-text-color: var(--vp-c-text-1);--docsearch-muted-color: var(--vp-c-text-2);--docsearch-searchbox-shadow: none;--docsearch-searchbox-background: transparent;--docsearch-searchbox-focus-background: transparent;--docsearch-key-gradient: transparent;--docsearch-key-shadow: none;--docsearch-modal-background: var(--vp-c-bg-soft);--docsearch-footer-background: var(--vp-c-bg)}.dark [class*=DocSearch]{--docsearch-modal-shadow: none;--docsearch-footer-shadow: none;--docsearch-logo-color: var(--vp-c-text-2);--docsearch-hit-background: var(--vp-c-default-soft);--docsearch-hit-color: var(--vp-c-text-2);--docsearch-hit-shadow: none}.DocSearch-Button{display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:48px;height:55px;background:transparent;transition:border-color .25s}.DocSearch-Button:hover{background:transparent}.DocSearch-Button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.DocSearch-Button:focus:not(:focus-visible){outline:none!important}@media (min-width: 768px){.DocSearch-Button{justify-content:flex-start;border:1px solid transparent;border-radius:8px;padding:0 10px 0 12px;width:100%;height:40px;background-color:var(--vp-c-bg-alt)}.DocSearch-Button:hover{border-color:var(--vp-c-brand-1);background:var(--vp-c-bg-alt)}}.DocSearch-Button .DocSearch-Button-Container{display:flex;align-items:center}.DocSearch-Button .DocSearch-Search-Icon{position:relative;width:16px;height:16px;color:var(--vp-c-text-1);fill:currentColor;transition:color .5s}.DocSearch-Button:hover .DocSearch-Search-Icon{color:var(--vp-c-text-1)}@media (min-width: 768px){.DocSearch-Button .DocSearch-Search-Icon{top:1px;margin-right:8px;width:14px;height:14px;color:var(--vp-c-text-2)}}.DocSearch-Button .DocSearch-Button-Placeholder{display:none;margin-top:2px;padding:0 16px 0 0;font-size:13px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.DocSearch-Button:hover .DocSearch-Button-Placeholder{color:var(--vp-c-text-1)}@media (min-width: 768px){.DocSearch-Button .DocSearch-Button-Placeholder{display:inline-block}}.DocSearch-Button .DocSearch-Button-Keys{direction:ltr;display:none;min-width:auto}@media (min-width: 768px){.DocSearch-Button .DocSearch-Button-Keys{display:flex;align-items:center}}.DocSearch-Button .DocSearch-Button-Key{display:block;margin:2px 0 0;border:1px solid var(--vp-c-divider);border-right:none;border-radius:4px 0 0 4px;padding-left:6px;min-width:0;width:auto;height:22px;line-height:22px;font-family:var(--vp-font-family-base);font-size:12px;font-weight:500;transition:color .5s,border-color .5s}.DocSearch-Button .DocSearch-Button-Key+.DocSearch-Button-Key{border-right:1px solid var(--vp-c-divider);border-left:none;border-radius:0 4px 4px 0;padding-left:2px;padding-right:6px}.DocSearch-Button .DocSearch-Button-Key:first-child{font-size:0!important}.DocSearch-Button .DocSearch-Button-Key:first-child:after{content:"Ctrl";font-size:12px;letter-spacing:normal;color:var(--docsearch-muted-color)}.mac .DocSearch-Button .DocSearch-Button-Key:first-child:after{content:"⌘"}.DocSearch-Button .DocSearch-Button-Key:first-child>*{display:none}.VPNavBarSearch{display:flex;align-items:center}@media (min-width: 768px){.VPNavBarSearch{flex-grow:1;padding-left:24px}}@media (min-width: 960px){.VPNavBarSearch{padding-left:32px}}.dark .DocSearch-Footer{border-top:1px solid var(--vp-c-divider)}.DocSearch-Form{border:1px solid var(--vp-c-brand-1);background-color:var(--vp-c-white)}.dark .DocSearch-Form{background-color:var(--vp-c-default-soft)}.DocSearch-Screen-Icon>svg{margin:auto}.VPNavBarSocialLinks[data-v-7a5f4317]{display:none}@media (min-width: 1280px){.VPNavBarSocialLinks[data-v-7a5f4317]{display:flex;align-items:center}}.title[data-v-fb02e02e]{display:flex;align-items:center;border-bottom:1px solid transparent;width:100%;height:var(--vp-nav-height);font-size:16px;font-weight:600;color:var(--vp-c-text-1);transition:opacity .25s}@media (min-width: 960px){.title[data-v-fb02e02e]{flex-shrink:0}.VPNavBarTitle.has-sidebar .title[data-v-fb02e02e]{border-bottom-color:var(--vp-c-divider)}}[data-v-fb02e02e] .logo{margin-right:8px;height:var(--vp-nav-logo-height)}.VPNavBarTranslations[data-v-505f8924]{display:none}@media (min-width: 1280px){.VPNavBarTranslations[data-v-505f8924]{display:flex;align-items:center}}.title[data-v-505f8924]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.VPNavBar[data-v-c292e453]{position:relative;height:var(--vp-nav-height);pointer-events:none;white-space:nowrap;transition:background-color .5s}.VPNavBar.has-local-nav[data-v-c292e453]{background-color:var(--vp-nav-bg-color)}@media (min-width: 960px){.VPNavBar.has-local-nav[data-v-c292e453]{background-color:transparent}.VPNavBar[data-v-c292e453]:not(.has-sidebar):not(.top){background-color:var(--vp-nav-bg-color)}}.wrapper[data-v-c292e453]{padding:0 8px 0 24px}@media (min-width: 768px){.wrapper[data-v-c292e453]{padding:0 32px}}@media (min-width: 960px){.VPNavBar.has-sidebar .wrapper[data-v-c292e453]{padding:0}}.container[data-v-c292e453]{display:flex;justify-content:space-between;margin:0 auto;max-width:calc(var(--vp-layout-max-width) - 64px);height:var(--vp-nav-height);pointer-events:none}.container>.title[data-v-c292e453],.container>.content[data-v-c292e453]{pointer-events:none}.container[data-v-c292e453] *{pointer-events:auto}@media (min-width: 960px){.VPNavBar.has-sidebar .container[data-v-c292e453]{max-width:100%}}.title[data-v-c292e453]{flex-shrink:0;height:calc(var(--vp-nav-height) - 1px);transition:background-color .5s}@media (min-width: 960px){.VPNavBar.has-sidebar .title[data-v-c292e453]{position:absolute;top:0;left:0;z-index:2;padding:0 32px;width:var(--vp-sidebar-width);height:var(--vp-nav-height);background-color:transparent}}@media (min-width: 1440px){.VPNavBar.has-sidebar .title[data-v-c292e453]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}.content[data-v-c292e453]{flex-grow:1}@media (min-width: 960px){.VPNavBar.has-sidebar .content[data-v-c292e453]{position:relative;z-index:1;padding-right:32px;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPNavBar.has-sidebar .content[data-v-c292e453]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2 + 32px);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.content-body[data-v-c292e453]{display:flex;justify-content:flex-end;align-items:center;height:var(--vp-nav-height);transition:background-color .5s}@media (min-width: 960px){.VPNavBar:not(.top) .content-body[data-v-c292e453]{position:relative;background-color:var(--vp-nav-bg-color)}.VPNavBar:not(.has-sidebar):not(.top) .content-body[data-v-c292e453]{background-color:transparent}}@media (max-width: 767px){.content-body[data-v-c292e453]{column-gap:.5rem}}.menu+.translations[data-v-c292e453]:before,.menu+.appearance[data-v-c292e453]:before,.menu+.social-links[data-v-c292e453]:before,.translations+.appearance[data-v-c292e453]:before,.appearance+.social-links[data-v-c292e453]:before{margin-right:8px;margin-left:8px;width:1px;height:24px;background-color:var(--vp-c-divider);content:""}.menu+.appearance[data-v-c292e453]:before,.translations+.appearance[data-v-c292e453]:before{margin-right:16px}.appearance+.social-links[data-v-c292e453]:before{margin-left:16px}.social-links[data-v-c292e453]{margin-right:-8px}.divider[data-v-c292e453]{width:100%;height:1px}@media (min-width: 960px){.VPNavBar.has-sidebar .divider[data-v-c292e453]{padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPNavBar.has-sidebar .divider[data-v-c292e453]{padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.divider-line[data-v-c292e453]{width:100%;height:1px;transition:background-color .5s}.VPNavBar.has-local-nav .divider-line[data-v-c292e453]{background-color:var(--vp-c-gutter)}@media (min-width: 960px){.VPNavBar:not(.top) .divider-line[data-v-c292e453]{background-color:var(--vp-c-gutter)}.VPNavBar:not(.has-sidebar):not(.top) .divider[data-v-c292e453]{background-color:var(--vp-c-gutter)}}.VPNavScreenAppearance[data-v-a7a418c5]{display:flex;justify-content:space-between;align-items:center;border-radius:8px;padding:12px 14px 12px 16px;background-color:var(--vp-c-bg-soft)}.text[data-v-a7a418c5]{line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.VPNavScreenMenuLink[data-v-defd5a1e]{display:block;border-bottom:1px solid var(--vp-c-divider);padding:12px 0 11px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:border-color .25s,color .25s}.VPNavScreenMenuLink[data-v-defd5a1e]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupLink[data-v-c6f96b6c]{display:block;margin-left:12px;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-1);transition:color .25s}.VPNavScreenMenuGroupLink[data-v-c6f96b6c]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupSection[data-v-d9999553]{display:block}.title[data-v-d9999553]{line-height:32px;font-size:13px;font-weight:700;color:var(--vp-c-text-2);transition:color .25s}.VPNavScreenMenuGroup[data-v-fae047cc]{border-bottom:1px solid var(--vp-c-divider);height:48px;overflow:hidden;transition:border-color .5s}.VPNavScreenMenuGroup .items[data-v-fae047cc]{visibility:hidden}.VPNavScreenMenuGroup.open .items[data-v-fae047cc]{visibility:visible}.VPNavScreenMenuGroup.open[data-v-fae047cc]{padding-bottom:10px;height:auto}.VPNavScreenMenuGroup.open .button[data-v-fae047cc]{padding-bottom:6px;color:var(--vp-c-brand-1)}.VPNavScreenMenuGroup.open .button-icon[data-v-fae047cc]{transform:rotate(45deg)}.button[data-v-fae047cc]{display:flex;justify-content:space-between;align-items:center;padding:12px 4px 11px 0;width:100%;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.button[data-v-fae047cc]:hover{color:var(--vp-c-brand-1)}.button-icon[data-v-fae047cc]{width:14px;height:14px;fill:var(--vp-c-text-2);transition:fill .5s,transform .25s}.group[data-v-fae047cc]:first-child{padding-top:0}.group+.group[data-v-fae047cc],.group+.item[data-v-fae047cc]{padding-top:4px}.VPNavScreenTranslations[data-v-62d810e0]{height:24px;overflow:hidden}.VPNavScreenTranslations.open[data-v-62d810e0]{height:auto}.title[data-v-62d810e0]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-text-1)}.icon[data-v-62d810e0]{width:16px;height:16px;fill:currentColor}.icon.lang[data-v-62d810e0]{margin-right:8px}.icon.chevron[data-v-62d810e0]{margin-left:4px}.list[data-v-62d810e0]{padding:4px 0 0 24px}.link[data-v-62d810e0]{line-height:32px;font-size:13px;color:var(--vp-c-text-1)}.VPNavScreen[data-v-223ed9ec]{position:fixed;top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 1px);right:0;bottom:0;left:0;padding:0 32px;width:100%;background-color:var(--vp-nav-screen-bg-color);overflow-y:auto;transition:background-color .5s;pointer-events:auto}.VPNavScreen.fade-enter-active[data-v-223ed9ec],.VPNavScreen.fade-leave-active[data-v-223ed9ec]{transition:opacity .25s}.VPNavScreen.fade-enter-active .container[data-v-223ed9ec],.VPNavScreen.fade-leave-active .container[data-v-223ed9ec]{transition:transform .25s ease}.VPNavScreen.fade-enter-from[data-v-223ed9ec],.VPNavScreen.fade-leave-to[data-v-223ed9ec]{opacity:0}.VPNavScreen.fade-enter-from .container[data-v-223ed9ec],.VPNavScreen.fade-leave-to .container[data-v-223ed9ec]{transform:translateY(-8px)}@media (min-width: 768px){.VPNavScreen[data-v-223ed9ec]{display:none}}.container[data-v-223ed9ec]{margin:0 auto;padding:24px 0 96px;max-width:288px}.menu+.translations[data-v-223ed9ec],.menu+.appearance[data-v-223ed9ec],.translations+.appearance[data-v-223ed9ec]{margin-top:24px}.menu+.social-links[data-v-223ed9ec]{margin-top:16px}.appearance+.social-links[data-v-223ed9ec]{margin-top:16px}.VPNav[data-v-b9dbd140]{position:relative;top:var(--vp-layout-top-height, 0px);left:0;z-index:var(--vp-z-index-nav);width:100%;pointer-events:none;transition:background-color .5s}@media (min-width: 960px){.VPNav[data-v-b9dbd140]{position:fixed}}.VPSidebarItem.level-0[data-v-b5e6ce1f]{padding-bottom:24px}.VPSidebarItem.collapsed.level-0[data-v-b5e6ce1f]{padding-bottom:10px}.item[data-v-b5e6ce1f]{position:relative;display:flex;width:100%}.VPSidebarItem.collapsible>.item[data-v-b5e6ce1f]{cursor:pointer}.indicator[data-v-b5e6ce1f]{position:absolute;top:6px;bottom:6px;left:-17px;width:2px;border-radius:2px;transition:background-color .25s}.VPSidebarItem.level-2.is-active>.item>.indicator[data-v-b5e6ce1f],.VPSidebarItem.level-3.is-active>.item>.indicator[data-v-b5e6ce1f],.VPSidebarItem.level-4.is-active>.item>.indicator[data-v-b5e6ce1f],.VPSidebarItem.level-5.is-active>.item>.indicator[data-v-b5e6ce1f]{background-color:var(--vp-c-brand-1)}.link[data-v-b5e6ce1f]{display:flex;align-items:center;flex-grow:1}.text[data-v-b5e6ce1f]{flex-grow:1;padding:4px 0;line-height:24px;font-size:14px;transition:color .25s}.VPSidebarItem.level-0 .text[data-v-b5e6ce1f]{font-weight:700;color:var(--vp-c-text-1)}.VPSidebarItem.level-1 .text[data-v-b5e6ce1f],.VPSidebarItem.level-2 .text[data-v-b5e6ce1f],.VPSidebarItem.level-3 .text[data-v-b5e6ce1f],.VPSidebarItem.level-4 .text[data-v-b5e6ce1f],.VPSidebarItem.level-5 .text[data-v-b5e6ce1f]{font-weight:500;color:var(--vp-c-text-2)}.VPSidebarItem.level-0.is-link>.item>.link:hover .text[data-v-b5e6ce1f],.VPSidebarItem.level-1.is-link>.item>.link:hover .text[data-v-b5e6ce1f],.VPSidebarItem.level-2.is-link>.item>.link:hover .text[data-v-b5e6ce1f],.VPSidebarItem.level-3.is-link>.item>.link:hover .text[data-v-b5e6ce1f],.VPSidebarItem.level-4.is-link>.item>.link:hover .text[data-v-b5e6ce1f],.VPSidebarItem.level-5.is-link>.item>.link:hover .text[data-v-b5e6ce1f]{color:var(--vp-c-brand-1)}.VPSidebarItem.level-0.has-active>.item>.text[data-v-b5e6ce1f],.VPSidebarItem.level-1.has-active>.item>.text[data-v-b5e6ce1f],.VPSidebarItem.level-2.has-active>.item>.text[data-v-b5e6ce1f],.VPSidebarItem.level-3.has-active>.item>.text[data-v-b5e6ce1f],.VPSidebarItem.level-4.has-active>.item>.text[data-v-b5e6ce1f],.VPSidebarItem.level-5.has-active>.item>.text[data-v-b5e6ce1f],.VPSidebarItem.level-0.has-active>.item>.link>.text[data-v-b5e6ce1f],.VPSidebarItem.level-1.has-active>.item>.link>.text[data-v-b5e6ce1f],.VPSidebarItem.level-2.has-active>.item>.link>.text[data-v-b5e6ce1f],.VPSidebarItem.level-3.has-active>.item>.link>.text[data-v-b5e6ce1f],.VPSidebarItem.level-4.has-active>.item>.link>.text[data-v-b5e6ce1f],.VPSidebarItem.level-5.has-active>.item>.link>.text[data-v-b5e6ce1f]{color:var(--vp-c-text-1)}.VPSidebarItem.level-0.is-active>.item .link>.text[data-v-b5e6ce1f],.VPSidebarItem.level-1.is-active>.item .link>.text[data-v-b5e6ce1f],.VPSidebarItem.level-2.is-active>.item .link>.text[data-v-b5e6ce1f],.VPSidebarItem.level-3.is-active>.item .link>.text[data-v-b5e6ce1f],.VPSidebarItem.level-4.is-active>.item .link>.text[data-v-b5e6ce1f],.VPSidebarItem.level-5.is-active>.item .link>.text[data-v-b5e6ce1f]{color:var(--vp-c-brand-1)}.caret[data-v-b5e6ce1f]{display:flex;justify-content:center;align-items:center;margin-right:-7px;width:32px;height:32px;color:var(--vp-c-text-3);cursor:pointer;transition:color .25s;flex-shrink:0}.item:hover .caret[data-v-b5e6ce1f]{color:var(--vp-c-text-2)}.item:hover .caret[data-v-b5e6ce1f]:hover{color:var(--vp-c-text-1)}.caret-icon[data-v-b5e6ce1f]{width:18px;height:18px;fill:currentColor;transform:rotate(90deg);transition:transform .25s}.VPSidebarItem.collapsed .caret-icon[data-v-b5e6ce1f]{transform:rotate(0)}.VPSidebarItem.level-1 .items[data-v-b5e6ce1f],.VPSidebarItem.level-2 .items[data-v-b5e6ce1f],.VPSidebarItem.level-3 .items[data-v-b5e6ce1f],.VPSidebarItem.level-4 .items[data-v-b5e6ce1f],.VPSidebarItem.level-5 .items[data-v-b5e6ce1f]{border-left:1px solid var(--vp-c-divider);padding-left:16px}.VPSidebarItem.collapsed .items[data-v-b5e6ce1f]{display:none}.VPSidebar[data-v-6d56fb3e]{position:fixed;top:var(--vp-layout-top-height, 0px);bottom:0;left:0;z-index:var(--vp-z-index-sidebar);padding:32px 32px 96px;width:calc(100vw - 64px);max-width:320px;background-color:var(--vp-sidebar-bg-color);opacity:0;box-shadow:var(--vp-c-shadow-3);overflow-x:hidden;overflow-y:auto;transform:translate(-100%);transition:opacity .5s,transform .25s ease;overscroll-behavior:contain}.VPSidebar.open[data-v-6d56fb3e]{opacity:1;visibility:visible;transform:translate(0);transition:opacity .25s,transform .5s cubic-bezier(.19,1,.22,1)}.dark .VPSidebar[data-v-6d56fb3e]{box-shadow:var(--vp-shadow-1)}@media (min-width: 960px){.VPSidebar[data-v-6d56fb3e]{padding-top:var(--vp-nav-height);width:var(--vp-sidebar-width);max-width:100%;background-color:var(--vp-sidebar-bg-color);opacity:1;visibility:visible;box-shadow:none;transform:translate(0)}}@media (min-width: 1440px){.VPSidebar[data-v-6d56fb3e]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}@media (min-width: 960px){.curtain[data-v-6d56fb3e]{position:sticky;top:-64px;left:0;z-index:1;margin-top:calc(var(--vp-nav-height) * -1);margin-right:-32px;margin-left:-32px;height:var(--vp-nav-height);background-color:var(--vp-sidebar-bg-color)}}.nav[data-v-6d56fb3e]{outline:0}.group+.group[data-v-6d56fb3e]{border-top:1px solid var(--vp-c-divider);padding-top:10px}@media (min-width: 960px){.group[data-v-6d56fb3e]{padding-top:10px;width:calc(var(--vp-sidebar-width) - 64px)}}.VPSkipLink[data-v-b55af449]{top:8px;left:8px;padding:8px 16px;z-index:999;border-radius:8px;font-size:12px;font-weight:700;text-decoration:none;color:var(--vp-c-brand-1);box-shadow:var(--vp-shadow-3);background-color:var(--vp-c-bg)}.VPSkipLink[data-v-b55af449]:focus{height:auto;width:auto;clip:auto;clip-path:none}@media (min-width: 1280px){.VPSkipLink[data-v-b55af449]{top:14px;left:16px}}.Layout[data-v-39c7485e]{display:flex;flex-direction:column;min-height:100vh}.VPHomeSponsors[data-v-f2c20b74]{border-top:1px solid var(--vp-c-gutter);padding:88px 24px 96px;background-color:var(--vp-c-bg)}.container[data-v-f2c20b74]{margin:0 auto;max-width:1152px}.love[data-v-f2c20b74]{margin:0 auto;width:28px;height:28px;color:var(--vp-c-text-3)}.icon[data-v-f2c20b74]{width:28px;height:28px;fill:currentColor}.message[data-v-f2c20b74]{margin:0 auto;padding-top:10px;max-width:320px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.sponsors[data-v-f2c20b74]{padding-top:32px}.action[data-v-f2c20b74]{padding-top:40px;text-align:center}.VPTeamPage[data-v-c9cc5bbd]{padding-bottom:96px}@media (min-width: 768px){.VPTeamPage[data-v-c9cc5bbd]{padding-bottom:128px}}.VPTeamPageSection+.VPTeamPageSection[data-v-c9cc5bbd-s],.VPTeamMembers+.VPTeamPageSection[data-v-c9cc5bbd-s]{margin-top:64px}.VPTeamMembers+.VPTeamMembers[data-v-c9cc5bbd-s]{margin-top:24px}@media (min-width: 768px){.VPTeamPageTitle+.VPTeamPageSection[data-v-c9cc5bbd-s]{margin-top:16px}.VPTeamPageSection+.VPTeamPageSection[data-v-c9cc5bbd-s],.VPTeamMembers+.VPTeamPageSection[data-v-c9cc5bbd-s]{margin-top:96px}}.VPTeamMembers[data-v-c9cc5bbd-s]{padding:0 24px}@media (min-width: 768px){.VPTeamMembers[data-v-c9cc5bbd-s]{padding:0 48px}}@media (min-width: 960px){.VPTeamMembers[data-v-c9cc5bbd-s]{padding:0 64px}}.VPTeamPageTitle[data-v-f86d4927]{padding:48px 32px;text-align:center}@media (min-width: 768px){.VPTeamPageTitle[data-v-f86d4927]{padding:64px 48px 48px}}@media (min-width: 960px){.VPTeamPageTitle[data-v-f86d4927]{padding:80px 64px 48px}}.title[data-v-f86d4927]{letter-spacing:0;line-height:44px;font-size:36px;font-weight:500}@media (min-width: 768px){.title[data-v-f86d4927]{letter-spacing:-.5px;line-height:56px;font-size:48px}}.lead[data-v-f86d4927]{margin:0 auto;max-width:512px;padding-top:12px;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 768px){.lead[data-v-f86d4927]{max-width:592px;letter-spacing:.15px;line-height:28px;font-size:20px}}.VPTeamPageSection[data-v-f1ec77a0]{padding:0 32px}@media (min-width: 768px){.VPTeamPageSection[data-v-f1ec77a0]{padding:0 48px}}@media (min-width: 960px){.VPTeamPageSection[data-v-f1ec77a0]{padding:0 64px}}.title[data-v-f1ec77a0]{position:relative;margin:0 auto;max-width:1152px;text-align:center;color:var(--vp-c-text-2)}.title-line[data-v-f1ec77a0]{position:absolute;top:16px;left:0;width:100%;height:1px;background-color:var(--vp-c-divider)}.title-text[data-v-f1ec77a0]{position:relative;display:inline-block;padding:0 24px;letter-spacing:0;line-height:32px;font-size:20px;font-weight:500;background-color:var(--vp-c-bg)}.lead[data-v-f1ec77a0]{margin:0 auto;max-width:480px;padding-top:12px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.members[data-v-f1ec77a0]{padding-top:40px}.VPTeamMembersItem[data-v-091cbe90]{display:flex;flex-direction:column;gap:2px;border-radius:12px;width:100%;height:100%;overflow:hidden}.VPTeamMembersItem.small .profile[data-v-091cbe90]{padding:32px}.VPTeamMembersItem.small .data[data-v-091cbe90]{padding-top:20px}.VPTeamMembersItem.small .avatar[data-v-091cbe90]{width:64px;height:64px}.VPTeamMembersItem.small .name[data-v-091cbe90]{line-height:24px;font-size:16px}.VPTeamMembersItem.small .affiliation[data-v-091cbe90]{padding-top:4px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .desc[data-v-091cbe90]{padding-top:12px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .links[data-v-091cbe90]{margin:0 -16px -20px;padding:10px 0 0}.VPTeamMembersItem.medium .profile[data-v-091cbe90]{padding:48px 32px}.VPTeamMembersItem.medium .data[data-v-091cbe90]{padding-top:24px;text-align:center}.VPTeamMembersItem.medium .avatar[data-v-091cbe90]{width:96px;height:96px}.VPTeamMembersItem.medium .name[data-v-091cbe90]{letter-spacing:.15px;line-height:28px;font-size:20px}.VPTeamMembersItem.medium .affiliation[data-v-091cbe90]{padding-top:4px;font-size:16px}.VPTeamMembersItem.medium .desc[data-v-091cbe90]{padding-top:16px;max-width:288px;font-size:16px}.VPTeamMembersItem.medium .links[data-v-091cbe90]{margin:0 -16px -12px;padding:16px 12px 0}.profile[data-v-091cbe90]{flex-grow:1;background-color:var(--vp-c-bg-soft)}.data[data-v-091cbe90]{text-align:center}.avatar[data-v-091cbe90]{position:relative;flex-shrink:0;margin:0 auto;border-radius:50%;box-shadow:var(--vp-shadow-3)}.avatar-img[data-v-091cbe90]{position:absolute;top:0;right:0;bottom:0;left:0;border-radius:50%;object-fit:cover}.name[data-v-091cbe90]{margin:0;font-weight:600}.affiliation[data-v-091cbe90]{margin:0;font-weight:500;color:var(--vp-c-text-2)}.org.link[data-v-091cbe90]{color:var(--vp-c-text-2);transition:color .25s}.org.link[data-v-091cbe90]:hover{color:var(--vp-c-brand-1)}.desc[data-v-091cbe90]{margin:0 auto}.desc[data-v-091cbe90] a{font-weight:500;color:var(--vp-c-brand-1);text-decoration-style:dotted;transition:color .25s}.links[data-v-091cbe90]{display:flex;justify-content:center;height:56px}.sp-link[data-v-091cbe90]{display:flex;justify-content:center;align-items:center;text-align:center;padding:16px;font-size:14px;font-weight:500;color:var(--vp-c-sponsor);background-color:var(--vp-c-bg-soft);transition:color .25s,background-color .25s}.sp .sp-link.link[data-v-091cbe90]:hover,.sp .sp-link.link[data-v-091cbe90]:focus{outline:none;color:var(--vp-c-white);background-color:var(--vp-c-sponsor)}.sp-icon[data-v-091cbe90]{margin-right:8px;width:16px;height:16px;fill:currentColor}.VPTeamMembers.small .container[data-v-07437725]{grid-template-columns:repeat(auto-fit,minmax(224px,1fr))}.VPTeamMembers.small.count-1 .container[data-v-07437725]{max-width:276px}.VPTeamMembers.small.count-2 .container[data-v-07437725]{max-width:576px}.VPTeamMembers.small.count-3 .container[data-v-07437725]{max-width:876px}.VPTeamMembers.medium .container[data-v-07437725]{grid-template-columns:repeat(auto-fit,minmax(256px,1fr))}@media (min-width: 375px){.VPTeamMembers.medium .container[data-v-07437725]{grid-template-columns:repeat(auto-fit,minmax(288px,1fr))}}.VPTeamMembers.medium.count-1 .container[data-v-07437725]{max-width:368px}.VPTeamMembers.medium.count-2 .container[data-v-07437725]{max-width:760px}.container[data-v-07437725]{display:grid;gap:24px;margin:0 auto;max-width:1152px}.sticky-container[data-v-12fc2a51]{position:sticky;top:0;background:var(--vp-sidebar-bg-color);z-index:9}[data-v-12fc2a51] .VPSidebar.open .sticky-container{top:-32px}*,:before,:after{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 rgb(0 0 0 / 0);--un-ring-shadow:0 0 rgb(0 0 0 / 0);--un-shadow-inset: ;--un-shadow:0 0 rgb(0 0 0 / 0);--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgb(147 197 253 / .5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }::backdrop{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 rgb(0 0 0 / 0);--un-ring-shadow:0 0 rgb(0 0 0 / 0);--un-shadow-inset: ;--un-shadow:0 0 rgb(0 0 0 / 0);--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgb(147 197 253 / .5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }.container{width:100%}@media (min-width: 640px){.container{max-width:640px}}@media (min-width: 768px){.container{max-width:768px}}@media (min-width: 1024px){.container{max-width:1024px}}@media (min-width: 1280px){.container{max-width:1280px}}@media (min-width: 1536px){.container{max-width:1536px}}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.sticky{position:sticky}.static{position:static}.inset-0{top:0;right:0;bottom:0;left:0}.z-90{z-index:90}.grid{display:grid}.-m-2{margin:-.5rem}.m10\.6{margin:2.65rem}.m12{margin:3rem}.m21{margin:5.25rem}.m9{margin:2.25rem}.my-4{margin-top:1rem;margin-bottom:1rem}.me{margin-inline-end:1rem}.inline{display:inline}.block{display:block}.inline-block{display:inline-block}.contents{display:contents}.hidden{display:none}.h1{height:.25rem}.h2{height:.5rem}.h3{height:.75rem}.h4{height:1rem}.h5{height:1.25rem}.h6{height:1.5rem}.max-w-min{max-width:min-content}.flex{display:flex}.inline-flex{display:inline-flex}.flex-1{flex:1 1 0%}.flex-shrink{flex-shrink:1}.flex-grow,.grow{flex-grow:1}.flex-row-reverse{flex-direction:row-reverse}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.table{display:table}.transform{transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.cursor-not-allowed{cursor:not-allowed}.items-center{align-items:center}.justify-center{justify-content:center}.space-x-2>:not([hidden])~:not([hidden]){--un-space-x-reverse:0;margin-left:calc(.5rem * calc(1 - var(--un-space-x-reverse)));margin-right:calc(.5rem * var(--un-space-x-reverse))}.space-x-4>:not([hidden])~:not([hidden]){--un-space-x-reverse:0;margin-left:calc(1rem * calc(1 - var(--un-space-x-reverse)));margin-right:calc(1rem * var(--un-space-x-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--un-space-y-reverse:0;margin-top:calc(.25rem * calc(1 - var(--un-space-y-reverse)));margin-bottom:calc(.25rem * var(--un-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--un-space-y-reverse:0;margin-top:calc(1rem * calc(1 - var(--un-space-y-reverse)));margin-bottom:calc(1rem * var(--un-space-y-reverse))}.overflow-y-scroll{overflow-y:scroll}.whitespace-pre{white-space:pre}.border{border-width:1px}.border-gray-300{--un-border-opacity:1;border-color:rgb(209 213 219 / var(--un-border-opacity))}.rounded{border-radius:.25rem}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.border-solid{border-style:solid}.bg-black\/30{background-color:#0000004d}.bg-vp-bg{background-color:var(--vp-c-bg)}.bg-vp-brand-2{background-color:var(--vp-c-brand-2)}.dark .dark\:bg-vp-brand-3{background-color:var(--vp-c-brand-3)}.dark .dark\:hover\:bg-vp-brand-2:hover{background-color:var(--vp-c-brand-2)}.hover\:bg-vp-brand-1:hover{background-color:var(--vp-c-brand-1)}.hover\:bg-vp-brand-soft:hover{background-color:var(--vp-c-brand-soft)}.p-2{padding:.5rem}.p-4{padding:1rem}.p-8{padding:2rem}.px,.px-4{padding-left:1rem;padding-right:1rem}.px-3{padding-left:.75rem;padding-right:.75rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-4{padding-top:1rem;padding-bottom:1rem}.ps{padding-inline-start:1rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-base{font-size:1rem;line-height:1.5rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.text-white{--un-text-opacity:1;color:rgb(255 255 255 / var(--un-text-opacity))}.hover\:text-vp-brand-2:hover{color:var(--vp-c-brand-2)}.font-medium{font-weight:500}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.underline{text-decoration-line:underline}.tab{-moz-tab-size:4;-o-tab-size:4;tab-size:4}.opacity-50{opacity:.5}.shadow-elevation-btn{--un-shadow:0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12);box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow)}.shadow-lg{--un-shadow:var(--un-shadow-inset) 0 10px 15px -3px var(--un-shadow-color, rgb(0 0 0 / .1)),var(--un-shadow-inset) 0 4px 6px -4px var(--un-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow)}.shadow-md{--un-shadow:var(--un-shadow-inset) 0 4px 6px -1px var(--un-shadow-color, rgb(0 0 0 / .1)),var(--un-shadow-inset) 0 2px 4px -2px var(--un-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow)}.shadow-none{--un-shadow:0 0 var(--un-shadow-color, rgb(0 0 0 / 0));box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow)}.outline{outline-style:solid}.blur{--un-blur:blur(8px);filter:var(--un-blur) var(--un-brightness) var(--un-contrast) var(--un-drop-shadow) var(--un-grayscale) var(--un-hue-rotate) var(--un-invert) var(--un-saturate) var(--un-sepia)}.filter{filter:var(--un-blur) var(--un-brightness) var(--un-contrast) var(--un-drop-shadow) var(--un-grayscale) var(--un-hue-rotate) var(--un-invert) var(--un-saturate) var(--un-sepia)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.ease{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}:root{--vp-font-family-mono: "JetBrains Mono", "Fira Code", Menlo, Monaco, Consolas, "Courier New", monospace}.vp-doc div[class*=language-] pre{font-size:14px;font-variant-ligatures:none}.vp-doc code{font-variant-ligatures:none}.vp-doc sup{line-height:0}.VPLocalSearchBox[data-v-fcbfb6ff]{position:fixed;z-index:100;top:0;right:0;bottom:0;left:0;display:flex}.backdrop[data-v-fcbfb6ff]{position:absolute;top:0;right:0;bottom:0;left:0;background:var(--vp-backdrop-bg-color);transition:opacity .5s}.shell[data-v-fcbfb6ff]{position:relative;padding:12px;margin:64px auto;display:flex;flex-direction:column;gap:16px;background:var(--vp-local-search-bg);width:min(100vw - 60px,900px);height:min-content;max-height:min(100vh - 128px,900px);border-radius:6px}@media (max-width: 767px){.shell[data-v-fcbfb6ff]{margin:0;width:100vw;height:100vh;max-height:none;border-radius:0}}.search-bar[data-v-fcbfb6ff]{border:1px solid var(--vp-c-divider);border-radius:4px;display:flex;align-items:center;padding:0 12px;cursor:text}@media (max-width: 767px){.search-bar[data-v-fcbfb6ff]{padding:0 8px}}.search-bar[data-v-fcbfb6ff]:focus-within{border-color:var(--vp-c-brand-1)}.search-icon[data-v-fcbfb6ff]{margin:8px}@media (max-width: 767px){.search-icon[data-v-fcbfb6ff]{display:none}}.search-input[data-v-fcbfb6ff]{padding:6px 12px;font-size:inherit;width:100%}@media (max-width: 767px){.search-input[data-v-fcbfb6ff]{padding:6px 4px}}.search-actions[data-v-fcbfb6ff]{display:flex;gap:4px}@media (any-pointer: coarse){.search-actions[data-v-fcbfb6ff]{gap:8px}}@media (min-width: 769px){.search-actions.before[data-v-fcbfb6ff]{display:none}}.search-actions button[data-v-fcbfb6ff]{padding:8px}.search-actions button[data-v-fcbfb6ff]:not([disabled]):hover,.toggle-layout-button.detailed-list[data-v-fcbfb6ff]{color:var(--vp-c-brand-1)}.search-actions button.clear-button[data-v-fcbfb6ff]:disabled{opacity:.37}.search-keyboard-shortcuts[data-v-fcbfb6ff]{font-size:.8rem;opacity:75%;display:flex;flex-wrap:wrap;gap:16px;line-height:14px}.search-keyboard-shortcuts span[data-v-fcbfb6ff]{display:flex;align-items:center;gap:4px}@media (max-width: 767px){.search-keyboard-shortcuts[data-v-fcbfb6ff]{display:none}}.search-keyboard-shortcuts kbd[data-v-fcbfb6ff]{background:#8080801a;border-radius:4px;padding:3px 6px;min-width:24px;display:inline-block;text-align:center;vertical-align:middle;border:1px solid rgba(128,128,128,.15);box-shadow:0 2px 2px #0000001a}.results[data-v-fcbfb6ff]{display:flex;flex-direction:column;gap:6px;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain}.result[data-v-fcbfb6ff]{display:flex;align-items:center;gap:8px;border-radius:4px;transition:none;line-height:1rem;border:solid 2px var(--vp-local-search-result-border);outline:none}.result>div[data-v-fcbfb6ff]{margin:12px;width:100%;overflow:hidden}@media (max-width: 767px){.result>div[data-v-fcbfb6ff]{margin:8px}}.titles[data-v-fcbfb6ff]{display:flex;flex-wrap:wrap;gap:4px;position:relative;z-index:1001;padding:2px 0}.title[data-v-fcbfb6ff]{display:flex;align-items:center;gap:4px}.title.main[data-v-fcbfb6ff]{font-weight:500}.title-icon[data-v-fcbfb6ff]{opacity:.5;font-weight:500;color:var(--vp-c-brand-1)}.title svg[data-v-fcbfb6ff]{opacity:.5}.result.selected[data-v-fcbfb6ff]{--vp-local-search-result-bg: var(--vp-local-search-result-selected-bg);border-color:var(--vp-local-search-result-selected-border)}.excerpt-wrapper[data-v-fcbfb6ff]{position:relative}.excerpt[data-v-fcbfb6ff]{opacity:75%;pointer-events:none;max-height:140px;overflow:hidden;position:relative;opacity:.5;margin-top:4px}.result.selected .excerpt[data-v-fcbfb6ff]{opacity:1}.excerpt[data-v-fcbfb6ff] *{font-size:.8rem!important;line-height:130%!important}.titles[data-v-fcbfb6ff] mark,.excerpt[data-v-fcbfb6ff] mark{background-color:var(--vp-local-search-highlight-bg);color:var(--vp-local-search-highlight-text);border-radius:2px;padding:0 2px}.excerpt[data-v-fcbfb6ff] .vp-code-group .tabs{display:none}.excerpt[data-v-fcbfb6ff] .vp-code-group div[class*=language-]{border-radius:8px!important}.excerpt-gradient-bottom[data-v-fcbfb6ff]{position:absolute;bottom:-1px;left:0;width:100%;height:8px;background:linear-gradient(transparent,var(--vp-local-search-result-bg));z-index:1000}.excerpt-gradient-top[data-v-fcbfb6ff]{position:absolute;top:-1px;left:0;width:100%;height:8px;background:linear-gradient(var(--vp-local-search-result-bg),transparent);z-index:1000}.result.selected .titles[data-v-fcbfb6ff],.result.selected .title-icon[data-v-fcbfb6ff]{color:var(--vp-c-brand-1)!important}.no-results[data-v-fcbfb6ff]{font-size:.9rem;text-align:center;padding:12px}svg[data-v-fcbfb6ff]{flex:none} diff --git a/documenting/snippets.html b/documenting/snippets.html new file mode 100644 index 00000000..d82be690 --- /dev/null +++ b/documenting/snippets.html @@ -0,0 +1,67 @@ + + + + + + Code Snippets | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Code Snippets

    To make code snippets in the documentation more "real" and robust, it is better to fetch them directly from the source files. The sources are located in other repositories, where they are built, run, and tested.

    How it works

    Snippet Sources

    Snippet sources are defined in snippet_sources.ts. The snippet_sources.ts file is located in the documentation repository and has the following format:

    ts
    export default [
    +  {
    +    src: 'https://raw.githubusercontent.com/hyperledger/iroha/main/MAINTAINERS.md',
    +    filename: 'iroha-maintainers-at-stable.md',
    +  },
    +  {
    +    src: './src/example_code/lorem.rs',
    +  },
    +]
    • src defines the source file location and could be either an HTTP(s) URI or a relative file path.
    • filename (optional) explicitly defines the local filename.

    Fetching Snippets

    Code snippets are fetched from the locations specified in snippet_sources.ts and written into the /src/snippets directory. There are two ways to fetch the snippets:

    • Automatically after dependencies were installed (i.e. pnpm install)
    • Manually by calling pnpm get-snippets

    TIP

    By default, snippets are deleted and reloaded each time pnpm get-snippets is called. For local development it might be more convenient to enable "lazy" behavior by calling pnpm get-snippets --force false.

    Using Snippets in Markdown

    Use Code Snippets feature in VitePress to include snippets into documentation:

    Input

    md
    <<<@/snippets/lorem.rs
    +
    +<<<@/snippets/lorem.rs#ipsum

    Output

    rs
    fn main() {
    +    // #region ipsum
    +    println!("Lorem ipsum");
    +    // #endregion ipsum
    +}
    rs
    println!("Lorem ipsum");

    Note that we included only the #ipsum code region, not the entire file. This feature is essential when it comes to including code from real source files into the documentation.

    Example

    Let's add a code snippet from Iroha JavaScript SDK. For example, this one: /packages/docs-recipes/src/1.client-install.ts.

    1. First, get a permalink to the file. Open the file on GitHub and click Raw button to get the link. For example: https://raw.githubusercontent.com/hyperledger/iroha-javascript/e300886e76c777776efad1e2f5cb245bfb8ed02e/packages/docs-recipes/src/1.client-install.ts

    2. Define the new snippet in the Snippet Sources:

      ts
      export default [
      +  /// ...
      +
      +  {
      +    src: 'https://raw.githubusercontent.com/hyperledger/iroha-javascript/e300886e76c777776efad1e2f5cb245bfb8ed02e/packages/docs-recipes/src/1.client-install.ts',
      +    filename: 'js-sdk-1-client-install.ts',
      +  },
      +]

      TIP

      Since snippet_sources.ts is a TypeScript file, we can use all scripting features in it. Meanwhile, we are trying to keep it as simple as possible, so even the one who doesn't know TypeScript at all could edit it.

      However, we use a bit of scripting. We defined several constants with git revisions from multiple repositories:

      ts
      const IROHA_REV_STABLE = 'c4af68c4f7959b154eb5380aa93c894e2e63fe4e'
      +
      +const IROHA_REV_DEV = '...'
      +
      +const IROHA_JS_REV = '...'

      Then we use them in links to snippet sources in place of git revisions, like this:

      ts
      export default [
      +  // ...
      +
      +  {
      +    src: `https://raw.githubusercontent.com/hyperledger/iroha/${IROHA_REV_STABLE}/MAINTAINERS.md`,
      +    //                                                        ^^^^^^^^^^^^^^^^^^^
      +    filename: 'iroha-maintainers-at-stable.md',
      +  },
      +]

      It helps us to reduce repetitions and keep sources clean.

    3. Include the snippet in any Markdown file in the documentation as follows:

      Input

      md
      <<<@/snippets/js-sdk-1-client-install.ts

      Output

      ts
      import { crypto } from '@iroha2/crypto-target-node'
      +import { setCrypto } from '@iroha2/client'
      +
      +setCrypto(crypto)
    + + + + \ No newline at end of file diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 00000000..b14a8296 Binary files /dev/null and b/favicon.ico differ diff --git a/guide/advanced/hot-reload.html b/guide/advanced/hot-reload.html new file mode 100644 index 00000000..0a0f0222 --- /dev/null +++ b/guide/advanced/hot-reload.html @@ -0,0 +1,31 @@ + + + + + + How to hot reload Iroha in a Docker container | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    How to hot reload Iroha in a Docker container

    Here is the overall procedure for hot reloading Iroha in a Docker container:

    1. Build Iroha on your host OS.

      To avoid issues with dynamic linking, run:

      bash
      $ cargo build --release --target x86_64-unknown-linux-musl --features "vendored"
      An explanation for using `cargo build` with these parameters.

      You may experience an issue with dynamic linking if your host OS has a newer version of glibc compared to the one in the Docker container. The options used in the command above resolve the issue:

      • --target x86_64-unknown-linux-musl forces static linking against musl libc implementation
      • --features "vendored" facilitates static linkage of the openssl library
    2. Enter Docker container. For example:

      bash
      $ docker exec -it iroha-iroha0-1 bash
    3. Copy Iroha to the current directory:

      bash
      $ docker cp root/soramitsu/iroha/target/x86_64-unknown-linux-musl/release/iroha .
    4. (Optional) Make any modifications you need:

    5. Exit docker container and restart it using docker restart.

      Note: If you use the combination of container down and container up, any modifications you made on the previous step will be lost. Use docker restart to preserve changes.

    If you skip the optional step (step 4), the state of the blockchain after hot reload will be the same as it was before the Docker container was restarted.

    Note that if you get the Kura initialisation failed error message, it might mean one of two things: corruption or binary incompatibility of the stored block. To fix this, remove the blocks/ directory.

    Wiping previous blockchain state (recommit genesis)

    To recommit a custom genesis block, remove the previously stored blocks before restarting the container:

    bash
    $ rm blocks/*

    The new genesis block will be automatically recommited upon container restart.

    Use custom configuration files

    To use custom configuration files, such as config.json or genesis.json, copy (or bind mount) them to the config/ subvolume before restarting the Docker container.

    The changes will take effect upon container restart.

    Use custom environment variables

    To use custom environment variables (e.g. IROHA_PUBLIC_KEY), simply modify them before restarting the Docker container. For example:

    bash
    $ IROHA_PUBLIC_KEY=<new_key> docker restart

    The changes will take effect upon container restart.

    + + + + \ No newline at end of file diff --git a/guide/advanced/metrics.html b/guide/advanced/metrics.html new file mode 100644 index 00000000..b5efae97 --- /dev/null +++ b/guide/advanced/metrics.html @@ -0,0 +1,45 @@ + + + + + + Metrics | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Metrics

    To conveniently and thoroughly monitor the performance of your instance of the Iroha network, we recommend using Prometheus. Prometheus is a program that can monitor your Iroha peer over a separate socket and provide different kinds of performance metrics.

    This data can help you find performance bottlenecks and optimise your Iroha configuration.

    /metrics Endpoint

    See Reference > Torii Endpoints: Metrics.

    How to use metrics

    Work in Progress.

    This topic will be updated as part of the new configuration reference.

    The progress on the configuration reference can be tracked in the following GitHub issue:
    iroha-2-docs > Issue #392: Tracking issue for Configuration Reference as per RFC.

    ::: note

    For examples, see Sample Configuration Files.

    :::

    After the above is configured, you can use the IP address set in the "TORII_TELEMETRY_URL" variable to access the metrics data from within a running Iroha instance.

    Example:

    bash
    $ curl http://127.0.0.1:8180/metrics

    This returns a result similar to the following:

    bash
    # HELP blocks_height Total number of blocks in chain
    +# TYPE blocks_height gauge
    +blocks_height 135543
    +# HELP peers_number Total number peers to send transactions and request proposals
    +# TYPE peers_number gauge
    +peers_number 7
    +# HELP number_of_domains Total number of domains in WSV
    +# TYPE number_of_domains gauge
    +number_of_domains 14
    +# HELP total_number_of_transactions Total number of transactions in blockchain
    +# TYPE total_number_of_transactions gauge
    +total_number_of_transactions 216499
    +# HELP number_of_signatures_in_last_block Number of signatures in last block
    +# TYPE number_of_signatures_in_last_block gauge
    +number_of_signatures_in_last_block 5
    + + + + \ No newline at end of file diff --git a/guide/advanced/running-iroha-on-bare-metal.html b/guide/advanced/running-iroha-on-bare-metal.html new file mode 100644 index 00000000..12997b2f --- /dev/null +++ b/guide/advanced/running-iroha-on-bare-metal.html @@ -0,0 +1,156 @@ + + + + + + Iroha on bare metal | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Iroha on bare metal

    What we are going to do is replicate the setup that we have in docker compose and run Iroha directly, without going through the intermediary of containers. Running Iroha on bare metal involves manipulating files and/or environment variables.

    The file-based approach is the easiest to get right. Using environment variables can offer a better user experience if done right, but is more error-prone, particularly for exotic systems (Windows).

    INFO

    For this chapter, we assume you have learned about configuration and management in Iroha 2. Here we offer you instructions to run Iroha on bare metal without going into details about various configuration options available.

    You can always check sample configuration files for configs/peer/genesis.json and configs/peer/config.json, or refer to peer configuration options for more details.

    Prerequisites

    First of all, we should note that we have only built the Iroha client so far in this tutorial. We also need to build the peer software to run Iroha on bare metal.

    INFO

    Building in debug mode retains much more information and optimises the binary to a far lesser extent. As such, we advise you to build Iroha in debug mode for testing: it’s faster and it makes it easier for you to find issues and fix them. However, if you intend to actually deploy Iroha, you should build it in --release mode.

    • To build the peer software in debug mode, run:

      kotlin
      cargo build -p iroha
    • To build the peer software in release mode, run:

      kotlin
      cargo build --bin iroha --release

      The release mode binary takes significantly longer to compile than debug mode, but the result is a smaller and faster binary, suitable for deployment in the actual blockchains.

    Setup

    Setup: Environment variables

    We want to make sure that we have the right configuration.

    There are different ways to do this. You can copy the contents of the ~/Git/iroha/configs/peer/ into a new directory, or, alternatively, just run all commands from that directory:

    bash
    $ cd ~/Git/iroha/configs/peer

    The third option is to specify the full path to the configuration file in an environment variable. For simplicity, we shall do the latter:

    bash
    $ cd ~
    +$ export IROHA2_GENESIS_PATH="$(pwd)/Git/iroha/configs/peer/genesis.json"
    +$ export IROHA2_CONFIG_PATH="$(pwd)/Git/iroha/configs/peer/config.json"

    For extra convenience, you could add the Iroha 2 target directory to your PATH. This means that instead of having to specify the full path to the executable iroha, you can instead type iroha directly into your command line.

    bash
    $ export PATH="$PATH:$(pwd)/Git/iroha/target/debug"

    TIP

    Don’t forget to replace debug with release when you’re ready to deploy in the real world.

    This way you can run iroha from any directory without having to worry about configuration paths and/or specifying the full path to the Iroha executable.

    It is a good idea to make these instructions permanent, which you can do by adding the environment variables to your startup shell.

    Save the instructions to the startup shell

    On older Linux systems, you copy and paste the instructions (without the cd ~) to ~/.bashrc. On Mac OS X 10.6 and later, as well as some Linux systems, you want to add the same lines to ~/.zshrc.

    Copy these instructions to the specified files (replace debug with release when you are ready to deploy):

    bash
    $ export IROHA2_GENESIS_PATH="$(pwd)/Git/iroha/configs/peer/genesis.json"
    +$ export IROHA2_CONFIG_PATH="$(pwd)/Git/iroha/configs/peer/config.json"
    +$ export PATH="$PATH:$(pwd)/Git/iroha/target/debug"

    TIP

    This process is almost universally unreliable and messy, and it is likely that your system is special in that it breaks some of our assumptions.

    If the above optional steps didn’t work for you, you can keep working in the ~/Git/iroha/configs/peer/ folder, and run Iroha via ~/Git/iroha/target/debug/iroha.

    This makes the command-line a little harder to read, which is why we recommend setting up your environment first.

    Note

    The tutorial assumes that you’re running either Linux, Mac OS X, or Windows using WSL. It should be possible to run directly on Windows, but that is neither recommended nor easy. If you don’t want to use a Unix-like system, we suggest that you wait until we publish a detailed guide for Windows users.

    Setup: Files

    This is the recommended method of bringing up an Iroha peer. What we do is:

    1. Create a new directory for the configuration files:

      bash
      $ mkdir -p ~/Git/iroha/deploy
    2. Copy the peer configuration into it:

      bash
      $ cp -vfr ~/Git/iroha/configs/peer/*.json ~/Git/iroha/deploy
    3. Copy the respective Iroha binary into your binary folder:

      bash
      $ sudo cp -vfr ~/Git/iroha/target/debug/iroha /usr/bin/

      which will install Iroha 2 system wide.

    TIP

    You could also use the iroha peer binary locally by copying it into the same folder. The only difference would be that you’d be calling Iroha like so: ./iroha instead of iroha.

    First run of Iroha on bare metal

    If you’ve done everything correctly, you can now do

    bash
    $ iroha

    to start your first peer and be greeted with

    Untitled

    This means that everything is working, but also that we need to do some more work.

    You have just started a single peer, which can tolerate exactly 0 faults. Running two peers is also possible, but again, can tolerate 0 faults. You must run at least 4 peers in order to have the capacity to tolerate at least one fault.

    In general, if you want to be resistant to f faults, you want to have 3f+1 peers: (4, 7, 10, etc.).

    You cannot really start the peers in any way you want, though. When we started our original peer, in its configuration, we specified that it has to trust very specific peers, which have the given private key and listen on a specific address. In order to know how to run them appropriately, take a look at docker-compose.yml:

    docker-compose.yaml
    yaml
    version: '3.8'
    +services:
    +  iroha0:
    +    image: hyperledger/iroha2:dev
    +    environment:
    +      TORII_P2P_ADDR: iroha0:1337
    +      TORII_API_URL: iroha0:8080
    +      TORII_TELEMETRY_URL: iroha0:8180
    +      IROHA_PUBLIC_KEY: 'ed01201c61faf8fe94e253b93114240394f79a607b7fa55f9e5a41ebec74b88055768b'
    +      IROHA_PRIVATE_KEY:
    +        '{"digest_function": "ed25519", "payload":
    +        "282ed9f3cf92811c3818dbc4ae594ed59dc1a2f78e4241e31924e101d6b1fb831c61faf8fe94e253b93114240394f79a607b7fa55f9e5a41ebec74b88055768b"}'
    +      SUMERAGI_TRUSTED_PEERS:
    +        '[{"address":"iroha0:1337", "public_key":
    +        "ed01201c61faf8fe94e253b93114240394f79a607b7fa55f9e5a41ebec74b88055768b"},
    +        {"address":"iroha1:1338", "public_key":
    +        "ed0120cc25624d62896d3a0bfd8940f928dc2abf27cc57cefeb442aa96d9081aae58a1"},
    +        {"address": "iroha2:1339", "public_key":
    +        "ed0120faca9e8aa83225cb4d16d67f27dd4f93fc30ffa11adc1f5c88fd5495ecc91020"},
    +        {"address": "iroha3:1340", "public_key":
    +        "ed01208e351a70b6a603ed285d666b8d689b680865913ba03ce29fb7d13a166c4e7f1f"}]'
    +      IROHA_GENESIS_ACCOUNT_PUBLIC_KEY: 'ed01203f4e3e98571b55514edc5ccf7e53ca7509d89b2868e62921180a6f57c2f4e255'
    +      IROHA_GENESIS_ACCOUNT_PRIVATE_KEY:
    +        '{ "digest_function": "ed25519", "payload":
    +        "038ae16b219da35aa036335ed0a43c28a2cc737150112c78a7b8034b9d99c9023f4e3e98571b55514edc5ccf7e53ca7509d89b2868e62921180a6f57c2f4e255"
    +        }'
    +    ports:
    +      - '1337:1337'
    +      - '8080:8080'
    +      - '8180:8180'
    +    volumes:
    +      - './configs/peer:/config'
    +    init: true
    +    command: iroha --submit-genesis
    +
    +  iroha1:
    +    image: hyperledger/iroha2:dev
    +    environment:
    +      TORII_P2P_ADDR: iroha1:1338
    +      TORII_API_URL: iroha1:8081
    +      TORII_TELEMETRY_URL: iroha1:8181
    +      IROHA_PUBLIC_KEY: 'ed0120cc25624d62896d3a0bfd8940f928dc2abf27cc57cefeb442aa96d9081aae58a1'
    +      IROHA_PRIVATE_KEY:
    +        '{"digest_function": "ed25519", "payload":
    +        "3bac34cda9e3763fa069c1198312d1ec73b53023b8180c822ac355435edc4a24cc25624d62896d3a0bfd8940f928dc2abf27cc57cefeb442aa96d9081aae58a1"}'
    +      SUMERAGI_TRUSTED_PEERS:
    +        '[{"address":"iroha0:1337", "public_key":
    +        "ed01201c61faf8fe94e253b93114240394f79a607b7fa55f9e5a41ebec74b88055768b"},
    +        {"address":"iroha1:1338", "public_key":
    +        "ed0120cc25624d62896d3a0bfd8940f928dc2abf27cc57cefeb442aa96d9081aae58a1"},
    +        {"address": "iroha2:1339", "public_key":
    +        "ed0120faca9e8aa83225cb4d16d67f27dd4f93fc30ffa11adc1f5c88fd5495ecc91020"},
    +        {"address": "iroha3:1340", "public_key":
    +        "ed01208e351a70b6a603ed285d666b8d689b680865913ba03ce29fb7d13a166c4e7f1f"}]'
    +      IROHA_GENESIS_ACCOUNT_PUBLIC_KEY: 'ed01203f4e3e98571b55514edc5ccf7e53ca7509d89b2868e62921180a6f57c2f4e255'
    +    ports:
    +      - '1338:1338'
    +      - '8081:8081'
    +      - '8181:8181'
    +    volumes:
    +      - './configs/peer:/config'
    +    init: true
    +
    +  iroha2:
    +    image: hyperledger/iroha2:dev
    +    environment:
    +      TORII_P2P_ADDR: iroha2:1339
    +      TORII_API_URL: iroha2:8082
    +      TORII_TELEMETRY_URL: iroha2:8182
    +      IROHA_PUBLIC_KEY: 'ed0120faca9e8aa83225cb4d16d67f27dd4f93fc30ffa11adc1f5c88fd5495ecc91020'
    +      IROHA_PRIVATE_KEY:
    +        '{"digest_function": "ed25519", "payload":
    +        "1261a436d36779223d7d6cf20e8b644510e488e6a50bafd77a7485264d27197dfaca9e8aa83225cb4d16d67f27dd4f93fc30ffa11adc1f5c88fd5495ecc91020"}'
    +      SUMERAGI_TRUSTED_PEERS:
    +        '[{"address":"iroha0:1337", "public_key":
    +        "ed01201c61faf8fe94e253b93114240394f79a607b7fa55f9e5a41ebec74b88055768b"},
    +        {"address":"iroha1:1338", "public_key":
    +        "ed0120cc25624d62896d3a0bfd8940f928dc2abf27cc57cefeb442aa96d9081aae58a1"},
    +        {"address": "iroha2:1339", "public_key":
    +        "ed0120faca9e8aa83225cb4d16d67f27dd4f93fc30ffa11adc1f5c88fd5495ecc91020"},
    +        {"address": "iroha3:1340", "public_key":
    +        "ed01208e351a70b6a603ed285d666b8d689b680865913ba03ce29fb7d13a166c4e7f1f"}]'
    +      IROHA_GENESIS_ACCOUNT_PUBLIC_KEY: 'ed01203f4e3e98571b55514edc5ccf7e53ca7509d89b2868e62921180a6f57c2f4e255'
    +    ports:
    +      - '1339:1339'
    +      - '8082:8082'
    +      - '8182:8182'
    +    volumes:
    +      - './configs/peer:/config'
    +    init: true
    +
    +  iroha3:
    +    image: hyperledger/iroha2:dev
    +    environment:
    +      TORII_P2P_ADDR: iroha3:1340
    +      TORII_API_URL: iroha3:8083
    +      TORII_TELEMETRY_URL: iroha3:8183
    +      IROHA_PUBLIC_KEY: 'ed01208e351a70b6a603ed285d666b8d689b680865913ba03ce29fb7d13a166c4e7f1f'
    +      IROHA_PRIVATE_KEY:
    +        '{"digest_function": "ed25519", "payload":
    +        "a70dab95c7482eb9f159111b65947e482108cfe67df877bd8d3b9441a781c7c98e351a70b6a603ed285d666b8d689b680865913ba03ce29fb7d13a166c4e7f1f"}'
    +      SUMERAGI_TRUSTED_PEERS:
    +        '[{"address":"iroha0:1337", "public_key":
    +        "ed01201c61faf8fe94e253b93114240394f79a607b7fa55f9e5a41ebec74b88055768b"},
    +        {"address":"iroha1:1338", "public_key":
    +        "ed0120cc25624d62896d3a0bfd8940f928dc2abf27cc57cefeb442aa96d9081aae58a1"},
    +        {"address": "iroha2:1339", "public_key":
    +        "ed0120faca9e8aa83225cb4d16d67f27dd4f93fc30ffa11adc1f5c88fd5495ecc91020"},
    +        {"address": "iroha3:1340", "public_key":
    +        "ed01208e351a70b6a603ed285d666b8d689b680865913ba03ce29fb7d13a166c4e7f1f"}]'
    +      IROHA_GENESIS_ACCOUNT_PUBLIC_KEY: 'ed01203f4e3e98571b55514edc5ccf7e53ca7509d89b2868e62921180a6f57c2f4e255'
    +    ports:
    +      - '1340:1340'
    +      - '8083:8083'
    +      - '8183:8183'
    +    volumes:
    +      - './configs/peer:/config'
    +    init: true

    For every peer, the environment section is a set of things that you should put in front of the iroha command, replacing colons with equals signs. All the socket addresses are also given internal to the docker network, so we should replace them with [localhost](http://localhost), which is 127.0.0.1 on most machines.

    TIP

    Each Iroha instance is going to listen on three ports: the Peer-to-peer communications channel (133X), the API url, where most client requests are posted (808X), and finally, a telemetry endpoint 818X. All three ports need to be adjusted so there are no collisions. See the docker-compose.yml for an example, and adjust as needed.

    Deploy a minimal BFT network

    Both of the following approaches could be messy and error-prone, which is why the Launch Iroha 2 tutorial suggests using the docker compose command. However, this brings you closer to the experience of actually maintaining a functional Iroha peer.

    Using Environment Variables

    To run the First peer, we need to write

    bash
    $ TORII_P2P_ADDR="127.0.0.1:1337"
    +$ TORII_API_URL="127.0.0.1:8080"
    +$ TORII_STATUS_URL="127.0.0.1:8180"
    +$ IROHA_PUBLIC_KEY="ed01207233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0" IROHA_PRIVATE_KEY='{"digest_function": "ed25519", "payload": "9ac47abf59b356e0bd7dcbbbb4dec080e302156a48ca907e47cb6aea1d32719e7233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0"}'
    +$ iroha --submit

    and three other similar lines of bash code for the remaining deployments.

    TIP

    To copy and paste into the terminal on Linux systems, you should remember that Control + Shift + V is the appropriate paste shortcut.

    Also note that we asked this peer to --submit or --submit-genesis. This means that in the initial network topology, this peer is the leader. At least one peer (usually the first) needs to be the leader in the initial topology.

    Now you should do the same for the other four peers. Be mindful not to mix up which address goes where, replace irohaX with 127.0.0.1 in the addresses, and make sure that they correspond to the right public key.

    Using Files

    Our first peer can run off of the original configuration file. What we should do is create three more similar files and move them to three different folders e.g. peer1, peer2.

    What you need to do is change the TORII:P2P_ADDR, TORII:API_URLTORII:STATUS_URL and the PUBLIC_KEY configuration options to align with their docker-compose.yml counterparts.

    Be mindful not to mix up which address goes where, replace irohaX with 127.0.0.1 in the addresses, and make sure that they correspond to the right public key.

    Then, in each of the new folders (with the exception of peer0) run:

    bash
    $ iroha

    In the first folder peer0 you should run:

    bash
    $ iroha --submit-genesis

    We effectively asked this peer to --submit or --submit-genesis in the initial, or bootstrap, network. This means that in the initial network topology, this peer is the leader.

    Note

    Only the leader of the genesis network needs to have access to configs/peer/genesis.json. Having the same genesis in the initial folders of the other peers could be useful, since future versions of iroha will also sanity-check the genesis blocks.

    If all went well, you should be greeted with nice logs on each of the nodes, and the nodes should commit the blocks to the blocks/ directory.

    Real-world deployment

    Suppose now, that you have done all of the tinkering and want to deploy Iroha in the real world.

    1. Build Iroha in release mode:

      bash
      $ cargo build --release
    2. Generate a key pair for your peer and take note of that key:

      bash
      $ cargo run --bin iroha_crypto_cli
    3. Register your peer to a network, and make sure to add at least four of the peers on that network to the TRUSTED_PEERS array in your configuration file.

    4. Determine the web socket that the other peers will use to connect to you. Make sure that the port is open and use that address (P2P_ADDR) in your configs/peer/config.json file.

    5. After you have finished editing the configuration file, deploy Iroha by running

      bash
      $ ~/Git/iroha/target/release/iroha

    Note

    There is no need to pass the --submit flag unless you are starting the initial peer on the network.

    + + + + \ No newline at end of file diff --git a/guide/blockchain/accounts.html b/guide/blockchain/accounts.html new file mode 100644 index 00000000..60441d43 --- /dev/null +++ b/guide/blockchain/accounts.html @@ -0,0 +1,31 @@ + + + + + + Accounts | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/guide/blockchain/assets.html b/guide/blockchain/assets.html new file mode 100644 index 00000000..6d0fc345 --- /dev/null +++ b/guide/blockchain/assets.html @@ -0,0 +1,31 @@ + + + + + + Assets | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Assets

    Iroha has been built with few underlying assumptions about what the assets need to be.

    The assets can be fungible (every £1 is exactly the same as every other £1) or non-fungible (a £1 bill signed by the Queen of Hearts is not the same as a £1 bill signed by the King of Spades).

    The assets can also be mintable (you can make more of them) and non-mintable (you can only specify their initial quantity in the genesis block).

    Value Types

    Additionally, the assets have different underlying value types. Specifically, we have AssetValueType.Quantity, which is effectively an unsigned 32-bit integer, a BigQuantity, which is an unsigned 128-bit integer, and Fixed, which is a positive (though signed) 64-bit fixed-precision number with nine significant digits after the decimal point. All three types can be registered as either mintable or non-mintable.

    There is also the Store asset type, which is used for storing key-values in object's metadata. We talk in detail about Store asset in the chapter related to metadata.

    Asset Structure

    Instructions

    Assets can be registered, minted or burned, and transferred.

    Refer to one of the language-specific guides to walk you through the process of registering and minting assets in a blockchain:

    + + + + \ No newline at end of file diff --git a/guide/blockchain/consensus.html b/guide/blockchain/consensus.html new file mode 100644 index 00000000..27b92a20 --- /dev/null +++ b/guide/blockchain/consensus.html @@ -0,0 +1,31 @@ + + + + + + Consensus | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Consensus

    Each time you send a transaction to Iroha, it gets put into a queue. When it's time to produce a new block, the queue is emptied, and the consensus process begins. This process is equal parts common sense and black magic[1].

    The mundane aspect is that a special set of peers needs to take the transaction queue and reproduce the same world state. If the world state cannot be reproduced for some reason or another, none of the transactions get committed to a block.

    The consensus starts over from scratch by choosing a different special set of peers. This is where the black magic comes in. There is a number of things that are fine-tuned: the number of peers in the voting process, the way in which subsequent voting peers are chosen, and the way in which the peers communicate that consensus has failed. Because this changes the view of the world, the process is called a view change. The exact reason for why the view was changed is encoded in the view change proof, but decoding that information is an advanced topic that we won't cover here.

    The reasoning behind this algorithm is simple: if someone had some evil peers and connected them to the existing network, if they tried to fake data, some good™ peers would not get the same (evil™) world state. If that's the case, the evil™ peers would not be allowed to participate in consensus, and you would eventually produce a block using only good™ peers.

    As a natural consequence, if any changes to the world state are made without the use of ISI, the good™ peers cannot know of them. They won't be able to reproduce the hash of the world state, and thus consensus will fail. The same thing happens if the peers have different instructions.


    1. For prospective wizards, the Iroha 2 Whitepaper is a good start. ↩︎

    + + + + \ No newline at end of file diff --git a/guide/blockchain/data-model.html b/guide/blockchain/data-model.html new file mode 100644 index 00000000..dd4230f9 --- /dev/null +++ b/guide/blockchain/data-model.html @@ -0,0 +1,49 @@ + + + + + + Data Model | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Data Model

    In language-specific guides we already walked you through registering domains, accounts, and assets. Here we merely wish to illustrate the relationship between various objects in the blockchain.

    
    +   +-----------------------------------------------+
    +   |                                               |
    +   |     +-----------------+                       |
    +   |     |Domain           |                       |
    +   |     +--------------+  |                       |
    +   |     ||Asset        |  |                       |
    ++--+--+  ||Definition(s)|  |                       |
    +|World|  +--------------+  |                       |
    ++--+--+  |                 |                       |
    +   |     +------------+    |                       |
    +   |     ||Account(s)||    | has   +-----------+   |
    +   |     |------------------------->Signatories|   |
    +   |     +-----------------+       +-----------+   |
    +   |                       |                       |
    +   |                       |  has  +--------+      |
    +   |                       +------->Asset(s)|      |
    +   |                               +--------+      |
    +   +-----------------------------------------------+

    The following example shows the relationship between domains, accounts, and assets.

    Language-specific guides to register these objects
    LanguageGuide
    CLIRegister a domain, an account, an asset
    RustRegister a domain, an account, an asset
    Kotlin/JavaRegister a domain, an account, an asset
    PythonRegister a domain, an account, an asset
    JavaScript/TypeScriptRegister a domain, an account, an asset

    The diagram below provides a more detailed illustration of the relationship between domains, accounts, and assets in the blockchain. You can learn more about permissions and roles and metadata in the corresponding sections. The asset structure is illustrated in a dedicated chapter.

    + + + + \ No newline at end of file diff --git a/guide/blockchain/domains.html b/guide/blockchain/domains.html new file mode 100644 index 00000000..a3a9a5ea --- /dev/null +++ b/guide/blockchain/domains.html @@ -0,0 +1,31 @@ + + + + + + Domains | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/guide/blockchain/events.html b/guide/blockchain/events.html new file mode 100644 index 00000000..4489a904 --- /dev/null +++ b/guide/blockchain/events.html @@ -0,0 +1,31 @@ + + + + + + Events | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Events

    Events are emitted when certain things happen within the blockchain, e.g. a new account is created or a block is committed. There are different types of events:

    • pipeline events
    • data events
    • time events
    • trigger execution events

    Pipeline Events

    Pipeline events are emitted when transactions are submitted, executed, or committed to a block. A pipeline event contains the following information: the kind of entity that caused an event (transaction or block), its hash and status. The status can be either Validating (validation in progress), Rejected, or Committed. If an entity was rejected, the reason for the rejection is provided.

    Data Events

    Data events are emitted when there is a change related to one of the following entities: peers, domains, accounts, asset definitions, assets, triggers, roles, permission tokens, permission validators, or Iroha configuration. These types of events are used in entity filters.

    Time Events

    Time events are emitted when the world state view is ready to handle time triggers.

    Trigger Execution Events

    Trigger execution events are emitted when the ExecuteTrigger instruction is executed

    + + + + \ No newline at end of file diff --git a/guide/blockchain/expressions.html b/guide/blockchain/expressions.html new file mode 100644 index 00000000..b042666f --- /dev/null +++ b/guide/blockchain/expressions.html @@ -0,0 +1,31 @@ + + + + + + Expressions, Conditionals, Logic | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Expressions, Conditionals, Logic

    All Iroha Special Instructions operate on expressions. Each expression has an EvaluatesTo, which is used in instruction execution. While you could specify the account name directly, you could also specify the account ID via some mathematical or string operation. You can check if an account is registered on the blockchain too.

    Using expressions that implement EvaluatesTo<bool>, you can set up conditional logic and execute more sophisticated operations on-chain. For example, you can submit a Mint instruction only if a specific account is registered.

    Recall that you can combine this with queries, and as such can program the blockchain to do some amazing stuff. This is what we refer to as smart contracts, the defining feature of the advanced usage of blockchain technology.

    + + + + \ No newline at end of file diff --git a/guide/blockchain/filters.html b/guide/blockchain/filters.html new file mode 100644 index 00000000..8f8d911e --- /dev/null +++ b/guide/blockchain/filters.html @@ -0,0 +1,31 @@ + + + + + + Filters | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Filters

    Iroha uses filter-map paradigm to monitor events. Let's look at different types of filters that can be used in Iroha.

    Data Filters

    A data filter is a tuple with a single variant, which is a FilterOpt of an EntityFilter:

    FilterOpt stands for Optional Filter. It can either AcceptAll or accept BySome of another Filter. An EntityFilter is a filter that matches events produced by a certain type entity, e.g. by account or domain.

    Here is the list of EntityFilters in Iroha:

    + + + + \ No newline at end of file diff --git a/guide/blockchain/how-iroha-works.html b/guide/blockchain/how-iroha-works.html new file mode 100644 index 00000000..9b6e9400 --- /dev/null +++ b/guide/blockchain/how-iroha-works.html @@ -0,0 +1,31 @@ + + + + + + How Iroha works | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    How Iroha works

    To understand how Iroha operates, let's draw parallels between a blockchain and a computer. If the blockchain is the computer, then in this metaphor of ours the client binary (for example: iroha) is the keyboard, the blockchain is the hard drive, and the Iroha peer software is the processor. Like a processor, Iroha accepts portable instructions that modify what's written to the blockchain, allow certain users to use the network, and lock others out.

    Any operation that is run on-chain is written in terms of Iroha Special Instructions (ISI), and there is no other way of modifying the world state.

    Each interaction with the blockchain is done via a transaction. A transaction is a collection of instructions, which are either glued together in sequence or compiled into what we affectionately call a WASM blob. You need these instructions to register an account, remove an account, add X amount of Y currency, and so on.

    To read the information encoded in the blocks of a blockchain (the current world state), you use queries. Queries are submitted like instructions, but they're not tracked and recorded in blocks, so they're much more lightweight. If you use queries as part of complicated logic (e.g. inside WASM), they have a non-negligible impact on the size of the blocks. Queries that are only used to get information leave no trace in the blockchain.

    + + + + \ No newline at end of file diff --git a/guide/blockchain/instructions.html b/guide/blockchain/instructions.html new file mode 100644 index 00000000..3231e2b5 --- /dev/null +++ b/guide/blockchain/instructions.html @@ -0,0 +1,31 @@ + + + + + + Iroha Special Instructions | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Iroha Special Instructions

    When we spoke about how Iroha operates, we said that Iroha Special Instructions are the only way to modify the world state. So, what kind of special instructions do we have? If you've read the language-specific guides in this tutorial, you've already seen a couple of instructions: Register<Account> and Mint<Quantity>.

    Here is the full list of Iroha Special Instructions:

    InstructionDescriptions
    Register/UnregisterGive an ID to a new entity on the blockchain.
    Mint/BurnMint/burn assets, triggers, or permission tokens.
    SetKeyValue/RemoveKeyValueUpdate blockchain object metadata.
    NewParameter/SetParameterCreate/set a chain-wide config parameter.
    Grant/RevokeGive or remove certain permissions from accounts.
    TransferTransfer assets between accounts.
    ExecuteTriggerExecute triggers.
    If, Pair, SequenceUse to create composite instructions.

    Let's start with a summary of Iroha Special Instructions; what objects each instruction can be called for and what instructions are available for each object.

    Summary

    For each instruction, there is a list of objects on which this instruction can be run on. For example, only assets can be transferred, while minting can refer to assets, triggers, and permission tokens.

    Some instructions require a destination to be specified. For example, if you transfer assets, you always need to specify to which account you are transferring them. On the other hand, when you are registering something, all you need is the object that you want to register.

    InstructionObjectsDestination
    Register/Unregisteraccounts, domains, asset definitions, triggers, roles, peers
    Mint/Burnassets, triggers (trigger repetitions), permission tokensaccounts
    SetKeyValue/RemoveKeyValueany objects that have metadata: accounts, domains, assets, asset definitions, triggers, transactions
    NewParameter/SetParameterIroha configuration parameters
    Grant/Revokeroles, permission tokensaccounts
    Transferassetsaccounts
    ExecuteTriggertriggers
    If, Pair, Sequenceany instructions

    There is also another way of looking at ISI, i.e. in terms of the target of each instruction. For example, when you register an account, you do so within a certain domain. This means that the target of the Register<Account> instruction would be the domain within which it is being registered.

    TargetInstructions
    Account(un)register assets, mint/burn account public key, mint/burn account signature condition check, update account metadata, grant/revoke a permission token, grant/revoke role
    Domain(un)register accounts, (un)register asset definitions, update asset metadata, update domain metadata
    Assetupdate metadata, mint/burn, transfer
    Trigger(un)register, mint/burn trigger repetitions, execute trigger
    World(un)register domains, peers, roles

    (Un)Register

    Registering and unregistering are the instructions used to give an ID to a new entity on the blockchain.

    Everything that can be registered is both Registrable and Identifiable, but not everything that's Identifiable is Registrable. Most things are registered directly, like Peers, but in some cases the representation in the blockchain has considerably more data. For security and performance reasons, we use builders for such data structures (e.g. NewAccount). As a rule, everything that can be registered, can also be un-registered, but that is not a hard and fast rule.

    You can register domains, accounts, asset definitions, peers, roles, and triggers. Check our naming conventions to learn about the restrictions put on entity names.

    INFO

    Note that depending on how you decide to set up your genesis block in genesis.json (specifically, whether or not you include registration of permission tokens), the process for registering an account can be very different. In general, we can summarise it like this:

    • In a public blockchain, anyone should be able to register an account.
    • In a private blockchain, there can be a unique process for registering accounts. In a typical private blockchain, i.e. a blockchain without any unique processes for registering accounts, you need an account to register another account.

    We discuss these differences in great detail when we compare private and public blockchains.

    INFO

    Registering a peer is currently the only way of adding peers that were not part of the original TRUSTED_PEERS array to the network.

    Refer to one of the language-specific guides to walk you through the process of registering objects in a blockchain:

    LanguageGuide
    CLIRegister a domain, an account, an asset
    RustRegister a domain, an account, an asset
    Kotlin/JavaRegister a domain, an account, an asset
    PythonRegister a domain, an account, an asset
    JavaScript/TypeScriptRegister a domain, an account, an asset

    Mint/Burn

    Minting and burning can refer to assets, triggers (if the trigger has a limited number of repetitions), and temporary permission tokens. Some assets can be declared as non-mintable, meaning that they can be minted only once after registration.

    Assets and permission tokens need to be minted to a specific account, usually the one that registered the asset in the first place. All assets are assumed to be non-negative as well, so you can never have 1.0-1.0 of time or Burn a negative amount and get a Mint.

    Refer to one of the language-specific guides to walk you through the process of minting assets in a blockchain:

    Here are examples of burning assets:

    Transfer

    Similar to mint and burn instructions, transferring refers to assets. You can transfer assets between different accounts.

    To do this, an account have to be granted the permission to transfer assets. Refer to an example on how to transfer assets with CLI or Rust.

    Grant/Revoke

    Grant and revoke instructions are used for account permissions and roles.

    Grant is used to permanently grant a user either a single permission, or a group of permissions (a "role"). Granted roles and permissions can only be removed via the Revoke instruction. As such, these instructions should be used carefully.

    SetKeyValue/RemoveKeyValue

    These instructions are used with the key/value Store asset type. This use case has not received much attention so far, because storing data in the blockchain is a rather advanced topic that we shall cover separately.

    NewParameter/SetParameter

    With these instructions, you can create (NewParameter) and change (SetParameter) chain-wide configuration parameters for Iroha.

    ExecuteTrigger

    This instruction is used to execute triggers.

    Composite instructions

    Iroha also offers composite instructions (If, Pair, Sequence) to execute instructions in a certain way:

    • If: execute one of the two given instructions based on a given condition
    • Sequence: execute a provided vector of instructions in a given order
    • Pair: execute both provided instructions in a specified order
    + + + + \ No newline at end of file diff --git a/guide/blockchain/metadata.html b/guide/blockchain/metadata.html new file mode 100644 index 00000000..5f1baecb --- /dev/null +++ b/guide/blockchain/metadata.html @@ -0,0 +1,90 @@ + + + + + + Metadata | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content
    + + + + \ No newline at end of file diff --git a/guide/blockchain/permissions.html b/guide/blockchain/permissions.html new file mode 100644 index 00000000..51f000bc --- /dev/null +++ b/guide/blockchain/permissions.html @@ -0,0 +1,45 @@ + + + + + + Permissions | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Permissions

    Accounts need permission tokens for various actions on a blockchain, e.g. to mint or burn assets.

    There is a difference between a public and a private blockchain in terms of permissions granted to users. In a public blockchain, most accounts have the same set of permissions. In a private blockchain, most accounts are assumed not to be able to do anything outside of their own account or domain unless explicitly granted said permission.

    Having a permission to do something means having a PermissionToken to do so. There are two ways for users to receive permission tokens: they can be granted directly or as a part of a Role (a set of permission tokens). Permissions are granted via Grant special instruction. Permission tokens and roles do not expire, they can only be removed using Revoke instruction.

    Permission Tokens

    Permission token definitions have parameters. When a new permission token is registered, the names of the parameters and their types are checked against their names and types in the token definition. The token registration fails if there are too few parameters, if the parameter types don't match the definition, or parameters with unrecognised names.

    Here are some examples of parameters used for various permission tokens:

    • A token that grants permission to change the values associated to keys in a Store asset needs the asset_definition_id parameter of type Id:

      json
        "params": {
      +     "asset_definition_id": "Id"
      +}
    • By contrast, the permission token that grants the permission to set keys to values in user metadata needs the account_id parameter of type Id:

      json
      "params": {
      +  "account_id": "Id"
      +}
    • The permission token that grants the permission to transfer assets only a fixed number of times per some time period, needs these two parameters:

      json
      "params": {
      +  "count": "U32",
      +  "period": "U128"
      +}

      Where the period is specified as a standard Duration since the UNIX epoch in milliseconds (more details about time in Rust).

    Pre-configured Permission Tokens

    You can find the list of pre-configured permission tokens in the Reference chapter.

    Permission Groups (Roles)

    A set of permissions is called a role. Similarly to permission tokens, roles can be granted using the Grant instruction and revoked using the Revoke instruction.

    Before granting a role to an account, the role should be registered first.

    Register a new role

    Let's register a new role that, when granted, will allow another account access to the metadata in Mouse's account:

    rust
    let role_id = RoleId::from_str("ACCESS_TO_MOUSE_METADATA")?;
    +let role = iroha_data_model::role::Role::new(role_id)
    +    .add_permission(CanSetKeyValueInUserMetadata::new(mouse_id))
    +    .add_permission(CanRemoveKeyValueInUserMetadata::new(mouse_id));
    +let register_role = RegisterBox::new(role);

    Grant a role

    After the role is registered, Mouse can grant it to Alice:

    rust
    let grant_role = GrantBox::new(role_id, alice_id);
    +let grant_role_tx =
    +    Transaction::new(mouse_id, vec![grant_role.into()].into(), 100_000)
    +    .sign(mouse_key_pair)?;

    Permission Validators

    Permissions exist so that only those accounts that have a required permission token to perform a certain action could do so.

    The Judge trait is used to check permissions. The Judge decides whether a certain operation (instruction, query, or expression) could be performed based on the verdicts of multiple validators.

    Each validator returns one of the following verdicts: Deny (with the exact reason to deny an operation), Skip (if an operation is not supported or has no meaning in a given context), or Allow.

    There are several implementations of the Judge trait in Iroha 2, such as:

    JudgeDescription
    AtLeastOneAllowThe judge that succeeds only if there is at least one Allow verdict. The execution is stopped once there is a first Allow verdict.
    NoDeniesThe judge that succeeds only if there is no Deny verdict. All validators are checked.
    NoDeniesAndAtLeastOneAllowThe judge that succeeds only if there is no Deny verdict and at least one Allow verdict. The execution is stopped once there is a Deny verdict or all validators were checked.
    AllowAllFor tests and simple cases. All operations are allowed to be executed for all possible values.
    DenyAllFor tests and simple cases. All operations are disallowed to be executed for all possible for all possible values.

    You can also build a custom permission validator by combining multiple validators, all of which should be of the same type (for checking instructions, queries, or expressions).

    Runtime Validators

    Currently Iroha 2 has only built-in validators. In the future, built-in validators will be completely replaced with runtime validators that use WASM.

    The chain of runtime validators is used to validate operations that require permissions. It works similarly to the Chain of responsibility.

    All runtime validators return validation verdict. By default, all operations are considered valid unless proven otherwise. Validators check whether or not an operation is not allowed: each validator either allows an operation and passes it to the following validator, or denies the operation. The validation stops at the first Deny verdict.

    Supported Queries

    Permission tokens and roles can be queried.

    Queries for roles:

    Queries for permission tokens:

    + + + + \ No newline at end of file diff --git a/guide/blockchain/queries.html b/guide/blockchain/queries.html new file mode 100644 index 00000000..a15e075a --- /dev/null +++ b/guide/blockchain/queries.html @@ -0,0 +1,37 @@ + + + + + + Queries | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Queries

    Although much of the information about the state of the blockchain can be obtained, as we've shown before, using an event subscriber and a filter to narrow the scope of the events to those of interest, sometimes you need to take a more direct approach. Enter queries.

    Queries are small instruction-like objects that, when sent to an Iroha peer, prompt a response with details from the current world state view.

    This is not necessarily the only kind of information that is available on the network, but it's the only kind of information that is guaranteed to be accessible on all networks.

    For each deployment of Iroha, there might be other available information. For example, the availability of telemetry data is up to the network administrators. It's entirely their decision whether or not they want to allocate processing power to track the work instead of using it to do the actual work. By contrast, some functions are always required, e.g. having access to your account balance.

    The results of queries can be sorted, paginated and filtered peer-side all at once. Sorting is done lexicographically on metadata keys. Filtering can be done on a variety of principles, from domain-specific (individual IP address filter masks) to sub-string methods like begins_with combined using logical operations.

    Create a query

    Use QueryBox to construct a query. For example, a query to find all accounts would be created like this:

    rust
    let query = QueryBox::FindAllAccounts(FindAllAccounts {});

    Here is an example of a query that finds Alice's assets:

    rust
    let alice_id =
    +    AccountId::from_str("alice@wonderland")?;
    +let query = QueryBox::FindAssetsByAccountId(
    +    FindAssetsByAccountId::new(alice_id)
    +  );

    Pagination

    For both a Vec<Z> and just Z as the return type, you can use client.request(query) to submit a query and get the full result in one go.

    However, some queries, particularly the ones with "All" in their names, can return exorbitant amounts of data. As such, we highly recommend you consider pagination to reduce the load on the system.

    To construct a Pagination, you need to call client.request_with_pagination(query, pagination), where the pagination is constructed as follows:

    rust
    let starting_result: u32 = _;
    +let limit: u32 = _;
    +let pagination = Pagination::new(Some(starting_result), Some(limit));

    Filters

    When you create a query, you can use a filter to only return the results that match the specified filter.

    Sorting

    Iroha 2 can sort items with metadata lexicographically if you provide a key to sort by during the construction of the query. A typical use case is for accounts to have a registered-on metadata entry, which, when sorted, allows you to view the account registration history.

    Sorting only applies to entities that have metadata, as the metadata key is used to sort query results.

    You can combine sorting with pagination and filters. Note that sorting is an optional feature, most queries with pagination won't need it.

    Reference

    Check the list of existing queries for detailed information about them.

    + + + + \ No newline at end of file diff --git a/guide/blockchain/transactions.html b/guide/blockchain/transactions.html new file mode 100644 index 00000000..950a2653 --- /dev/null +++ b/guide/blockchain/transactions.html @@ -0,0 +1,34 @@ + + + + + + Transactions | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Transactions

    A transaction is a collection of instructions. The instructions within a transaction can be executed in a sequence or compiled into a WASM blob.

    All interactions in the blockchain are done via transactions.

    All transactions, including rejected transactions, are stored in blocks.

    Here is an example of creating a new transaction with the Grant instruction. In this transaction, Mouse is granting Alice the specified role (role_id). Check the full example.

    rust
    let grant_role = GrantBox::new(role_id, alice_id);
    +let grant_role_tx =
    +    Transaction::new(mouse_id, vec![grant_role.into()].into(), 100_000)
    +    .sign(mouse_key_pair)?;
    + + + + \ No newline at end of file diff --git a/guide/blockchain/triggers.html b/guide/blockchain/triggers.html new file mode 100644 index 00000000..95a92b75 --- /dev/null +++ b/guide/blockchain/triggers.html @@ -0,0 +1,76 @@ + + + + + + Triggers | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Triggers

    Certain things, such as changing the state of an entity, committing a block or executing an Iroha Special Instruction (ISI), can emit events, and you can attach triggers to these events.

    A trigger is a fairly basic entity that can be registered. Just like with Accounts, to register a trigger, you submit a RegisterBox::Trigger, which contains the necessary information:

    • an account ID, which should ideally be a brand new account that you register in the same transaction
    • an executable, which itself is either a Vec<Instruction> or a WASM blob
    • an EventFilter[1], which is something that combs through all[2] events and returns true when it finds the matching event to start the execution

    Let's take a closer look at how triggers work.

    The Anatomy of a Trigger

    A trigger has roughly the following form:

    rust
    struct Trigger {
    +  id: TriggerId,
    +  action: Action,
    +}

    Trigger.id

    The TriggerId is a simple wrapper around a single Name, a string with no whitespaces and no reserved characters (@, #, $).

    A typical domain-scoped trigger looks like trigger_id$domain_name, while a bare trigger looks like @@trigger_id, which makes these names easy to parse.

    Trigger.action

    An Action is the heart of the trigger. It is defined like this:

    rust
    struct Action {
    +  executable: Executable,
    +  repeats: Repeats,
    +  technical_account: AccountId,
    +  filter: EventFilter,
    +  metadata: Metadata,
    +}

    Action.executable

    The executable linked to this action, either a Vec<Instruction> or a WASM binary.

    Action.repeats

    The Repeats is a universal enumeration of all possible repetition schemes.

    rust
    enum Repeats {
    +  Indefinitely,
    +  Exactly(u32),
    +}

    Action.technical_account

    A technical account is the account that would (in theory) be responsible for the execution environment and be the authority for Instruction execution.

    For now, you can leave this as the account that registered the trigger. If you have been following the tutorial, this is alice@wonderland. However, later on we will show you why you'd want to create a brand new account for those purposes.

    INFO

    Note that you can only use the account that already exists in order to be able to register a new trigger.

    Action.filter

    A filter is what determines what kind of trigger you're dealing with. All triggers respond to events, but the precise type of event that activates a trigger depends on which EventFilter was used.

    The reason why we chose this architecture is simple; front end code has an abundance of event filters, and so, your knowledge of filters is transferable to writing smart contracts.

    Action.metadata

    This Metadata is the same kind of Metadata that can be attached to accounts, domains, assets, or transactions. This is the storage for trigger data.

    You can learn more about metadata in a dedicated section.

    How Triggers Work

    As we already said, the filter that is used to register a trigger determines what kind of trigger this is. It is, of course, also determines how the trigger works, e.g. when it is executed. We will go into more details about the types of triggers in just a moment.

    First, we shall point out that there two other characteristics of a trigger that determine how this trigger works: its scope and repetition schema.

    Scope

    Triggers can be scoped and un-scoped. Iroha supports both un-scoped system-wide triggers as well as domain-scoped triggers. Since system-wide triggers scan all events, and domain-scoped triggers only scan events emitted in a certain domain, it is highly recommended to use domain-scoped triggers where possible.

    INFO

    Be mindful of the limitations. Currently triggers don't check for permissions , so they can do things your account wouldn't be allowed to. Un-scoped triggers process every event, and the amount of work grows quadratically.

    Domain-scoped Triggers

    While un-scoped triggers check all events of a specified type, domain-scoped triggers only look for events in a given domain. These triggers are more optimised compared to un-scoped triggers.

    You can use FindTriggersByDomainId query to find triggers for the given domain.

    When you register a domain-scoped trigger, you need to add the domain id to the trigger id using $ symbol: my_trigger$my_domain.

    Repetition Schema

    Each such trigger can be set to repeat either Indefinitely or Exactly(n) times, where n is a 32-bit integer. Once the number of repetitions reaches zero, the trigger is gone. That means that if your trigger got repeated exactly n times, you can't Mint new repetitions, you have to Register it again, with the same name.

    After a trigger is repeated for the last time, i.e. the execution count reaches 0, the trigger should be un-registered.

    Types of Triggers

    We shall cover the following basic types of triggers and provide you with the detailed information on how to use each of them:

    All triggers are essentially event triggers. The type of a trigger is determined by the type of an event that trigger is associated with. This, in turn, is determined by the filter used to register a trigger.

    Data Triggers

    This category includes the largest variety of triggers. The events that are associated with this trigger type account for the vast majority of events in Ethereum. These are data-related events, such as: an account got registered, an asset got transferred, the Queen of Hearts decided to burn all of her assets.

    Time Triggers

    Time triggers behave slightly differently compared to data triggers. There are two sub-types of this type: scheduled triggers and pre-commit triggers.

    Instead of processing all the events generated by normal transactions, all time triggers process one event: the block formation event.

    The filters of scheduled triggers are only interested in the timestamp provided in that event, but not the block height, and not the current time. They are executed according to a certain schedule. Pre-commit triggers, on the other hand, are executed right before a block is committed.

    Scheduled Triggers

    When going through consensus, all peers must agree on which triggers got executed. Scheduled triggers can't use real time, because then you can easily create a situation when they would never agree: e.g. by giving the Repeats::Indefinitely trigger a period that is smaller than the time it takes to pass consensus. It's really that simple.

    So instead of using the actual current time at each peer, we use the time when the block got started plus a small offset. All triggers before that point in time get executed. All triggers that would be executed after that time wait for the next block.

    Why we use the offset

    The reason why we add this offset has to do with Iroha being best effort.

    Imagine if we didn't have the offset... Normally, triggers would be set to nice round numbers; e.g. 12:00, 12:05, 11:55, etc. (as opposed to e.g. 11:59). However, the consensus can start at any point in time and could last a while.

    Suppose that the block started to form at 11:56 and consensus finished at 12:03 (which is optimistically quick). Let's consider different scenarios:

    • If your trigger was supposed to run at 11:55, you'd be happy, since your trigger got executed just 1 minute late.
    • If your trigger was supposed to run at 12:05, it will run in the next block, not the one that was formed at 11:56. If you're the author and you're looking at the time stamp of 12:03, it makes sense, your trigger wasn't supposed to run yet.
    • For the trigger scheduled for 12:00, the situation is different. You look at the clock, you see 12:03, which is when the blockchain explorer shows you the block data was committed, but you don't see your trigger. It was supposed to run, but didn't.

    So, the offset is meant to anticipate when the block would get added to the chain, so that people who were just 4 minutes early don't have to be potentially several hours late.

    Because more triggers get executed sooner, your throughput is also infinitesimally smaller.

    We could also say "you should aim to execute your trigger slightly earlier than consensus starts", but people writing smart contracts already have too much to worry about.

    Pre-commit Triggers

    This is a variant of timed triggers that gets run before blocks with transactions get committed. It leaves a special event to be triggered in the next block. Effectively, it's a delayed pre-commit that can track the behaviour of transactions in the pipeline.

    INFO

    These triggers are not meant for restricting the execution of transactions.

    If you want to stop your users from transferring more than X amount of Y to user Z, you really want a permission. While you could hack the pre-commit triggers to emulate the desired behaviour, this is not economical neither in terms of gas fees nor computation.

    Until Iroha 2 supports WASM-based permissions validators, however, your only choice is pre-commit triggers.

    By-call Triggers

    These triggers only get executed once the CallTrigger(trigger_name) instruction is executed. They can be useful if you want to achieve dynamic linkage between different smart contract modules.

    Space is precious, so you want to use as little of it as you can. Thus, you follow the UNIX design philosophy, and instead of creating one large smart contract, you create many smaller ones, and re-use as much logic as you can.

    INFO

    Of course, this is a rather exotic use case, so it shall be implemented last.

    Event Triggers by Example

    Now that we've gotten the theory out of the way, we want to sit down with the Mad Hatter, the March Hare, and the Dormouse and see if we can spin. Let's start with an event trigger that shows the basics.

    1. Register accounts

    We have mad_hatter@wonderland, dormouse@wonderland, march_hare@wonderland all of which share the fixed-point asset of tea#wonderland. The Mad Hatter has the tea pot, while the rest have a single cup of tea. When alice@wonderland had arrived, she got a nice cup of tea as well.

    The way we get them in Rust code looks like this:

    rust
    let tea = AssetDefinitionId::new("tea", "wonderland")?;
    +let mad_hatter = AccountId::new("mad_hatter", "wonderland")?;
    +let dormouse = AccountId::new("dormouse", "wonderland")?;
    +let march_hare = AccountId::new("march_hare", "wonderland")?;
    +vec![
    +  RegisterBox::new(IdentifiableBox::from(NewAccount::new(mad_hatter.clone()))),
    +  RegisterBox::new(IdentifiableBox::from(NewAccount::new(march_hare.clone()))),
    +  RegisterBox::new(IdentifiableBox::from(NewAccount::new(dormouse.clone()))),
    +  RegisterBox::new(IdentifiableBox::from(AssetDefinition::new_fixed(tea.clone()))),
    +  MintBox::new(Value::Fixed(100.0_f64.try_into()?), IdBox::AssetId(AssetId::new(tea.clone(), mad_hatter.clone())))
    +  MintBox::new(Value::Fixed(1.0_f64.try_into()?), IdBox::AssetId(AssetId::new(tea.clone(), march_hare.clone())))
    +  MintBox::new(Value::Fixed(1.0_f64.try_into()?), IdBox::AssetId(AssetId::new(tea.clone(), dormouse.clone())))
    +  MintBox::new(Value::Fixed(1.0_f64.try_into()?), IdBox::AssetId(AssetId::new(tea.clone(), alice.clone())))
    +]

    2. Register a trigger

    We want a smart contract that transfers some tea from mad_hatter@wonderland to alice@wonderland when her tea reduces by a single cup.

    For that we need to register a trigger. The boilerplate is straightforward:

    rust
    let id = TriggerId::new(Name::new("refresh_tea"));
    +
    +let metadata = Metadata::new();
    +
    +let executable = vec![
    +    TransferBox::new(
    +      IdBox::AssetId(AssetId::new(tea.clone(), mad_hatter.clone())),
    +      Value::Fixed(1_f64.try_into()?),
    +      IdBox::AssetId(AssetId::new(alice.clone(), mad_hatter.clone())),
    +    )
    +];
    +
    +let repeats = Repeats::Indefinitely;
    +
    +let technical_account = mad_hatter.clone();
    +
    +let filter = _ // ...

    3. Define an event filter

    The event filter is where we need to spend some time and think. So far we've seen the Pipeline variety of filters. This time around, the filter is a Data kind. This type of filter is a tuple with a single variant, which is a FilterOpt of an EntityFilter:

    • FilterOpt stands for Optional Filter. It can either AcceptAll or accept BySome of another Filter.
    • An EntityFilter is a filter that matches ByAccount in our case, but can match by many other means. It wraps an AccountFilter, which matches various events produced on accounts.

    What we want to do is create an event filter for when alice@wonderland drinks some of her tea, or, in other words, reduces the tea asset by any amount. To do this with the current API, we need to work bottom up.

    An IdFilter is a filter that .matches(event) == true if and only if the identities are exactly the same. Everything that has an Id has a corresponding IdFilter.

    INFO

    An IdFilter is a parametric structure, an IdFilter that works on Peers has the type IdFilter<PeerId> and is not the same type as an IdFilter that works with AccountId; IdFilter<AccountId.

    Now if we wanted a filter that will match whenever tea gets reduced, either through a Transfer or a Burn instruction, we need an AssetFilter. It needs to look at what the Id of the asset is, hence IdFilter<AssetDefinitionId> and ByRemoved.

    rust
    use FilterOpt::{BySome, AcceptAll};
    +
    +let asset_filter = AssetFilter::new(BySome(IdFilter(tea.clone())), BySome(AssetEventFilter::ByRemoved));

    So far so good?

    Next, we want a filter that looks for changes in an asset for an account. Specifically:

    rust
    let account_filter = AccountFilter::new(BySome(IdFilter(alice.clone())), BySome(asset_filter));

    Now, because of the way that parity_scale_codec works, we need to wrap this in various boxes.

    rust
    let filter = EventFilter::Data(BySome(EntityFilter::ByAccount(account_filter)));

    4. Create a Trigger instance

    After this somewhat laborious filter combination, we can create an Action

    rust
    let action = Action {
    +    executable, repeats, technical_account, filter, metadata
    +}

    Which allows us to create an instance of a Trigger.

    rust
    let trigger = Trigger::new(id, action);

    5. Create a transaction

    Finally, in order to get said trigger onto the blockchain, we create a transaction with the following single instruction:

    rust
    Instruction::Register(RegisterBox::new(IdentifiableBox::Trigger(Box::new(trigger))));

    How it works

    The technical details of the created transaction are summarised as follows:

    • The (normal) instructions that either got submitted from WASM or directly from the client get executed. If there were any triggers that should have been registered, they get registered.
    • Using the total set of events that got generated during the execution of instructions, the triggers (including some that got registered just this round) get executed.
    • The events produced in the previous step get scheduled for execution in the next block.

    INFO

    The reason why the events caused by the execution of triggers get processed in the next block is that we don't want two triggers to inadvertently cause an infinite loop of instruction execution and break consensus.

    Now each time Alice drinks some tea, the Mad Hatter pours in a whole new cup. The keen eyed among you will have noticed that the amount that Alice drinks is irrelevant to how much tea will be transferred. Alice may take a tiny sip and still be poured a whole new cup's worth.

    INFO

    We intend to address this issue in the future so that an emitted event also has an attached Value. We also intend to provide more event filter types. For example, we will have filters that match when the asset:

    • Decreases by any amount (current behaviour)
    • Decreases by more than (or exactly) the specific amount in one instruction
    • Decreases to below a certain threshold

    Only the first type of event filter is implemented now, and the other two can be emulated using a WASM smart contract as the Executable.

    Why not WASM

    The above observation can be generalised. WASM can do any logic that a Turing complete machine could, using the data available via queries. So in theory for event-based triggers, you could create an AcceptAll event filter and do all of the processing using the key-value store as persistent storage, and then, determining if you want to execute using easy-to-understand Rust code, and not our admittedly cumbersome, EventFilters.

    We don't want that. WASM takes up significantly more space, and takes longer to execute compared to plain ISI, which are slower than EventFilters. We want you to want to use the EventFilters because they would make the process much more efficient, and we are working tirelessly to make the experience of using event filters much less gruelling.

    However, as was mentioned previously on several occasions, implementing a feature properly takes time and effort. Ergonomics must be balanced against safety and reliability, so we cannot just make things easier to use. We want them to retain many of the advantages of strong typing.

    This is all a work in progress. Our code is in flux. We need time to play around with a particular implementation to optimise it.

    Supported ISI

    All Iroha Special Instructions work with triggers, specifically:

    • Register<Trigger>: Create a trigger object and subscribe it to global events.

    • Unregister<Trigger>: Remove a trigger from the World State View and stop passing events through it.

    • Mint<Trigger, u32>: For triggers that repeat a certain number of times, increase the number of times that the trigger gets executed. Can be done from inside the executable of the trigger.

    • Burn<Trigger, u32>: For triggers that repeat a certain number of times, decrease the number of times that the trigger gets executed.

      WARNING

      If the number provided is greater than the remaining number of repetitions, the instruction will fail to execute, and the transaction that it is part of will be rejected.

    You can learn more about Iroha Special Instructions in the dedicated section.

    Supported Queries

    We list supported queries for triggers when we talk in more detail about queries in the next chapter.


    1. The documentation on the EventFilter types is under construction, as we are likely to make major changes to that particular architecture. For now, suffice it to say that you can look at the source code in iroha_data_model and see a few particularly interesting applications. ↩︎

    2. This behaviour is likely to change in future releases.

      ↩︎
    + + + + \ No newline at end of file diff --git a/guide/blockchain/wasm.html b/guide/blockchain/wasm.html new file mode 100644 index 00000000..d5245910 --- /dev/null +++ b/guide/blockchain/wasm.html @@ -0,0 +1,67 @@ + + + + + + WASM | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    WASM

    While we had initially assumed that all operations within Iroha will be handled with instructions and conditionals, however, there are a few problems with this approach.

    • The ISI syntax is verbose and ugly.
    • The ISI syntax is not familiar for most programmers.
    • While simple ISI smart contracts are compact (usually a few bytes), they need different kinds of manual optimisations.

    In the long run, all of these problems are taken care of by using a domain-specific language, which gets optimised and compiled into a sequence of instructions that executes fast and takes very little space in the blocks, but is also easy to understand. Something that looks like your traditional if statements and for loops.

    However, in the interim, we have decided to use another portable binary standard called Web assembly, or WASM.

    Working with WASM

    The main advantage of using the WASM format is that you can use any language you like (as long as it links statically against our helper library), and produce a 32-bit portable executable. The compilers take care of the optimisation, and you don't have to learn a new language (ahem... solidity... ahem), just to operate on the blockchain.

    You'd still need to use ISI from inside your WASM binary to do anything on-chain, as we explained earlier.

    In theory, you can do anything you want just using ISI as it is a Turing-complete language. However, it'll be less convenient and efficient since you'd need to use metadata as memory and write complex conditionals using just the tools that we've provided in the Expression and ISI infrastructure. We highly recommend choosing a well-known programming language, such as Rust, to build the necessary logic out of simple instructions. This is much easier than trying to reinvent the wheel using ISI.

    Moreover, as long as you fit within the limits of WASM runtime and the provided libraries, you can do anything (and everything) you want. The drawback is that this process is a tad more involved than just writing the ISI using the client libraries.

    Simple Rust Smart Contract Example

    WASM projects, just like any other binary in Rust, need to be separate crates. Don't worry, it doesn't have to be big.

    1. Create a new project

    To get started, create a new project:

    bash
    $ cargo new --lib

    Yes! We need the lib type; more on that later.

    The Cargo.toml of your project should look something like this:

    toml
    [package]
    +name  = "smartcontract"
    +version = "0.1.0"
    +edition = "2021"
    +
    +[lib]
    +crate-type = ['cdylib']
    +
    +[dependencies]
    +iroha_wasm = { git = "https://github.com/hyperledger/iroha/"}

    Note that the crate type is cdylib. Most Rust code is linked in a non-portable architecture and OS-specific static manner, but WASM is a portable format. Since C ABI is the lingua franca of the programming world and there is no other stable Rust ABI (yet), Iroha relies on the C-linkage to generate WASM bindings. Thankfully, iroha_wasm takes care of everything related to foreign function interfaces (FFI), so you don't have to worry about things like unsafe, repr(C), padding, alignment, and others.

    The iroha_wasm crate contains all of the bindings, macros, and trait implementations that you'd need to write the program, most notably the iroha_wasm attribute macro. The crate also exposes our data_model, which contains all of the basic ISI and types. The chosen serialisation format is parity-scale-codec, though there is a strong possibility it'll get replaced with a different (custom) serialisation format in the near future, as it seems to dominate the binary size[1].

    2. Write a smart contract

    Now that we have the preliminaries nailed down, we get to write some code for our smart contract. In the src/lib.rs you should write the following:

    rust
    #![no_std]
    +#![no_main]
    +
    +extern crate alloc;
    +
    +use alloc::vec::Vec;
    +
    +use iroha_wasm::data_model::prelude::*;
    +
    +#[iroha_wasm::iroha_wasm]
    +fn smartcontract_entry_point(_account_id: AccountId) {
    +    let query = QueryBox::FindAllDomains(FindAllDomains {});
    +    let domains: Vec<Domain> = query.execute().try_into().unwrap();
    +
    +    for domain in domains {
    +        let new_account_id = AccountId {
    +            name: Name::new("mad_hatter").unwrap(),
    +            domain_id: domain.id,
    +        };
    +
    +        Instruction::Register(RegisterBox::new(NewAccount::new(new_account_id))).execute();
    +    }
    +}

    To submit the instruction and run it, execute the following command (be sure to have a peer up):

    cargo run --release

    What does this smart contract do? Let's see. It queries all of the currently existing domains and puts the results into a std::vec::Vec. In this case, std::vec::Vec has to be imported from alloc, as we use no_std (more on that later). It is then used to add the user named mad_hatter to all of the existing domains.

    Building the same logic out of Expression and If and Sequence would be significantly harder. Moreover, the actual low-level instructions that would run are very likely not going to be as well-optimised as what the compiler produces.

    Advanced Smart Contracts: Optimising for Size

    WASM smart contracts can get big. So big, in fact, that we might not let you store them in the blockchain. So how do you reduce the size? The most important modifications are done in Cargo.toml:

    toml
    [profile.release]
    +strip = "debuginfo" # Remove debugging info from the binary
    +panic = "abort"     # Abort panics as they are transcribed to Traps when compiling for WASM anyways
    +lto = true          # Use link-time-optimisation (it produces a notable decrease in binary size)
    +opt-level = "z"     # Optimise for size vs speed with "s"/"z"(removes vectorization)
    +codegen-units = 1   # Use one code generation unit (it further reduces the binary size but increases compilation time)

    Let's take a closer look at what you can do to reduce the size of the WASM binary.

    Remove debugging info

    Rust stores a lot of debug information (even when compiled in release mode), which is (as the name suggests) used for debugging a panic in your Rust application. As you would expect, this information increases the size of the compiled WASM significantly.

    Normally, this would be a worthwhile trade-off, but not in our case. Firstly, since the WASM is stored on-chain, it will be permanently recorded in some block and take space on every full node of an Iroha network. Iroha stores a lot of its information in RAM, so storage space for WASM is at a premium.

    Secondly, once the WASM smart contract is stored on-chain, the debug information is no longer accessible. Indeed, you shouldn't debug on a peer. Instead, you should replicate the conditions that caused the panic locally and debug on your personal machine.

    Work under a no_std environment

    Another step that we've already taken involves working under a no_std environment. All of our size-related woes stem from Rust being predominantly statically linked. As such, breaking the standard library into more manageable crates, like using alloc::vec instead of std::vec, can help us reduce the size and compilation time[2].

    Re-compile libcore

    Next, you're advised to re-compile libcore and any other standard library crate (e.g. alloc) to exclude the leftover panic-related code that comes with the prebuilt core library[3]:

    bash
    $ cargo +nightly build -Z build-std -Z build-std-features=panic_immediate_abort --target wasm32-unknown-unknown

    Unfortunately, this is an unstable feature. In other words, the developers of the Rust programming language can decide to change how this works, or remove this option entirely.

    Use tools to optimise WASM size

    Finally, you can use an automated tool to optimise the size of the WASM binary. You could use wasm-opt or twiggy to guide your manual optimisation efforts.

    We highly advise using wasm-opt because it will often significantly reduce your binary size:

    bash
    $ wasm-opt -Os -o output.wasm input.wasm

    Conclusion

    At some point, unfortunately, the smallest size of your WASM blob is going to be determined by the libraries that you need to use. Using all of the above steps on the provided smart contract can reduce it down to a manageable (for the blockchain) size.


    1. Size is an important metric. We shall cover size-optimisation strategies as we go. ↩︎

    2. It should be noted that excluding the standard library is necessary for compiling to the wasm32 target, and is thus mandatory. ↩︎

    3. wasm-opt can also be used to remove the debug sections. ↩︎

    + + + + \ No newline at end of file diff --git a/guide/blockchain/world.html b/guide/blockchain/world.html new file mode 100644 index 00000000..45a83791 --- /dev/null +++ b/guide/blockchain/world.html @@ -0,0 +1,31 @@ + + + + + + World | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    World

    World is the global entity that contains other entities. The World consists of:

    When domains, peers, or roles are registered or unregistered, the World is the target of the (un)register instruction.

    World State View (WSV)

    World State View is the in-memory representation of the current blockchain state. This includes all currently loaded blocks, with all of their contents, as well as peers elected for the current epoch.

    + + + + \ No newline at end of file diff --git a/guide/configure/client-configuration.html b/guide/configure/client-configuration.html new file mode 100644 index 00000000..6d67dc26 --- /dev/null +++ b/guide/configure/client-configuration.html @@ -0,0 +1,56 @@ + + + + + + Client Configuration | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Client Configuration

    Let's look at the client configuration options.

    Client configuration template
    toml
    # chain_id =
    +
    +## Might be set via `TORII_URL` env var
    +# torii_url =
    +
    +[basic_auth]
    +# login =
    +# password =
    +
    +[account]
    +# id =
    +# public_key =
    +# private_key =
    +
    +[transaction]
    +# time_to_live = "100s"
    +# status_timeout = "100s"
    +## Nonce is TODO describe what it is
    +# nonce = false

    Generation

    You can use kagami to generate the default client configuration:

    bash
    $ kagami config client > client-config.json

    Public and Private Keys

    The defaults/client.toml client configuration file should contain the user's domain and a pair of their cryptographic keys: public_key and private_key.

    For details on cryptographic keys, see Public Key Cryptography.

    User account

    The ACCOUNT_ID should be self-explanatory. The only thing you need to worry about is that the account must already exist in the blockchain. In other words, the account you provide here should already be registered.

    Note

    Iroha is case-sensitive, meaning that Alice@wonderland is different from alice@wonderland. It should go without saying that alice@wonderland is not the same as alice@looking_glass either, since these accounts belong to different domains, wonderland and looking_glass.

    Basic Authentication Credentials

    The idea of basic authentication credentials is to provide the access control using a web server with a reverse proxy like Nginx while these credentials are ignored by the Iroha peers.

    The login and password will be filled by the client and used for the Authorization HTTP header.

    Use this style of configuration to provide the basic authentication credentials (login and password):

    json
      "BASIC_AUTH": {
    +    "web_login": "mad_hatter",
    +    "password": "ilovetea"
    +  },

    Iroha Public Addresses

    TORII is the module in charge of handling incoming and outgoing connections. For client configuration, you can set up two addresses: TORII_API_URL and TORII_TELEMETRY_URL.

    TORII_API_URL

    First, the TORII_API_URL is the same as TORII API_URL in the peer configuration. This is the module responsible for handling incoming and outgoing connections. You should also add the prefix http:// or (preferably) https:// to the address. For example:

    json
    "TORII_API_URL": "http://127.0.0.1:8080"

    TORII_TELEMETRY_URL

    The TORII_TELEMETRY_URL is used to specify the prometheus endpoint address. You can set TORII_TELEMETRY_URL like this:

    json
    "TORII_TELEMETRY_URL": "http://127.0.0.1:8180"

    A GET request to the 127.0.0.1:8180/status will give you a JSON-encoded representation of the top-level metrics, while a GET request to 127.0.0.1:8180/metrics will give you a (somewhat verbose) list of all available metrics gathered in Iroha. You might want to change this if you're having trouble gathering metrics using prometheus.

    INFO

    Learn how to monitor Iroha performance using prometheus.

    Transaction Limits

    You can specify the transaction limits that each transaction must adhere to: the maximum number of instructions and the maximum size of a WASM blob (in bytes). For example:

    json
    {
    +  "max_instruction_number": 4096,
    +  "max_wasm_size_bytes": 4194304
    +}

    Transaction TTL and Timeout

    Configure the time-to-live (TTL) for transactions and the timeout to wait for the status. Both values have to be provided in milliseconds. For example:

    json
    "TRANSACTION_TIME_TO_LIVE_MS": 100000,
    +"TRANSACTION_STATUS_TIMEOUT_MS": 15000,

    Transaction Nonce

    If you set ADD_TRANSACTION_NONCE to true, Iroha will create different hashes for transactions that occur repeatedly and simultaneously.

    + + + + \ No newline at end of file diff --git a/guide/configure/configuration-types.html b/guide/configure/configuration-types.html new file mode 100644 index 00000000..a8b51008 --- /dev/null +++ b/guide/configure/configuration-types.html @@ -0,0 +1,31 @@ + + + + + + Configuration Types | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Configuration Types

    Configuration options have different underlying types and default values, which are denoted in code as types wrapped in a single Option<..> or in a double Option<Option<..>>.

    In this section we explain the difference between Option<..> and Option<Option<..>> used for configuration types. You can find more about available configuration options in the Peer Configuration topic.

    Option<..>

    A type wrapped in a single Option<..> signifies that in the corresponding json block there is a fallback value for this type, and that it only serves as a reference.

    If a default for such a type has a null value, it means that

    there is no meaningful fallback available for this particular value. It doesn't mean that you can omit the value. Quite the opposite, it must be set manually, either in the configuration file, or via the environment variables.

    All the default values can be freely obtained from a provided sample configuration file, but it is only a starting point. **If left unchanged, the sample configuration file will not work. All null values in place of public and private keys as well as endpoint URLs should be provided either by modifying the sample config file or as environment variables. No other overloading of configuration values happens besides reading them from a file and capturing the environment variables, and environment variables take precedence.

    For both types of configuration options wrapped in a single Option<..> (i.e. both those that have meaningful defaults and those that have null), failure to provide them in any of the above two ways results in an error.

    Option<Option<..>>

    Option<Option<..>> types should be distinguished from types wrapped in a single Option<..>. Only the double option ones are allowed to stay null, meaning that not providing them in an environment variable or a file will not cause an error.

    Thus, only these types are truly optional in the common sense of the word. An example of this distinction is genesis public and private keys. While the first one is a single Option<..> wrapped type, the latter is wrapped in Option<Option<..>>. This means that the genesis public key should always be provided by the user, be it via a file config or an environment variable, whereas the private key is only needed for the peer that submits the genesis block, and can be omitted for all others. The same logic goes for other double option fields such as logger file path.

    Sumeragi: default null values

    A special note about Sumeragi fields with null as default: only the trusted_peers field out of the three can be initialized via a provided file or an environment variable.

    The other two fields, namely key_pair and peer_id, go through a process of finalization where their values are derived from the corresponding ones in the uppermost Iroha config (using its public_key and private_key fields) or the Torii config (via its p2p_addr). This ensures that these linked fields stay in sync, and prevents the programmer error when different values are provided to these field pairs. Providing either sumeragi.key_pair or sumeragi.peer_id by hand will result in an error, as it should never be done directly. In later versions these configuration options shall be hidden completely.

    + + + + \ No newline at end of file diff --git a/guide/configure/genesis.html b/guide/configure/genesis.html new file mode 100644 index 00000000..7baca2cd --- /dev/null +++ b/guide/configure/genesis.html @@ -0,0 +1,221 @@ + + + + + + Genesis Block | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Genesis Block

    The genesis block is the first block in your blockchain. It's never empty, even if configs/peer/genesis.json is. Here's an example:

    Genesis Block Example: alice@wonderland
    json
    {
    +  "transactions": [
    +    [
    +      {
    +        "Register": {
    +          "Domain": {
    +            "id": "wonderland",
    +            "logo": null,
    +            "metadata": {
    +              "key": {
    +                "String": "value"
    +              }
    +            }
    +          }
    +        }
    +      },
    +      {
    +        "Register": {
    +          "Account": {
    +            "id": "alice@wonderland",
    +            "signatories": [
    +              "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0"
    +            ],
    +            "metadata": {
    +              "key": {
    +                "String": "value"
    +              }
    +            }
    +          }
    +        }
    +      },
    +      {
    +        "Register": {
    +          "Account": {
    +            "id": "bob@wonderland",
    +            "signatories": [
    +              "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0"
    +            ],
    +            "metadata": {
    +              "key": {
    +                "String": "value"
    +              }
    +            }
    +          }
    +        }
    +      },
    +      {
    +        "Register": {
    +          "AssetDefinition": {
    +            "id": "rose#wonderland",
    +            "value_type": "Numeric",
    +            "mintable": "Infinitely",
    +            "logo": null,
    +            "metadata": {}
    +          }
    +        }
    +      },
    +      {
    +        "Register": {
    +          "Domain": {
    +            "id": "garden_of_live_flowers",
    +            "logo": null,
    +            "metadata": {}
    +          }
    +        }
    +      },
    +      {
    +        "Register": {
    +          "Account": {
    +            "id": "carpenter@garden_of_live_flowers",
    +            "signatories": [
    +              "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0"
    +            ],
    +            "metadata": {}
    +          }
    +        }
    +      },
    +      {
    +        "Register": {
    +          "AssetDefinition": {
    +            "id": "cabbage#garden_of_live_flowers",
    +            "value_type": "Numeric",
    +            "mintable": "Infinitely",
    +            "logo": null,
    +            "metadata": {}
    +          }
    +        }
    +      },
    +      {
    +        "Mint": {
    +          "Asset": {
    +            "object": "13",
    +            "destination_id": "rose##alice@wonderland"
    +          }
    +        }
    +      },
    +      {
    +        "Mint": {
    +          "Asset": {
    +            "object": "44",
    +            "destination_id": "cabbage#garden_of_live_flowers#alice@wonderland"
    +          }
    +        }
    +      },
    +      {
    +        "Transfer": {
    +          "Domain": {
    +            "source_id": "genesis@genesis",
    +            "object": "wonderland",
    +            "destination_id": "alice@wonderland"
    +          }
    +        }
    +      },
    +      {
    +        "Grant": {
    +          "PermissionToken": {
    +            "object": {
    +              "definition_id": "CanSetParameters",
    +              "payload": null
    +            },
    +            "destination_id": "alice@wonderland"
    +          }
    +        }
    +      },
    +      {
    +        "NewParameter": "?MaxTransactionsInBlock=512"
    +      },
    +      {
    +        "NewParameter": "?BlockTime=2000"
    +      },
    +      {
    +        "NewParameter": "?CommitTimeLimit=4000"
    +      },
    +      {
    +        "NewParameter": "?TransactionLimits=4096,4194304_TL"
    +      },
    +      {
    +        "NewParameter": "?WSVDomainMetadataLimits=1048576,4096_ML"
    +      },
    +      {
    +        "NewParameter": "?WSVAssetDefinitionMetadataLimits=1048576,4096_ML"
    +      },
    +      {
    +        "NewParameter": "?WSVAccountMetadataLimits=1048576,4096_ML"
    +      },
    +      {
    +        "NewParameter": "?WSVAssetMetadataLimits=1048576,4096_ML"
    +      },
    +      {
    +        "NewParameter": "?WSVTriggerMetadataLimits=1048576,4096_ML"
    +      },
    +      {
    +        "NewParameter": "?WSVIdentLengthLimits=1,128_LL"
    +      },
    +      {
    +        "NewParameter": "?ExecutorFuelLimit=55000000"
    +      },
    +      {
    +        "NewParameter": "?ExecutorMaxMemory=524288000"
    +      },
    +      {
    +        "NewParameter": "?WASMFuelLimit=55000000"
    +      },
    +      {
    +        "NewParameter": "?WASMMaxMemory=524288000"
    +      },
    +      {
    +        "Register": {
    +          "Role": {
    +            "id": "ALICE_METADATA_ACCESS",
    +            "permissions": [
    +              {
    +                "definition_id": "CanRemoveKeyValueInAccount",
    +                "payload": {
    +                  "account_id": "alice@wonderland"
    +                }
    +              },
    +              {
    +                "definition_id": "CanSetKeyValueInAccount",
    +                "payload": {
    +                  "account_id": "alice@wonderland"
    +                }
    +              }
    +            ]
    +          }
    +        }
    +      }
    +    ]
    +  ],
    +  "executor_file": "./executor.wasm"
    +}

    The genesis account is specified in the peer configuration file, configs/peer/config.json. This is the account that will submit the genesis block. The genesis account is like a super user account that has elevated privileges, but only during the genesis round. The genesis account should be signed by one of the peers, or, in other words, it should have the public key of this peer.

    If you look at the example of a genesis block above, you will see that it contains instructions for registering a new domain (wonderland), two new accounts (alice@wonderland and bob@wonderland), a new asset (rose#wonderland) and a Mint instruction for this asset, as well as several permission tokens and roles. Both new accounts are signed with the ed01207233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0 public key.

    Note

    Iroha is case-sensitive, meaning that Alice@wonderland is different from alice@wonderland. It should go without saying that alice@wonderland is not the same as alice@looking_glass either, since these accounts belong to different domains, wonderland and looking_glass.

    The accounts registered in the genesis block are just new accounts. As we said above, the genesis account is determined in the peer configuration. However, you can use the matching signature for the genesis account and for a new account in the genesis block. Since the genesis account only has privileges during the genesis round, it won't be a security issue.

    You can generate the default genesis block or create a custom one.

    If you need to recommit a genesis block, remove the previously stored blocks, then restart the Docker container. The new genesis block will be automatically recommited upon container restart.

    Generation

    You can add various instructions to the genesis block, such as registering new accounts or assets, as well as minting assets. You can also register permission tokens and roles, as well as grant them to the registered accounts.

    Generate default genesis block

    You can use kagami to generate the default genesis block:

    • Generate a genesis block in JSON format:

      bash
      $ kagami genesis
    • Generate a genesis block in JSON format and write the output to the specified file:

      bash
      $ kagami genesis > genesis.json
    • Generate a synthetic genesis block in JSON format and write the n domains, m accounts per domain and p assets per domain:

      bash
      $ kagami genesis --synthetic --domains n --accounts-per-domain m --assets-per-domain p

    The genesis block should be located in configs/peer/genesis.json.

    Configuration

    As we already explained, genesis account is specified in the peer configuration file, configs/peer/config.json. You can use the same configuration file to fine-tune other genesis block configurations.

    + + + + \ No newline at end of file diff --git a/guide/configure/keys-for-network-deployment.html b/guide/configure/keys-for-network-deployment.html new file mode 100644 index 00000000..2542e478 --- /dev/null +++ b/guide/configure/keys-for-network-deployment.html @@ -0,0 +1,31 @@ + + + + + + Keys for Network Deployment | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Keys for Network Deployment

    If you're deploying your own Iroha 2 network, your unique cryptographic keys must be specified in all configuration files:

    1. Client configuration file: defaults/client.toml
    2. Genesis block file: defaults/genesis.json

    To learn more about cryptographic keys and their role, see Security > Public Key Cryptography.

    Setting Keys For a New Network

    1. Generate New Key Pairs

    To generate new key pairs for the peers, a wide variety of methods can be used. However, within the Iroha 2 framework, you can conveniently use the built-in kagami tool for generating cryptographic keys.

    To generate a new key pair run the following command from the project's root directory:

    bash
    $ cargo run --bin kagami --release -- crypto --json

    Note

    The output cryptographic keys generated by kagami are customizable by using preferences. Note that in the example above the --json parameter is specified to generate a key pair in the JSON format.

    To learn more about generating cryptographic keys with kagami, available algorithms, and other parameters, see Generating Cryptographic Keys with Kagami.

    If you plan to use the generated private_key with one of our SDKs, note that even though cryptographic keys are commonly encoded using ASCII characters, both the payload value of the private_key and the string representation of the public_key are encoded as Hex.

    2. Update Keys For Peers

    If you want to set up your own network, you should change the keys for all your peers: in peer/config.json change PUBLIC_KEY and PRIVATE_KEY to the fresh pair. When you've done that, you should add the keys to the TRUSTED_PEERS array in the same configuration file. Every peer that wants to connect to the given peer from the outside must know its PRIVATE_KEY specified in the TRUSTED_PEERS section.

    To create a minimum BFT network one needs four peers, which means four different private keys split across four different configuration files (or environment variables).

    Each peer must have their own PUBLIC_KEY and PRIVATE_KEY variables specified. All four of the public keys—including the peer that is being configured—must be added to the TRUSTED_PEERS array. The same TRUSTED_PEERS array must be copied across all four of the configuration files. If either one of the peers is missing, or there's an extraneous peer or one of the peers has the incorrect key, the network will fail to start.

    After that, make sure that the peers agree on the GENESIS_ACCOUNT key pairs. Failure to do so will result in a network which cannot accept any transactions.

    Note

    Even though the private key for the genesis account is known to all peers, the account itself loses all privileges after the first block is committed.

    3. Register a Non-Genesis Account

    Finally, while the first client could use the genesis account to register new users, it's not a great idea for most networks. You should, instead, register a non-genesis account (for example, alice@wonderland).

    WARNING

    iroha binary currently processes all of its instructions in the JSON format, it also provides a dedicated instruction to unregister accounts.

    If you plan on creating a private blockchain, you should consider writing your own client based on the client Rust crate, or any of the provided client libraries:

    + + + + \ No newline at end of file diff --git a/guide/configure/metadata-and-store-assets.html b/guide/configure/metadata-and-store-assets.html new file mode 100644 index 00000000..31743e2e --- /dev/null +++ b/guide/configure/metadata-and-store-assets.html @@ -0,0 +1,31 @@ + + + + + + Choosing Between the Store and Metadata Assets | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content
    + + + + \ No newline at end of file diff --git a/guide/configure/modes.html b/guide/configure/modes.html new file mode 100644 index 00000000..23bbfdcc --- /dev/null +++ b/guide/configure/modes.html @@ -0,0 +1,31 @@ + + + + + + Public and Private Blockchains | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Public and Private Blockchains

    Iroha can be ran in a variety of configurations. As the administrator of your own network, you can use different permission sets to decide what criteria must be met in order for some transaction to be accepted.

    We provide two major sets of permissions: called a private and public permission sets. These need to be added into the genesis.json before you start an Iroha peer.

    Below we outline the major differences in these two use cases.

    Permissions

    In a public blockchain, most accounts have the same set of permissions. In a private blockchain, most accounts are assumed not to be able to do anything outside of their own account or domain unless explicitly granted said permission.

    INFO

    Refer to the dedicated section on permissions for more details.

    Peers

    Any peer can join a public blockchain. For a private blockchain, automatic discovery of peers is turned off.

    INFO

    Refer to peer management for more details.

    Registering accounts

    Depending on how you decide to set up your genesis block (genesis.json), the process for registering an account might go one of two ways. To understand why, let's talk about permission first.

    By default, Iroha allows all instructions to go through, until a permission validator that can restrict instruction execution has been registered. You can add permission validators to your genesis block by registering built-in permission tokens that we thought would be useful for private and public blockchain use-cases. However, in that case, the process of registering accounts is different.

    When it comes to registering accounts, public and private blockchain have the following differences:

    • In a public blockchain, anyone should be able to register an account[1]. So, in theory, all that you need is a suitable client, a way to generate a private key of a suitable type (ED25519), and that's it.

    • In a private blockchain, you can have any process for setting up an account: it could be that the registering instruction has to be submitted by a specific account, or by a smart contract that asks for other details. It could be that in a private blockchain registering new accounts is only possible on specific dates, or limited by a non-mintable (finite) token.

    • In a typical private blockchain, i.e. a blockchain without any unique processes for registering accounts, you need an account to register another account.

    Built-in permission validators for private blockchains cover the `typical private blockchain use-case.

    INFO

    As of writing, the set of public blockchain permissions is incomplete, and as such Iroha source code needs to be modified to run it in the public mode.

    Refer to the section on instructions for more details about Register<Account> instructions.


    1. In fact, once we have finished with our key-centric address scheme for accounts, you don't register an account as much as claim it. ↩︎

    + + + + \ No newline at end of file diff --git a/guide/configure/overview.html b/guide/configure/overview.html new file mode 100644 index 00000000..635e4ab1 --- /dev/null +++ b/guide/configure/overview.html @@ -0,0 +1,31 @@ + + + + + + Configuration and Management | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/guide/configure/peer-configuration.html b/guide/configure/peer-configuration.html new file mode 100644 index 00000000..a7a2a7c6 --- /dev/null +++ b/guide/configure/peer-configuration.html @@ -0,0 +1,97 @@ + + + + + + Peer Configuration | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Peer Configuration

    The peer configuration file (configs/peer/config.json) determines how your blockchain operates.

    Here's an example of how peer configuration file looks like:

    Peer configuration template
    toml
    ## For the full reference, go to (TODO put link)
    +
    +## You can use another TOML file to extend from.
    +## For a single file extension:
    +# extends = "./base.toml"
    +## Or, for a chain of extensions:
    +# extends = ["base-1.toml", "base-2.toml"]
    +
    +# chain_id =
    +# public_key =
    +# private_key = {
    +#   algorithm = ,
    +#   payload =
    +# }
    +
    +[genesis]
    +# file =
    +# public_key =
    +# private_key =
    +
    +[network]
    +# address =
    +# block_gossip_period = "10s"
    +# block_gossip_max_size = 4
    +# transaction_gossip_period = "1s"
    +# transaction_gossip_max_size = 500
    +# idle_timeout = "60s"
    +
    +[torii]
    +# address =
    +# max_content_len = "16mb"
    +# query_idle_time = "30s"
    +
    +[kura]
    +# init_mode = "strict"
    +# store_dir = "./storage"
    +
    +## Add more of this section for each trusted peer
    +# [[sumeragi.trusted_peers]]
    +# address =
    +# public_key =
    +
    +[logger]
    +# level = "INFO"
    +# format = "full"
    +
    +## Transactions Queue
    +[queue]
    +# capacity = 65536
    +# capacity_per_user = 65536
    +# transaction_time_to_live = "1day"
    +# future_threshold = "1s"
    +
    +[snapshot]
    +# mode = "read_write"
    +# create_every = "1min"
    +# store_dir = "./storage/snapshot"
    +
    +[telemetry]
    +# name =
    +# url =
    +# min_retry_period = "1s"
    +# max_retry_delay_exponent = 4
    +
    +[dev_telemetry]
    +## A path to a file with JSON logs
    +# out_file = "./dev_telemetry.json"

    INFO

    Note that for convenient container deployment, configuration options specified via environment variables always override the corresponding values in the configuration file. This way, you can have a basic configuration file and also configure some options in a docker-compose.yml or in your shell's environment file (.bashrc, .zshrc, etc.).

    Some of the configuration options are required, while others are used for fine-tuning. When you create a new peer, you are required to provide the following:

    INFO

    Configuration options have different underlying types and default values, which are denoted in code as types wrapped in a single Option<..> or in a double Option<Option<..>>. Refer to configuration types for details.

    Generation

    You can use kagami to generate the default peer configuration:

    bash
    $ kagami config peer > peer-config.json

    Public and private keys

    The configs/peer/config.json peer configuration file should contain a pair of the user's public PUBLIC_KEY and private PRIVATE_KEY cryptographic keys for their account's ACCOUNT_ID.

    For details on cryptographic keys, see Public Key Cryptography.

    Trusted Peers

    Iroha is a blockchain ledger. In order for it to work optimally and be Byzantine-fault tolerant with the maximum number of faults allowed, it needs to be started with a set number of peers: 4, 7, 10, ... 3f+1, where f is the allowed number of faults.

    So usually, when you want to start an Iroha deployment, you should already know a number of peers that you can trust and join their blockchain. The way it works in the examples is that you just specify in four config.json files four peers with their public keys and API addresses.

    Since Iroha has no automatic peer discovery, the only other way to make peers known to each other is to use the iroha binary to register new peers). This is not too difficult with the provided client libraries. With Python's Beautiful Soup, the curated list of peers can be updated, registered, and un-registered on its own.

    The list of trusted peers is a part of SUMERAGI configuration. Here's an example of SUMERAGI_TRUSTED_PEERS environment variable to configure trusted peers:

    '[{"address":"iroha0:1337", "public_key": "ed01201c61faf8fe94e253b93114240394f79a607b7fa55f9e5a41ebec74b88055768b"}, {"address":"iroha1:1338", "public_key": "ed0120cc25624d62896d3a0bfd8940f928dc2abf27cc57cefeb442aa96d9081aae58a1"}, {"address": "iroha2:1339", "public_key": "ed0120faca9e8aa83225cb4d16d67f27dd4f93fc30ffa11adc1f5c88fd5495ecc91020"}, {"address": "iroha3:1340", "public_key": "ed01208e351a70b6a603ed285d666b8d689b680865913ba03ce29fb7d13a166c4e7f1f"}]'

    Iroha Public Addresses

    TORII is the module in charge of handling incoming and outgoing connections.

    API_URL

    The API_URL is the location to which the client(s) make their requests. You can also use it to change some peer-specific configuration options.

    Most of the time, the only reason to change the API_URL is to change the port, in case 8080 is either closed, or if you want to randomise ports to avoid certain kinds of attacks.

    P2P_ADDR

    The P2P_ADDR is the internal address used for communication between peers. This address should be included in the TRUSTED_PEERS section of the configuration file.

    TELEMETRY_URL

    The TELEMETRY_URL is used to specify the prometheus endpoint address. It's set by adding "TELEMETRY_URL": "127.0.0.1:8180" to the TORII section of the configuration file.

    It's not meant to be human-readable. However, a GET request to the 127.0.0.1:8180/status will give you a JSON-encoded representation of the top-level metrics, while a GET request to 127.0.0.1:8180/metrics will give you a (somewhat verbose) list of all available metrics gathered in Iroha. You might want to change this if you're having trouble gathering metrics using prometheus.

    INFO

    Learn how to monitor Iroha performance using prometheus.

    Genesis

    When you configure a peer, you have to provide private and public keys for the genesis account.

    You can do this via the configuration file (ACCOUNT_PUBLIC_KEY, ACCOUNT_PRIVATE_KEY) or environment variables (IROHA_GENESIS_ACCOUNT_PUBLIC_KEY, IROHA_GENESIS_ACCOUNT_PRIVATE_KEY).

    To learn more about genesis block, genesis account, and cryptographic keys, see the following:

    Aside from the public and private keys for the genesis account, which are required configuration options, you can also fine-tune other genesis block configurations, such as:

    • WAIT_FOR_PEERS_RETRY_COUNT_LIMIT: the number of attempts to connect to peers before genesis block is submitted
    • WAIT_FOR_PEERS_RETRY_PERIOD_MS: how long to wait before retrying a connection to peers
    • GENESIS_SUBMISSION_DELAY_MS: the delay before the genesis block submission after the minimum number of peers were discovered.

    Logger

    Let's cover the most useful LOGGER configurations, MAX_LOG_LEVEL and LOG_FILE_PATH.

    MAX_LOG_LEVEL

    The MAX_LOG_LEVEL is used to determine which messages are logged.

    With "MAX_LOG_LEVEL": "WARN" you won't get any messages unless they are either a warning or an error. Beside WARN, other available options are:

    • TRACE (log every time you enter a function)
    • DEBUG (use when you know something went wrong)
    • INFO (the default)
    • WARN (log everything that could be an error)
    • ERROR (to silence any logging except for error messages)

    LOG_FILE_PATH

    Another useful option is "LOG_FILE_PATH": bunyan.json. It creates (if it didn't already exist) a file called bunyan.json that contains the message log in a structured format.

    This is extremely useful for two reasons. Firstly, you can use the bunyan log viewer to filter information more precisely than Iroha would allow you to do. Do you only want messages from a specific module or package? You can do that with bunyan. Secondly, while copying logs is not too big of a problem if your instance is just a small setup, for bigger setups the log will be larger. Having it saved to a file makes much more sense in that case.

    INFO

    You can also set LOG_FILE_PATH to /dev/stdout if you want to use bunyan's logging facilities directly without saving the output.

    Kura

    Kura is the persistent storage engine of Iroha (Japanese for warehouse). The BLOCK_STORE_PATH specifies where the blocks are stored. You can change it to a custom location if for some reason the default location (./storage) is not available or desirable.

    + + + + \ No newline at end of file diff --git a/guide/configure/peer-management.html b/guide/configure/peer-management.html new file mode 100644 index 00000000..07b720cd --- /dev/null +++ b/guide/configure/peer-management.html @@ -0,0 +1,31 @@ + + + + + + Peer Management | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Peer Management

    If you followed any of the language-specific guides, you now have a well-functioning network that people will want to join.

    Public Blockchain

    Naturally, in a public blockchain, joining is a matter of installing the correct software and waiting until your node gets discovered.

    INFO

    Peer discovery is under construction.

    Private Blockchain

    In a bank setting, allowing everyone to join at their leisure is a security nightmare. For safety, automatic discovery of peers is turned off for Iroha 2 in the private blockchain configuration.

    Registering peers

    To add a peer to the network, it must be manually registered. Let's discuss the steps that should be taken in order to complete this process.

    1. Grant the user permissions

    The user that registers the peer must have the appropriate PermissionToken. This could be granted as part of a role, or as part of a one-time allowance.

    How to decide if you need to grant a role? Granting roles makes sense if a user is to serve as an administrator of sorts, where it's their responsibility to maintain the peers in the network long-term. A one-time permission grant is useful when the party registering the peer isn't responsible for registering peers in general, but the network administrator doesn't need to (or want to) spend time setting up a new peer.

    INFO

    Permissions for registering a peer are under construction.

    We discuss permissions and roles with more detail in a separate chapter.

    2. Set up a peer

    After a new peer was granted permissions, it must be set up.

    It's a good idea to request information about the peers' configuration in the network. Your best friend is the configuration endpoint of the API socket. Thus far querying is done manually. Until the bootstrapping procedure is implemented, you'll have to manually check that the timeouts and batch sizes match.

    To simplify the process, you can ask the network administrator for a redacted version of config.json, which excludes privileged information, such as PRIVATE_KEYs.

    3. Submit the instruction

    After your peer is running, you should submit the register peer instruction. The peer will go through the handshake process and start chatting with the network.

    TIP

    Submitting a Register<Peer> instruction does not (and cannot) instantiate a new peer process.

    Unregistering peers

    What about unregistering peers? For security reasons this process is one-sided. The network reaches consensus that it wants to remove a peer, but the peer itself doesn't know much about why nobody's talking to it.

    In most circumstances, if you want to unregister a peer, you want to do so because it is a Byzantine fault. Just "ghosting" this peer makes the life of the malicious actor on the network harder.

    + + + + \ No newline at end of file diff --git a/guide/configure/sample-configuration.html b/guide/configure/sample-configuration.html new file mode 100644 index 00000000..23e81b57 --- /dev/null +++ b/guide/configure/sample-configuration.html @@ -0,0 +1,239 @@ + + + + + + Sample Configuration Files | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Sample Configuration Files

    Here you can find sample configuration files for Iroha 2:

    json
    {
    +  "transactions": [
    +    [
    +      {
    +        "Register": {
    +          "Domain": {
    +            "id": "wonderland",
    +            "logo": null,
    +            "metadata": {
    +              "key": {
    +                "String": "value"
    +              }
    +            }
    +          }
    +        }
    +      },
    +      {
    +        "Register": {
    +          "Account": {
    +            "id": "alice@wonderland",
    +            "signatories": [
    +              "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0"
    +            ],
    +            "metadata": {
    +              "key": {
    +                "String": "value"
    +              }
    +            }
    +          }
    +        }
    +      },
    +      {
    +        "Register": {
    +          "Account": {
    +            "id": "bob@wonderland",
    +            "signatories": [
    +              "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0"
    +            ],
    +            "metadata": {
    +              "key": {
    +                "String": "value"
    +              }
    +            }
    +          }
    +        }
    +      },
    +      {
    +        "Register": {
    +          "AssetDefinition": {
    +            "id": "rose#wonderland",
    +            "value_type": "Numeric",
    +            "mintable": "Infinitely",
    +            "logo": null,
    +            "metadata": {}
    +          }
    +        }
    +      },
    +      {
    +        "Register": {
    +          "Domain": {
    +            "id": "garden_of_live_flowers",
    +            "logo": null,
    +            "metadata": {}
    +          }
    +        }
    +      },
    +      {
    +        "Register": {
    +          "Account": {
    +            "id": "carpenter@garden_of_live_flowers",
    +            "signatories": [
    +              "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0"
    +            ],
    +            "metadata": {}
    +          }
    +        }
    +      },
    +      {
    +        "Register": {
    +          "AssetDefinition": {
    +            "id": "cabbage#garden_of_live_flowers",
    +            "value_type": "Numeric",
    +            "mintable": "Infinitely",
    +            "logo": null,
    +            "metadata": {}
    +          }
    +        }
    +      },
    +      {
    +        "Mint": {
    +          "Asset": {
    +            "object": "13",
    +            "destination_id": "rose##alice@wonderland"
    +          }
    +        }
    +      },
    +      {
    +        "Mint": {
    +          "Asset": {
    +            "object": "44",
    +            "destination_id": "cabbage#garden_of_live_flowers#alice@wonderland"
    +          }
    +        }
    +      },
    +      {
    +        "Transfer": {
    +          "Domain": {
    +            "source_id": "genesis@genesis",
    +            "object": "wonderland",
    +            "destination_id": "alice@wonderland"
    +          }
    +        }
    +      },
    +      {
    +        "Grant": {
    +          "PermissionToken": {
    +            "object": {
    +              "definition_id": "CanSetParameters",
    +              "payload": null
    +            },
    +            "destination_id": "alice@wonderland"
    +          }
    +        }
    +      },
    +      {
    +        "NewParameter": "?MaxTransactionsInBlock=512"
    +      },
    +      {
    +        "NewParameter": "?BlockTime=2000"
    +      },
    +      {
    +        "NewParameter": "?CommitTimeLimit=4000"
    +      },
    +      {
    +        "NewParameter": "?TransactionLimits=4096,4194304_TL"
    +      },
    +      {
    +        "NewParameter": "?WSVDomainMetadataLimits=1048576,4096_ML"
    +      },
    +      {
    +        "NewParameter": "?WSVAssetDefinitionMetadataLimits=1048576,4096_ML"
    +      },
    +      {
    +        "NewParameter": "?WSVAccountMetadataLimits=1048576,4096_ML"
    +      },
    +      {
    +        "NewParameter": "?WSVAssetMetadataLimits=1048576,4096_ML"
    +      },
    +      {
    +        "NewParameter": "?WSVTriggerMetadataLimits=1048576,4096_ML"
    +      },
    +      {
    +        "NewParameter": "?WSVIdentLengthLimits=1,128_LL"
    +      },
    +      {
    +        "NewParameter": "?ExecutorFuelLimit=55000000"
    +      },
    +      {
    +        "NewParameter": "?ExecutorMaxMemory=524288000"
    +      },
    +      {
    +        "NewParameter": "?WASMFuelLimit=55000000"
    +      },
    +      {
    +        "NewParameter": "?WASMMaxMemory=524288000"
    +      },
    +      {
    +        "Register": {
    +          "Role": {
    +            "id": "ALICE_METADATA_ACCESS",
    +            "permissions": [
    +              {
    +                "definition_id": "CanRemoveKeyValueInAccount",
    +                "payload": {
    +                  "account_id": "alice@wonderland"
    +                }
    +              },
    +              {
    +                "definition_id": "CanSetKeyValueInAccount",
    +                "payload": {
    +                  "account_id": "alice@wonderland"
    +                }
    +              }
    +            ]
    +          }
    +        }
    +      }
    +    ]
    +  ],
    +  "executor_file": "./executor.wasm"
    +}
    toml
    # chain_id =
    +
    +## Might be set via `TORII_URL` env var
    +# torii_url =
    +
    +[basic_auth]
    +# login =
    +# password =
    +
    +[account]
    +# id =
    +# public_key =
    +# private_key =
    +
    +[transaction]
    +# time_to_live = "100s"
    +# status_timeout = "100s"
    +## Nonce is TODO describe what it is
    +# nonce = false
    + + + + \ No newline at end of file diff --git a/guide/get-started/index.html b/guide/get-started/index.html new file mode 100644 index 00000000..b29ded3a --- /dev/null +++ b/guide/get-started/index.html @@ -0,0 +1,31 @@ + + + + + + Iroha 2 | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Iroha 2

    Iroha 2 is a fully-featured blockchain ledger. With Iroha 2 you can:

    • Create and manage custom fungible assets, such as currencies, gold, etc.
    • Create and manage non-fungible assets, such as digital art, intellectual property, etc.
    • Manage user accounts with a domain hierarchy and multi-signature transactions.
    • Use efficient portable smart contracts implemented with WebAssembly and Iroha Special Instructions.
    • Use both permissioned and permissionless blockchain deployments.

    Get Started

    If you are just starting with Iroha 2, begin with the following step-by-step tutorials:

    1. Install Iroha 2: install prerequisites and clone the GitHub repository.
    2. Launch Iroha 2: install prerequisites and establish an instance of Iroha network.
    3. Operate Iroha 2 via CLI: learn how to setup and configure Iroha Client, and perform necessary basic operations on the network (e.g., registering domains and accounts, registering and minting assets, etc.).

    If you would like to operate Iroha 2 using a different programming language, Iroha provides SDKs and language-specific tutorials for the following languages:

    TIP

    The current version of Iroha covered in this documentation is Iroha 2. If you have previously worked with Iroha 1, you may want to start with the Iroha 2 vs. Iroha 1 comparison that will help you understand the improvements and new features of Iroha 2.

    Explore In-Depth

    Once you have learned the basics, we suggest exploring the following sections:

    Learn More

    For more information on Iroha, see the following:

    For more information on Iroha 1, see the official Hyperledger Iroha documentation.

    TIP

    If you want to contribute to Hyperledger Iroha, see the Contributing Guide.

    + + + + \ No newline at end of file diff --git a/guide/get-started/install-iroha-2.html b/guide/get-started/install-iroha-2.html new file mode 100644 index 00000000..8715aec2 --- /dev/null +++ b/guide/get-started/install-iroha-2.html @@ -0,0 +1,31 @@ + + + + + + Install Iroha 2 | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Install Iroha 2

    This tutorial guides you through the steps to install Iroha 2 and its necessary binaries on your machine.

    1. Prerequisites

    To install Iroha 2, you need to set up the following first:

    TIP: How to Install OpenSSL

    Note that in most Linux setups OpenSSL is already available to you.

    • Install OpenSSL on Ubuntu:

      bash
      $ sudo apt-get install libssl-dev
    • Install OpenSSL on macOS using brew:

      bash
      $ brew install openssl

    Check the OpenSSL installation guide for details.

    2. Clone Iroha from GitHub

    1. Create a new directory for Iroha. In this tutorial we use Git as an example, but you can name it anything else:

      bash
      $ mkdir -p ~/Git

      TIP

      On macOS, if you get the fatal: could not create work tree dir 'iroha': Read-only file system error, that is because the home directory is not a real file system.

      To fix this, create a directory named Git.

    2. Enter the directory that you created:

      bash
      $ cd ~/Git
    3. Clone the iroha GitHub repository:

      bash
      $ git clone https://github.com/hyperledger/iroha.git

    3. Install Iroha Binaries

    To get started you need two of the binaries shipped with Iroha:

    • iroha, the main command line tool for accessing the Iroha network as a user. It allows you to manage domains, accounts, and assets, and to query network status and events. To install iroha system-wide, use the following command:
    bash
    $ cargo install --git https://github.com/hyperledger/iroha.git iroha_cli
    • kagami, the tool that generates cryotpgraphic keys, configuration files and other necessary data. To install kagami system-wide, use the following command:
    bash
    $ cargo install --git https://github.com/hyperledger/iroha.git iroha_kagami
    + + + + \ No newline at end of file diff --git a/guide/get-started/javascript.html b/guide/get-started/javascript.html new file mode 100644 index 00000000..2baf8295 --- /dev/null +++ b/guide/get-started/javascript.html @@ -0,0 +1,712 @@ + + + + + + JavaScript/TypeScript Guide | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    JavaScript/TypeScript Guide

    INFO

    This guide targets @iroha2/client and @iroha/data-model version ^5.0, which targets Iroha 2 stable (2.0.0-pre-rc.13, c4af68c4f7959b154eb5380aa93c894e2e63fe4e).

    INFO

    This guide assumes you are familiar with Node.js and NPM ecosystem.

    1. Client Installation

    The Iroha 2 JavaScript library consists of multiple packages:

    PackageDescription
    clientSubmits requests to Iroha Peer
    data-modelProvides SCALE (Simple Concatenated Aggregate Little-Endian)-codecs for the Iroha 2 Data Model
    crypto-coreContains cryptography types
    crypto-target-nodeProvides compiled crypto WASM (Web Assembly) for the Node.js environment
    crypto-target-webProvides compiled crypto WASM for native Web (ESM)
    crypto-target-bundlerProvides compiled crypto WASM to use with bundlers such as Webpack

    All of these are published under the @iroha2 scope into Iroha Nexus Registry. In the future, they will be published in the main NPM Registry.

    INFO

    You can also work with the sources in Iroha Javascript repository, where the active development is happening. Clone the repository and check out the iroha2 branch:

    bash
    $ git clone https://github.com/hyperledger/iroha-javascript.git --branch iroha2

    Please note that this guide does not cover the details of this workflow.

    While we've taken great care to decouple the packages, so you could minimise their footprint, for the purposes of this tutorial, it's better to install everything.

    The installation consists of two steps: setting up a registry and then installing the packages you need.

    1. Set up a registry. In shell, run:

      bash
      $ echo "@iroha2:registry=https://nexus.iroha.tech/repository/npm-group/" > .npmrc
    2. Install Iroha 2 packages as any other NPM package. If you are following the tutorial, we recommend installing all of the following:

      bash
      $ npm i @iroha2/client
      +$ npm i @iroha2/data-model
      +$ npm i @iroha2/crypto-core
      +$ npm i @iroha2/crypto-target-node
      +$ npm i @iroha2/crypto-target-web
      +$ npm i @iroha2/crypto-target-bundler

      INFO

      Note that you can use other package managers, such as yarn or pnpm, for a faster installation. For example:

      bash
      $ yarn add @iroha2/data-model
      +$ pnpm add @iroha2/crypto-target-web

      The set of packages that you need to install depends on what you are trying to achieve. If you only need to play with the Data Model to perform (de-)serialisation, the data-model package is sufficient. If you need to check on a peer in terms of its status or health, then you only need the client library.

    3. Install the following packages as well:

      bash
      $ npm i hada
      +$ npm i tsx -g
    4. If you are planning to use the Transaction or Query API, you'll also need to inject an appropriate crypto instance into the client at runtime. This has to be adjusted according to your particular environment.

      For example, Node.js users need the following:

      ts
      import { crypto } from '@iroha2/crypto-target-node'
      +import { setCrypto } from '@iroha2/client'
      +
      +setCrypto(crypto)

      INFO

      Please refer to the documentation of the respective @iroha2/crypto-target-* package, because each case has specific configuration steps. For example, the web target needs to be initialised (via asynchronous init()) before you can use any cryptographic methods.

    NOTE

    When you are creating files in the following steps, you must place them in the same directory that contains node_modules, like so:

    ╭───┬───────────────────┬──────╮
    +│ # │       name        │ type │
    +├───┼───────────────────┼──────┤
    +│ 0 │ node_modules      │ dir  │
    +│ 1 │ addClient.ts      │ file │
    +│ 2 │ example.ts        │ file │
    +│ 3 │ package.json      │ file │
    +│ 4 │ pnpm-lock.yaml    │ file │
    +│ 5 │ registerDomain.ts │ file │
    +╰───┴───────────────────┴──────╯

    We recommend using tsx to run the scripts you've created. For example:

    bash
    $ tsx example.ts

    2. Client Configuration

    The JavaScript Client is fairly low-level in a sense that it doesn't expose any convenience features like a TransactionBuilder or a ConfigBuilder.

    INFO

    The work on implementing those is underway, and these features will very likely be available in the second round of this tutorial's release.

    Thus, on the plus side, configuration of the client is simple. On the downside, you have to prepare a lot manually.

    You may need to use transactions or queries, so before we initialize the client, let's set up this part. Let's assume that you have stringified public & private keys (more on that later). Thus, a key-pair generation could look like this:

    ts
    import { crypto } from '@iroha2/crypto-target-node'
    +
    +const keyPair = crypto.KeyPair.fromJSON({
    +  public_key: 'ed0120e555d194e8822da35ac541ce9eec8b45058f4d294d9426ef97ba92698766f7d3',
    +  private_key: {
    +    digest_function: 'ed25519',
    +    payload:
    +      'de757bcb79f4c63e8fa0795edc26f86dfdba189b846e903d0b732bb644607720e555d194e8822da35ac541ce9eec8b45058f4d294d9426ef97ba92698766f7d3',
    +  },
    +})

    When you have a key pair, you might create a Signer using the key pair:

    ts
    import { cryptoTypes } from '@iroha2/crypto-core'
    +import { Signer } from '@iroha2/client'
    +import { AccountId, DomainId } from '@iroha2/data-model'
    +
    +// Key pair from previous step
    +declare const keyPair: cryptoTypes.KeyPair
    +
    +const accountId = AccountId({
    +  // Account name
    +  name: 'alice',
    +  // The domain where this account is registered
    +  domain_id: DomainId({
    +    name: 'wonderland',
    +  }),
    +})
    +
    +const signer = new Signer(accountId, keyPair)

    Now we're able to make signatures with signer.sign(binary)! However, to interact with Iroha, we need to be able to do more than just sign. We would need to send something to Iroha, like transactions or queries. Torii will help us with that.

    Torii handles HTTP / WebSocket communications with Iroha. We will use it to communicate with Iroha endpoints. With the help of Torii we can:

    • Submit transactions with Torii.submit()
    • Send queries with Torii.request()
    • Listen for events with Torii.listenForEvents()
    • Listen for blocks stream with Torii.listenForBlocksStream()
    • and so on

    Torii is a stateless object, a compendium of methods. You can look at it as if it is a class with only static methods. Each method has its own requirements to be passed in — some of them only need an HTTP transport and Iroha Torii Telemetry URL, others — a WebSocket transport and Iroha Torii API URL. To better understand how Torii is used, look at this example:

    ts
    import { Torii } from '@iroha2/client'
    +import { VersionedSignedQueryRequest } from '@iroha2/data-model'
    +
    +// --snip--
    +declare const query: VersionedSignedQueryRequest
    +
    +const result = await Torii.request(
    +  {
    +    fetch,
    +    apiURL: 'http://127.0.0.1:8080',
    +  },
    +  query,
    +)

    In this example, we pass fetch (the HTTP transport) and apiURL as the first parameter, and the query itself as the second.

    To work with Torii, we need to know Iroha Torii URLs. Our Iroha Peer is configured to listen for API endpoints at http://127.0.0.1:8080 and for telemetry endpoints at http://127.0.0.1:8081. Then, we need to provide appropriate HTTP / WebSocket adapters which Torii will use[1]. These adapters depend on the environment in which you are going to use @iroha2/client.

    In Node.js, the full list of Torii requirements (i.e. covering all its methods) will look like this:

    ts
    import {
    +  ToriiRequirementsForApiHttp,
    +  ToriiRequirementsForApiWebSocket,
    +  ToriiRequirementsForTelemetry,
    +} from '@iroha2/client'
    +import { adapter as WS } from '@iroha2/client/web-socket/node'
    +
    +import nodeFetch from 'node-fetch'
    +// another alternative
    +import { fetch as undiciFetch } from 'undici'
    +
    +const toriiRequirements: ToriiRequirementsForApiHttp &
    +  ToriiRequirementsForApiWebSocket &
    +  ToriiRequirementsForTelemetry = {
    +  apiURL: 'http://127.0.0.1:8080',
    +  telemetryURL: 'http://127.0.0.1:8081',
    +  ws: WS,
    +  // type assertion is acceptable here
    +  // you can pass `undiciFetch` here as well
    +  fetch: nodeFetch as typeof fetch,
    +}

    TIP

    In the example above, we use node-fetch package which implements Fetch API in Node.js. However, you can use undici as well.

    INFO

    fetch: nodeFetch as typeof fetch type assertion is acceptable here for a reason. Torii expects the "classic", native fetch function, which is available natively in Browser. However, both node-fetch and undici don't provide fetch that is 100% compatible with the native one. Since Torii doesn't rely on those corner-features that are partially provided by node-fetch and undici, it's fine to ignore the TypeScript error here.

    And here is a sample of full Torii in-Browser requirements:

    ts
    import {
    +  ToriiRequirementsForApiHttp,
    +  ToriiRequirementsForApiWebSocket,
    +  ToriiRequirementsForTelemetry,
    +} from '@iroha2/client'
    +import { adapter as WS } from '@iroha2/client/web-socket/native'
    +
    +const toriiRequirements: ToriiRequirementsForApiHttp &
    +  ToriiRequirementsForApiWebSocket &
    +  ToriiRequirementsForTelemetry = {
    +  apiURL: 'http://127.0.0.1:8080',
    +  telemetryURL: 'http://127.0.0.1:8081',
    +  ws: WS,
    +  fetch:
    +    // passing globally available `fetch`, but binding it to `window`
    +    // to avoid `TypeError: "'fetch' called on an
    +    //           object that does not implement interface Window."`
    +    fetch.bind(window),
    +}

    NOTE

    We make fetch.bind(window) to avoid TypeError: "'fetch' called on an object that does not implement interface Window.".

    Great! Now we have signer and Torii requirements to work with. Finally, we can create a Client:

    ts
    import { Client, Signer, ToriiRequirementsForApiHttp } from '@iroha2/client'
    +import { Executable } from '@iroha2/data-model'
    +
    +// --snip--
    +declare const signer: Signer
    +declare const toriiRequirements: ToriiRequirementsForApiHttp
    +
    +const client = new Client({ signer })
    +
    +// `Client` will sign & wrap `Executable` into `VersionedSignedTransaction`
    +declare const exec: Executable
    +await client.submitExecutable(toriiRequirements, exec)

    Client provides useful utilities for transactions and queries. You can also use Torii to communicate with the endpoints directly. Signer is accessible with client.signer.

    3. Registering a Domain

    Here we see how similar the JavaScript code is to the Rust counterpart. It should be emphasised that the JavaScript library is a thin wrapper: It doesn't provide any special builder structures, meaning you have to work with bare-bones compiled Data Model structures and define all internal fields explicitly.

    Doubly so, since JavaScript employs many implicit conversions, we highly recommend that you employ TypeScript. This makes many errors far easier to debug, but, unfortunately, results in more boilerplates.

    Let's register a new domain named looking_glass using our current account, alice@wondeland.

    First, we need to import necessary models and a pre-configured client instance:

    ts
    import { Client, ToriiRequirementsForApiHttp } from '@iroha2/client'
    +import {
    +  DomainId,
    +  EvaluatesToRegistrableBox,
    +  Executable,
    +  Expression,
    +  IdentifiableBox,
    +  Instruction,
    +  MapNameValue,
    +  Metadata,
    +  NewDomain,
    +  OptionIpfsPath,
    +  QueryBox,
    +  RegisterBox,
    +  Value,
    +  VecInstruction,
    +} from '@iroha2/data-model'
    +
    +// --snip--
    +declare const client: Client
    +declare const toriiRequirements: ToriiRequirementsForApiHttp

    To register a new domain, we need to submit a transaction with a single instruction: to register a new domain. Let's wrap it all in an async function:

    ts
    async function registerDomain(domainName: string) {
    +  const registerBox = RegisterBox({
    +    object: EvaluatesToRegistrableBox({
    +      expression: Expression(
    +        'Raw',
    +        Value(
    +          'Identifiable',
    +          IdentifiableBox(
    +            'NewDomain',
    +            NewDomain({
    +              id: DomainId({
    +                name: domainName, 
    +              }),
    +              metadata: Metadata({ map: MapNameValue(new Map()) }),
    +              logo: OptionIpfsPath('None'),
    +            }),
    +          ),
    +        ),
    +      ),
    +    }),
    +  })
    +
    +  await client.submitExecutable(
    +    toriiRequirements,
    +    Executable('Instructions', VecInstruction([Instruction('Register', registerBox)])),
    +  )
    +}

    Which we use to register the domain like so:

    ts
    await registerDomain('looking_glass')

    We can also use Query API to ensure that the new domain is created. Let's create another function that wraps that functionality:

    ts
    async function ensureDomainExistence(domainName: string) {
    +  // Query all domains
    +  const result = await client.requestWithQueryBox(
    +    toriiRequirements,
    +    QueryBox('FindAllDomains', null),
    +  )
    +
    +  // Display the request status
    +  console.log('%o', result)
    +
    +  // Obtain the domain
    +  const domain = result
    +    .as('Ok')
    +    .result.enum.as('Vec')
    +    .map((x) => x.enum.as('Identifiable').enum.as('Domain'))
    +    .find((x) => x.id.name === domainName) 
    +
    +  // Throw an error if the domain is unavailable
    +  if (!domain) throw new Error('Not found')
    +}

    Now you can ensure that domain is created by calling:

    ts
    await ensureDomainExistence('looking_glass')

    4. Registering an Account

    Registering an account is a bit more involved than registering a domain. With a domain, the only concern is the domain name. However, with an account, there are a few more things to worry about.

    First of all, we need to create an AccountId. Note that we can only register an account to an existing domain. The best UX design practices dictate that you should check if the requested domain exists now, and if it doesn't, suggest a fix to the user. After that, we can create a new account named white_rabbit.

    Imports we need:

    ts
    import {
    +  AccountId,
    +  DomainId,
    +  EvaluatesToRegistrableBox,
    +  Expression,
    +  IdentifiableBox,
    +  Instruction,
    +  MapNameValue,
    +  Metadata,
    +  NewAccount,
    +  PublicKey,
    +  RegisterBox,
    +  Value,
    +  VecPublicKey,
    +} from '@iroha2/data-model'

    The AccountId structure:

    ts
    const accountId = AccountId({
    +  name: 'white_rabbit',
    +  domain_id: DomainId({
    +    name: 'looking_glass',
    +  }),
    +})

    Second, you should provide the account with a public key. It is tempting to generate both it and the private key at this time, but it isn't the brightest idea. Remember that the white_rabbit trusts you, alice@wonderland, to create an account for them in the domain looking_glass, but doesn't want you to have access to that account after creation.

    If you gave white_rabbit a key that you generated yourself, how would they know if you don't have a copy of their private key? Instead, the best way is to ask white_rabbit to generate a new key-pair, and give you the public half of it.

    ts
    const pubKey = PublicKey({
    +  payload: new Uint8Array([
    +    /* put bytes here */
    +  ]),
    +  digest_function: 'some_digest',
    +})

    Only then do we build an instruction from it:

    ts
    const registerAccountInstruction = Instruction(
    +  'Register',
    +  RegisterBox({
    +    object: EvaluatesToRegistrableBox({
    +      expression: Expression(
    +        'Raw',
    +        Value(
    +          'Identifiable',
    +          IdentifiableBox(
    +            'NewAccount',
    +            NewAccount({
    +              id: accountId, 
    +              signatories: VecPublicKey([pubKey]),
    +              metadata: Metadata({ map: MapNameValue(new Map()) }),
    +            }),
    +          ),
    +        ),
    +      ),
    +    }),
    +  }),
    +)

    Which is then wrapped in a transaction and submitted to the peer the same way as in the previous section when we registered a domain.

    5. Registering and minting assets

    Iroha has been built with few underlying assumptions about what the assets need to be in terms of their value type and characteristics (fungible or non-fungible, mintable or non-mintable).

    In JS, you can create a new asset with the following construction:

    ts
    import {
    +  AssetDefinition,
    +  AssetDefinitionId,
    +  AssetValueType,
    +  DomainId,
    +  EvaluatesToRegistrableBox,
    +  Expression,
    +  IdentifiableBox,
    +  Instruction,
    +  MapNameValue,
    +  Metadata,
    +  Mintable,
    +  RegisterBox,
    +  Value,
    +} from '@iroha2/data-model'
    +
    +const time = AssetDefinition({
    +  value_type: AssetValueType('Quantity'),
    +  id: AssetDefinitionId({
    +    name: 'time',
    +    domain_id: DomainId({ name: 'looking_glass' }),
    +  }),
    +  metadata: Metadata({ map: MapNameValue(new Map()) }),
    +  mintable: Mintable('Infinitely'), // If only we could mint more time.
    +})
    +
    +const register = Instruction(
    +  'Register',
    +  RegisterBox({
    +    object: EvaluatesToRegistrableBox({
    +      expression: Expression(
    +        'Raw',
    +        Value('Identifiable', IdentifiableBox('AssetDefinition', time)), 
    +      ),
    +    }),
    +  }),
    +)

    Pay attention to the fact that we have defined the asset as Mintable('Not'). What this means is that we cannot create more of time. The late bunny will always be late, because even the super-user of the blockchain cannot mint more of time than already exists in the genesis block.

    This means that no matter how hard the white_rabbit tries, the time that he has is the time that was given to him at genesis. And since we haven't defined any time in the domain looking_glass at genesis and defined time in a non-mintable fashion afterwards, the white_rabbit is doomed to always be late.

    If we had set mintable: Mintable('Infinitely') on our time asset, we could mint it:

    ts
    import {
    +  AccountId,
    +  AssetDefinitionId,
    +  AssetId,
    +  DomainId,
    +  EvaluatesToIdBox,
    +  EvaluatesToValue,
    +  Expression,
    +  IdBox,
    +  Instruction,
    +  MintBox,
    +  NumericValue,
    +  Value,
    +} from '@iroha2/data-model'
    +
    +const mint = Instruction(
    +  'Mint',
    +  MintBox({
    +    object: EvaluatesToValue({
    +      expression: Expression('Raw', Value('Numeric', NumericValue('U32', 42))),
    +    }),
    +    destination_id: EvaluatesToIdBox({
    +      expression: Expression(
    +        'Raw',
    +        Value(
    +          'Id',
    +          IdBox(
    +            'AssetId',
    +            AssetId({
    +              account_id: AccountId({
    +                name: 'alice',
    +                domain_id: DomainId({
    +                  name: 'wonderland',
    +                }),
    +              }),
    +              definition_id: AssetDefinitionId({
    +                name: 'time',
    +                domain_id: DomainId({ name: 'looking_glass' }),
    +              }),
    +            }),
    +          ),
    +        ),
    +      ),
    +    }),
    +  }),
    +)

    Again it should be emphasised that an Iroha 2 network is strongly typed. You need to take special care to make sure that only unsigned integers are passed to the Value('U32', ...) factory method. Fixed precision values also need to be taken into consideration. Any attempt to add to or subtract from a negative Fixed-precision value will result in an error.

    6. Transferring assets

    After minting the assets, you can transfer them to another account. In the example below, Alice transfers to Mouse 100 units of time asset:

    ts
    import {
    +  AccountId,
    +  AssetDefinitionId,
    +  AssetId,
    +  DomainId,
    +  EvaluatesToIdBox,
    +  EvaluatesToValue,
    +  Expression,
    +  IdBox,
    +  Instruction,
    +  NumericValue,
    +  TransferBox,
    +  Value,
    +} from '@iroha2/data-model'
    +
    +const domainId = DomainId({
    +  name: 'wonderland',
    +})
    +
    +const assetDefinitionId = AssetDefinitionId({
    +  name: 'time',
    +  domain_id: domainId,
    +})
    +
    +const amountToTransfer = Value('Numeric', NumericValue('U32', 100))
    +
    +const fromAccount = AccountId({
    +  name: 'alice',
    +  domain_id: domainId,
    +})
    +
    +const toAccount = AccountId({
    +  name: 'mouse',
    +  domain_id: domainId,
    +})
    +
    +const evaluatesToAssetId = (assetId: AssetId): EvaluatesToIdBox =>
    +  EvaluatesToIdBox({
    +    expression: Expression('Raw', Value('Id', IdBox('AssetId', assetId))),
    +  })
    +
    +const transferAssetInstruction = Instruction(
    +  'Transfer',
    +  TransferBox({
    +    source_id: evaluatesToAssetId(
    +      AssetId({
    +        definition_id: assetDefinitionId,
    +        account_id: fromAccount,
    +      }),
    +    ),
    +    destination_id: evaluatesToAssetId(
    +      AssetId({
    +        definition_id: assetDefinitionId,
    +        account_id: toAccount,
    +      }),
    +    ),
    +    object: EvaluatesToValue({
    +      expression: Expression('Raw', amountToTransfer),
    +    }),
    +  }),
    +)

    7. Querying for Domains, Accounts and Assets

    TODO

    ts
    import { Client, ToriiRequirementsForApiHttp } from '@iroha2/client'
    +import { QueryBox } from '@iroha2/data-model'
    +
    +declare const client: Client
    +declare const toriiRequirements: ToriiRequirementsForApiHttp
    ts
    const result = await client.requestWithQueryBox(
    +  toriiRequirements,
    +  QueryBox('FindAllDomains', null),
    +)
    +
    +const domains = result
    +  .as('Ok')
    +  .result.enum.as('Vec')
    +  .map((x) => x.enum.as('Identifiable').enum.as('Domain'))
    +
    +for (const domain of domains) {
    +  console.log(
    +    `Domain "${domain.id.name}" has ${domain.accounts.size} accounts` +
    +      ` and ${domain.asset_definitions.size} asset definitions`,
    +  )
    +  // => Domain "wonderland" has 5 accounts and 3 asset definitions
    +}
    ts
    const result = await client.requestWithQueryBox(
    +  toriiRequirements,
    +  QueryBox('FindAllAccounts', null),
    +)
    +
    +const accounts = result
    +  .as('Ok')
    +  .result.enum.as('Vec')
    +  .map((x) => x.enum.as('Identifiable').enum.as('Account'))
    +
    +for (const account of accounts) {
    +  console.log(
    +    `Account "${account.id.name}@${account.id.domain_id.name}" ` +
    +      `has ${account.assets.size} assets`,
    +  )
    +  // => Account "alice@wonderland" has 3 assets
    +}
    ts
    const result = await client.requestWithQueryBox(
    +  toriiRequirements,
    +  QueryBox('FindAllAssets', null),
    +)
    +
    +const assets = result
    +  .as('Ok')
    +  .result.enum.as('Vec')
    +  .map((x) => x.enum.as('Identifiable').enum.as('Asset'))
    +
    +for (const asset of assets) {
    +  console.log(
    +    `Asset "${asset.id.definition_id.name}#${asset.id.definition_id.domain_id.name}" ` +
    +      `at account "${asset.id.account_id.name}@${asset.id.account_id.domain_id.name}" ` +
    +      `has type "${asset.value.enum.tag}"`,
    +  )
    +  // => Asset "rose#wonderland" at account "alice@wonderland" has type "Quantity"
    +}

    8. Visualizing outputs in Web UI

    Finally, we should talk about visualising data. The Rust API is currently the most complete in terms of available queries and instructions. After all, this is the language in which Iroha 2 was built.

    Let's build a small Vue 3 application that uses each API we've discovered in this guide!

    TIP

    In this guide, we are roughly recreating the project that is a part of iroha-javascript integration tests. If you want to see the full project, please refer to the @iroha2/client-test-web sources.

    Our app will consist of 3 main views:

    • Status checker that periodically requests peer status (e.g. current blocks height) and shows it;
    • Domain creator, which is a form to create a new domain with specified name;
    • Listener with a toggle to setup listening for events.

    You can use this folder structure as a reference:

    ╭───┬──────────────────────────────╮
    +│ # │             name             │
    +├───┼──────────────────────────────┤
    +│ 0 │ App.vue                      │
    +│ 1 │ client.ts                    │
    +│ 2 │ components/CreateDomain.vue  │
    +│ 3 │ components/Listener.vue      │
    +│ 4 │ components/StatusChecker.vue │
    +│ 5 │ config.json                  │
    +│ 6 │ crypto.ts                    │
    +│ 7 │ main.ts                      │
    +╰───┴──────────────────────────────╯
    json
    {
    +  "torii": {
    +    "apiURL": "http://127.0.0.1:8080",
    +    "telemetryURL": "http://127.0.0.1:8081"
    +  },
    +  "account": {
    +    "name": "alice",
    +    "domain_id": {
    +      "name": "wonderland"
    +    }
    +  },
    +  "public_key": "ed01207233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0",
    +  "private_key": {
    +    "digest_function": "ed25519",
    +    "payload": "9ac47abf59b356e0bd7dcbbbb4dec080e302156a48ca907e47cb6aea1d32719e7233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0"
    +  }
    +}
    ts
    import { crypto, init } from '@iroha2/crypto-target-web'
    +
    +await init()
    +
    +export { crypto }
    ts
    import { Client, Signer } from '@iroha2/client'
    +import { adapter as WS } from '@iroha2/client/web-socket/native'
    +import { crypto } from './crypto'
    +import { client_config } from '../../config'
    +import { AccountId } from '@iroha2/data-model'
    +
    +const HOST = window.location.host
    +
    +export const toriiPre = {
    +  // proxified with vite
    +  apiURL: `http://${HOST}/torii/api`,
    +  telemetryURL: `http://${HOST}/torii/telemetry`,
    +  ws: WS,
    +  fetch: fetch.bind(window),
    +}
    +
    +const signer = new Signer(client_config.account as AccountId, crypto.KeyPair.fromJSON(client_config))
    +
    +export const client = new Client({ signer })
    vue
    <script setup lang="ts">
    +import { useIntervalFn } from '@vueuse/core'
    +import { useStaleState, useTask } from '@vue-kakuyaku/core'
    +import { toriiPre } from '../client'
    +import { Torii } from '@iroha2/client'
    +
    +const { state, run } = useTask(() => Torii.getStatus(toriiPre), { immediate: true })
    +const stale = useStaleState(state)
    +useIntervalFn(run, 1000)
    +</script>
    +
    +<template>
    +  <div>
    +    <h3>Status</h3>
    +
    +    <ul v-if="stale.fulfilled">
    +      <li>Blocks: {{ stale.fulfilled.value.blocks }}</li>
    +      <li>Uptime (sec): {{ stale.fulfilled.value.uptime.secs }}</li>
    +    </ul>
    +  </div>
    +</template>
    vue
    <script setup lang="ts">
    +import {
    +  DomainId,
    +  EvaluatesToRegistrableBox,
    +  Executable,
    +  Expression,
    +  IdentifiableBox,
    +  Instruction,
    +  MapNameValue,
    +  Metadata,
    +  NewDomain,
    +  OptionIpfsPath,
    +  RegisterBox,
    +  Value,
    +  VecInstruction,
    +} from '@iroha2/data-model'
    +import { ref } from 'vue'
    +import { client, toriiPre } from '../client'
    +import { useTask } from '@vue-kakuyaku/core'
    +
    +const domainName = ref('')
    +
    +const { state, run: registerDomain } = useTask(async () => {
    +  await client.submitExecutable(
    +    toriiPre,
    +    Executable(
    +      'Instructions',
    +      VecInstruction([
    +        Instruction(
    +          'Register',
    +          RegisterBox({
    +            object: EvaluatesToRegistrableBox({
    +              expression: Expression(
    +                'Raw',
    +                Value(
    +                  'Identifiable',
    +                  IdentifiableBox(
    +                    'NewDomain',
    +                    NewDomain({
    +                      id: DomainId({
    +                        name: domainName.value,
    +                      }),
    +                      metadata: Metadata({ map: MapNameValue(new Map()) }),
    +                      logo: OptionIpfsPath('None'),
    +                    }),
    +                  ),
    +                ),
    +              ),
    +            }),
    +          }),
    +        ),
    +      ]),
    +    ),
    +  )
    +})
    +</script>
    +
    +<template>
    +  <div>
    +    <h3>Create Domain</h3>
    +    <p>
    +      <label for="domain">New domain name:</label> <input
    +        id="domain"
    +        v-model="domainName"
    +      >
    +    </p>
    +    <p>
    +      <button @click="registerDomain()">
    +        Register domain{{ state.pending ? '...' : '' }}
    +      </button>
    +    </p>
    +  </div>
    +</template>
    vue
    <script setup lang="ts">
    +import { SetupEventsReturn, Torii } from '@iroha2/client'
    +import {
    +  FilterBox,
    +  OptionHash,
    +  OptionPipelineEntityKind,
    +  OptionPipelineStatusKind,
    +  PipelineEntityKind,
    +  PipelineEventFilter,
    +  PipelineStatus,
    +  PipelineStatusKind,
    +} from '@iroha2/data-model'
    +import { computed, onBeforeUnmount, shallowReactive, shallowRef } from 'vue'
    +import { toriiPre } from '../client'
    +
    +function bytesToHex(bytes: number[]): string {
    +  return bytes.map((byte) => byte.toString(16).padStart(2, '0')).join('')
    +}
    +
    +interface EventData {
    +  hash: string
    +  status: string
    +}
    +
    +const events = shallowReactive<EventData[]>([])
    +
    +const currentListener = shallowRef<null | SetupEventsReturn>(null)
    +
    +const isListening = computed(() => !!currentListener.value)
    +
    +function displayStatus(status: PipelineStatus): string {
    +  switch (status.enum.tag) {
    +    case 'Validating':
    +      return 'validating'
    +    case 'Committed':
    +      return 'committed'
    +    case 'Rejected':
    +      return 'rejected with some reason'
    +  }
    +}
    +
    +async function startListening() {
    +  currentListener.value = await Torii.listenForEvents(toriiPre, {
    +    filter: FilterBox(
    +      'Pipeline',
    +      PipelineEventFilter({
    +        entity_kind: OptionPipelineEntityKind('Some', PipelineEntityKind('Transaction')),
    +        status_kind: OptionPipelineStatusKind('Some', PipelineStatusKind('Committed')),
    +        hash: OptionHash('None'),
    +      }),
    +    ),
    +  })
    +
    +  currentListener.value.ee.on('event', (event) => {
    +    const { hash, status } = event.enum.as('Pipeline')
    +    events.push({
    +      hash: bytesToHex([...hash]),
    +      status: displayStatus(status),
    +    })
    +  })
    +}
    +
    +async function stopListening() {
    +  await currentListener.value?.stop()
    +  currentListener.value = null
    +}
    +
    +onBeforeUnmount(stopListening)
    +</script>
    +
    +<template>
    +  <div>
    +    <h3>Listening</h3>
    +
    +    <p>
    +      <button @click="isListening ? stopListening() : startListening()">
    +        {{ isListening ? 'Stop' : 'Listen' }}
    +      </button>
    +    </p>
    +
    +    <p>Events:</p>
    +
    +    <ul class="events-list">
    +      <li
    +        v-for="{ hash, status } in events"
    +        :key="hash"
    +      >
    +        Transaction <code>{{ hash }}</code> status:
    +        {{ status }}
    +      </li>
    +    </ul>
    +  </div>
    +</template>
    vue
    <script setup lang="ts">
    +import CreateDomain from './components/CreateDomain.vue'
    +import EventListener from './components/EventListener.vue'
    +import StatusChecker from './components/StatusChecker.vue'
    +</script>
    +
    +<template>
    +  <StatusChecker />
    +  <hr>
    +  <CreateDomain />
    +  <hr>
    +  <EventListener />
    +</template>
    +
    +<style lang="scss">
    +#app {
    +  padding: 16px;
    +  font-family: sans-serif;
    +}
    +</style>
    ts
    import { createApp } from 'vue'
    +import App from './App.vue'
    +import { Logger } from '@iroha2/data-model'
    +import { crypto } from './crypto'
    +import { setCrypto } from '@iroha2/client'
    +
    +setCrypto(crypto)
    +new Logger().mount()
    +localStorage.debug = '*'
    +
    +createApp(App).mount('#app')

    INFO

    In client.ts, we import the configuration file like this:

    ts
    import { client_config } from '../../config'

    Note that you need to import the config in this way because this is how the source code of this application works. You can interpret this line as import client_config from 'config.json'.

    Demo

    Here is a small demo with the usage of this component:

    Demo of the sample Vue application

    9. Subscribing to Block Stream

    You can use /block/stream endpoint to send a subscription request for block streaming.

    Via this endpoint, the client first provides the starting block number (i.e. height) in the subscription request. After sending the confirmation message, the server starts streaming all the blocks from the given block number up to the current block, and continues to stream blocks as they are added to the blockchain.

    Here is an example of how to listen to the block stream:

    ts
    import { Torii, ToriiRequirementsForApiWebSocket } from '@iroha2/client'
    +
    +declare const requirements: ToriiRequirementsForApiWebSocket
    +
    +const stream = await Torii.listenForBlocksStream(requirements, {
    +  height: 0n,
    +})
    +
    +stream.ee.on('block', (block) => {
    +  const height = block.enum.as('V1').header.height
    +  console.log('Got block with height', height)
    +})

    1. We have to pass environment-specific ws and fetch, because there is no way for Iroha Client to communicate with a peer in an environment-agnostic way. ↩︎

    + + + + \ No newline at end of file diff --git a/guide/get-started/kotlin-java.html b/guide/get-started/kotlin-java.html new file mode 100644 index 00000000..ae759f39 --- /dev/null +++ b/guide/get-started/kotlin-java.html @@ -0,0 +1,515 @@ + + + + + + Kotlin/Java Guide | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Kotlin/Java Guide

    1. Iroha 2 Client Setup

    In this part we shall cover the main things to look out for if you want to use Iroha 2 in your Kotlin application. Instead of providing the complete basics, we shall assume knowledge of the most widely used concepts, explain the unusual, and provide some instructions for creating your own Iroha 2-compatible client.

    We assume that you know how to create a new package and have basic understanding of the fundamental Kotlin code. Specifically, we shall assume that you know how to build and deploy your program on the target platforms. To clone Iroha 2 JVM compatible SDKs, you can use Iroha Java.

    Without further ado, here's a part of an example build.gradle.kts file, specifically, the plugins, repositories and dependencies sections:

    kotlin
    plugins {
    +    kotlin("jvm") version "1.6.10"
    +    application
    +}
    +
    +group = "jp.co.soramitsu"
    +version = "1.0-SNAPSHOT"
    +
    +repositories {
    +    mavenCentral()
    +    maven(url = "https://jitpack.io")
    +}
    +
    +dependencies {
    +    val iroha2Ver by System.getProperties()
    +
    +    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0")
    +    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.0")
    +
    +    api("com.github.hyperledger.iroha-java:admin-client:SNAPSHOT")
    +    implementation("com.github.hyperledger.iroha-java:model:SNAPSHOT")
    +    implementation("com.github.hyperledger.iroha-java:block:SNAPSHOT")
    +
    +    implementation("net.i2p.crypto:eddsa:0.3.0")
    +    implementation("org.bouncycastle:bcprov-jdk15on:1.65")
    +    implementation("com.github.multiformats:java-multihash:1.3.0")
    +}

    You should replace the SNAPSHOT in the above configuration with the latest iroha-java snapshot.

    Snapshot versions match the Git commits. To get the latest snapshot, simply visit the iroha-java repository on the iroha-2-dev branch and copy the short hash of the last commit on the main page.

    You can also check the commit history and copy the commit hash of a previous commit.

    This will give you the latest development release of Iroha 2.

    2. Configuring Iroha 2

    At present, the Kotlin SDK doesn't have any classes to interact with the configuration. Instead, you are provided with a ready-made Iroha2Client that reads the configuration from the environment variables and/or the resident config.json in the working directory.

    If you are so inclined, you can have a look at the testcontainers module, and see how the Iroha2Config is implemented.

    kotlin
    package jp.co.soramitsu.iroha2.testengine
    +
    +import jp.co.soramitsu.iroha2.DEFAULT_API_PORT
    +import jp.co.soramitsu.iroha2.DEFAULT_P2P_PORT
    +import jp.co.soramitsu.iroha2.DEFAULT_TELEMETRY_PORT
    +import jp.co.soramitsu.iroha2.Genesis
    +import jp.co.soramitsu.iroha2.generateKeyPair
    +import jp.co.soramitsu.iroha2.generated.datamodel.peer.PeerId
    +import jp.co.soramitsu.iroha2.toIrohaPublicKey
    +import org.slf4j.LoggerFactory.getLogger
    +import org.testcontainers.containers.Network
    +import org.testcontainers.containers.Network.newNetwork
    +import org.testcontainers.containers.output.OutputFrame
    +import org.testcontainers.containers.output.Slf4jLogConsumer
    +import org.testcontainers.images.ImagePullPolicy
    +import org.testcontainers.images.PullPolicy
    +import java.security.KeyPair
    +import java.time.Duration
    +import java.util.function.Consumer
    +
    +/**
    + * Iroha configuration
    + */
    +class IrohaConfig(
    +    var networkToJoin: Network = newNetwork(),
    +    var logConsumer: Consumer<OutputFrame> = Slf4jLogConsumer(getLogger(IrohaContainer::class.java)),
    +    var genesis: Genesis = Genesis.getEmpty(),
    +    var imageTag: String = IrohaContainer.DEFAULT_IMAGE_TAG,
    +    var imageName: String = IrohaContainer.DEFAULT_IMAGE_NAME,
    +    var pullPolicy: ImagePullPolicy = PullPolicy.ageBased(Duration.ofMinutes(10)),
    +    var alias: String = IrohaContainer.NETWORK_ALIAS + DEFAULT_P2P_PORT,
    +    var keyPair: KeyPair = generateKeyPair(),
    +    var trustedPeers: List<PeerId> = listOf(
    +        PeerId(
    +            "$alias:$DEFAULT_P2P_PORT",
    +            keyPair.public.toIrohaPublicKey()
    +        )
    +    ),
    +    var ports: List<Int> = listOf(DEFAULT_P2P_PORT, DEFAULT_API_PORT, DEFAULT_TELEMETRY_PORT),
    +    var shouldCloseNetwork: Boolean = true,
    +    var waitStrategy: Boolean = true,
    +    var submitGenesis: Boolean = true
    +) {
    +    companion object {
    +        const val P2P_PORT_IDX = 0
    +        const val API_PORT_IDX = 1
    +        const val TELEMETRY_PORT_IDX = 2
    +    }
    +}

    3. Querying and Registering Domains

    Querying and Registering a domain are easier operations. The usual boilerplate code, that often only serves to instantiate a client from an on-disk configuration file, is unnecessary. We will immediately add all the necessary imports to implement this client:

    kotlin
    import jp.co.soramitsu.iroha2.*
    +import jp.co.soramitsu.iroha2.generated.crypto.PublicKey
    +import jp.co.soramitsu.iroha2.generated.datamodel.Value
    +import jp.co.soramitsu.iroha2.generated.datamodel.account.AccountId
    +import jp.co.soramitsu.iroha2.generated.datamodel.asset.AssetValue
    +import jp.co.soramitsu.iroha2.generated.datamodel.asset.AssetValueType
    +import jp.co.soramitsu.iroha2.generated.datamodel.asset.Mintable
    +import jp.co.soramitsu.iroha2.generated.datamodel.metadata.Metadata
    +import jp.co.soramitsu.iroha2.generated.datamodel.name.Name
    +import jp.co.soramitsu.iroha2.generated.datamodel.predicate.GenericValuePredicateBox
    +import jp.co.soramitsu.iroha2.generated.datamodel.predicate.value.ValuePredicate
    +import jp.co.soramitsu.iroha2.query.QueryBuilder
    +import kotlinx.coroutines.runBlocking
    +import kotlinx.coroutines.withTimeout
    +import java.net.URL
    +import java.security.KeyPair

    We shall write this example in the form of a test class, hence the presence of test-related packages. Note the presence of coroutines.runBlocking. Iroha makes extensive use of asynchronous programming (in Rust terminology), hence blocking is not necessarily the only mode of interaction with the Iroha 2 code.

    In order to make sure that the raised peers work correctly, you can do a simple operation to get all registered domains.

    Next, we will add wrappers to the classes created in this section.

    kotlin
    fun main(args: Array<String>): Unit = runBlocking{
    +    val peerUrl = "http://127.0.0.1:8080"
    +    val telemetryUrl = "http://127.0.0.1:8180"
    +    val admin = AccountId("bob".asName(), "wonderland".asDomainId())
    +    val adminKeyPair = keyPairFromHex("7233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0",
    +        "9ac47abf59b356e0bd7dcbbbb4dec080e302156a48ca907e47cb6aea1d32719e")
    +
    +    val client = AdminIroha2Client(URL(peerUrl), URL(telemetryUrl), log = true)
    +    val query = Query(client, admin, adminKeyPair)
    +
    +    query.findAllDomains()
    +        .also { println("ALL DOMAINS: ${it.map { d -> d.id.asString() }}") }
    +
    +}
    +
    +open class Query (private val client: AdminIroha2Client,
    +                  private val admin: AccountId,
    +                  private val keyPair: KeyPair) {
    +    
    +    suspend fun findAllDomains(queryFilter: GenericValuePredicateBox<ValuePredicate>? = null) = QueryBuilder
    +        .findAllDomains(queryFilter)
    +        .account(admin)
    +        .buildSigned(keyPair)
    +        .let { client.sendQuery(it) }
    +}

    The output in the terminal will contain a list of all domains that are currently registered.

    Expand to see the expected output
    ALL DOMAINS: [wonderland, genesis, garden_of_live_flowers]

    To register a new domain, add the following lines to Main.kt:

    kotlin
    val sendTransaction = SendTransaction(client, admin, adminKeyPair)
    +
    +val domain = "looking_glass_${System.currentTimeMillis()}"
    +    sendTransaction.registerDomain(domain).also { println("DOMAIN $domain CREATED") }

    Then create new open class SendTransaction in your project:

    kotlin
    open class SendTransaction (private val client: AdminIroha2Client,
    +                            private val admin: AccountId,
    +                            private val keyPair: KeyPair,
    +                            private val timeout: Long = 10000) {
    +
    +    suspend fun registerDomain(
    +        id: String,
    +        metadata: Map<Name, Value> = mapOf(),
    +        admin: AccountId = this.admin,
    +        keyPair: KeyPair = this.keyPair
    +    ) {
    +        client.sendTransaction {
    +            account(admin)
    +            this.registerDomain(id.asDomainId(), metadata)
    +            buildSigned(keyPair)
    +        }.also {
    +            withTimeout(timeout) { it.await() }
    +        }
    +    }
    +}
    Expand to see the expected output
    DOMAIN looking_glass CREATED
    +ALL DOMAINS: [looking_glass, garden_of_live_flowers, genesis, wonderland]

    4. Registering an Account

    Registering an account is more involved than the aforementioned functions. Previously, we only had to worry about submitting a single instruction, with a single string-based registration box (in Rust terminology, the heap-allocated reference types are all called boxes).

    When registering an account, there are a few more variables. The account can only be registered to an existing domain. Also, an account typically has to have a key pair.

    To register a new account, add the following lines to Main.kt:

    Kotlin
        val madHatter = "madHatter_${System.currentTimeMillis()}$ACCOUNT_ID_DELIMITER$domain"
    +    val madHatterKeyPair = generateKeyPair()
    +    sendTransaction.registerAccount(madHatter, listOf(madHatterKeyPair.public.toIrohaPublicKey()))
    +        .also { println("ACCOUNT $madHatter CREATED") }
    +
    +    query.findAllAccounts()
    +        .also { println("ALL ACCOUNTS: ${it.map { a -> a.id.asString() }}") }

    Then implement new method for class SendTransaction in your project.

    Kotlin
        suspend fun registerAccount(
    +        id: String,
    +        signatories: List<PublicKey>,
    +        metadata: Map<Name, Value> = mapOf(),
    +        admin: AccountId = this.admin,
    +        keyPair: KeyPair = this.keyPair
    +    ) {
    +        client.sendTransaction {
    +            account(admin)
    +            this.registerAccount(id.asAccountId(), signatories, Metadata(metadata))
    +            buildSigned(keyPair)
    +        }.also {
    +            withTimeout(timeout) { it.await() }
    +        }
    +    }

    Also, a new method has been added to the Query class.

    Kotlin
        suspend fun findAllAccounts(queryFilter: GenericValuePredicateBox<ValuePredicate>? = null) = QueryBuilder
    +        .findAllAccounts(queryFilter)
    +        .account(admin)
    +        .buildSigned(keyPair)
    +        .let {
    +            client.sendQuery(it)
    +    }
    Expand to see the expected output
    DOMAIN looking_glass_1684835731653 CREATED
    +ALL DOMAINS: [looking_glass, garden_of_live_flowers, genesis, wonderland, looking_glass_1684835731653]
    +ACCOUNT madHatter_1684835733686@looking_glass_1684835731653 CREATED
    +ALL ACCOUNTS: [carpenter@garden_of_live_flowers, genesis@genesis, alice@wonderland, bob@wonderland, madHatter_1684835733686@looking_glass_1684835731653]

    As you can see, for illustrative purposes, we have generated a new key-pair. We converted that key-pair into an Iroha-compatible format using toIrohaPublicKey, and added the public key to the instruction to register an account.

    5. Registering and minting assets

    Iroha has been built with few underlying assumptions about what the assets need to be in terms of their value type and characteristics (fungible or non-fungible, mintable or non-mintable).

    INFO

    The non-mintable assets are a relatively recent addition to Iroha 2, thus registering and minting such assets is not presently possible through the Kotlin SDK.

    To register new assets definition, add the following lines of code to main

    Kotlin
        val assetDefinition = "asset_time_${System.currentTimeMillis()}$ASSET_ID_DELIMITER$domain"
    +    sendTransaction.registerAssetDefinition(assetDefinition, AssetValueType.Quantity())
    +        .also { println("ASSET DEFINITION $assetDefinition CREATED") }

    Then implement new method for class SendTransaction in your project.

    Kotlin
        suspend fun registerAssetDefinition(
    +        id: String,
    +        type: AssetValueType = AssetValueType.Store(),
    +        metadata: Map<Name, Value> = mapOf(),
    +        mintable: Mintable = Mintable.Infinitely(),
    +        admin: AccountId = this.admin,
    +        keyPair: KeyPair = this.keyPair
    +    ) {
    +        client.sendTransaction {
    +            account(admin)
    +            this.registerAssetDefinition(id.asAssetDefinitionId(), type, Metadata(metadata), mintable)
    +            buildSigned(keyPair)
    +        }.also {
    +            withTimeout(timeout) { it.await() }
    +        }
    +    }

    To mint new assets, add the following lines of code to main

    Kotlin
        val madHatterAsset = "$assetDefinition$ASSET_ID_DELIMITER$madHatter"
    +    sendTransaction.registerAsset(madHatterAsset, AssetValue.Quantity(100))
    +        .also { println("ASSET $madHatterAsset CREATED") }

    Then implement new method for class SendTransaction in your project.

    Kotlin
        suspend fun registerAsset(
    +        id: String,
    +        value: AssetValue,
    +        admin: AccountId = this.admin,
    +        keyPair: KeyPair = this.keyPair
    +        ) {
    +        client.sendTransaction {
    +            account(admin)
    +            this.registerAsset(id.asAssetId(), value)
    +            buildSigned(keyPair)
    +        }.also {
    +            withTimeout(timeout) { it.await() }
    +            }
    +        }

    To check the result, add the following line of code to the class main

    Kotlin
        query.findAllAssets()
    +        .also { println("ALL ASSETS: ${it.map { a -> a.id.asString() }}") }

    Also, a new method has been added to the open class Query

    Kotlin
        suspend fun findAllAssets(queryFilter: GenericValuePredicateBox<ValuePredicate>? = null) = QueryBuilder
    +        .findAllAssets(queryFilter)
    +        .account(admin)
    +        .buildSigned(keyPair)
    +        .let { client.sendQuery(it) }
    Expand to see the expected output
    DOMAIN looking_glass_1684842996549 CREATED
    +ALL DOMAINS: [looking_glass, garden_of_live_flowers, genesis, looking_glass_1684842996549, wonderland, looking_glass_1684835731653]
    +ACCOUNT madHatter_1684842997930@looking_glass_1684842996549 CREATED
    +ALL ACCOUNTS: [carpenter@garden_of_live_flowers, genesis@genesis, madHatter_1684842997930@looking_glass_1684842996549, alice@wonderland, bob@wonderland, madHatter_1684835733686@looking_glass_1684835731653]
    +ASSET DEFINITION asset_time_1684842998891#looking_glass_1684842996549 CREATED
    +ASSET asset_time_1684842998891#looking_glass_1684842996549#madHatter_1684842997930@looking_glass_1684842996549 CREATED
    +ALL ASSETS: [asset_time_1684842998891#looking_glass_1684842996549#madHatter_1684842997930@looking_glass_1684842996549, cabbage#garden_of_live_flowers#alice@wonderland, rose#wonderland#alice@wonderland]```

    6. Transferring assets

    After we have registered and minted madHatter's assets, let's transfer some of them to another blockchain user. To do this, we will create a new user, register their asset with the main method and add transfer operations for the asset.

    Kotlin
        val whiteRabbit = "whiteRabbit_${System.currentTimeMillis()}$ACCOUNT_ID_DELIMITER$domain"
    +    val whiteRabbitKeyPair = generateKeyPair()
    +    sendTransaction.registerAccount(whiteRabbit, listOf(whiteRabbitKeyPair.public.toIrohaPublicKey()))
    +        .also { println("ACCOUNT $whiteRabbit CREATED") }
    +    
    +    val whiteRabbitAsset = "$assetDefinition$ASSET_ID_DELIMITER$whiteRabbit"
    +    sendTransaction.registerAsset(whiteRabbitAsset, AssetValue.Quantity(0))
    +        .also { println("ASSET $whiteRabbitAsset CREATED") }
    +    
    +    sendTransaction.transferAsset(madHatterAsset, 10, whiteRabbitAsset, madHatter.asAccountId(), madHatterKeyPair)
    +        .also { println("$madHatter TRANSFERRED FROM $madHatterAsset TO $whiteRabbitAsset: 10") }
    +    query.getAccountAmount(madHatter, madHatterAsset).also { println("$madHatterAsset BALANCE: $it") }
    +    query.getAccountAmount(whiteRabbit, whiteRabbitAsset).also { println("$whiteRabbitAsset BALANCE: $it") }

    In the sendTransaction class, add a method for transferring assets.

    Kotlin
        suspend fun transferAsset(
    +        from: String,
    +        value: Int,
    +        to: String,
    +        admin: AccountId = this.admin,
    +        keyPair: KeyPair = this.keyPair
    +    ) {
    +        client.sendTransaction {
    +            account(admin)
    +            this.transferAsset(from.asAssetId(), value, to.asAssetId())
    +            buildSigned(keyPair)
    +        }.also {
    +            withTimeout(timeout) { it.await() }
    +        }
    +    }

    To check the result of the asset transfer, add the getAccountAmount() method to the Query class:

    Kotlin
        suspend fun getAccountAmount(accountId: String, assetId: String): Long {
    +        return QueryBuilder.findAccountById(accountId.asAccountId())
    +            .account(admin)
    +            .buildSigned(keyPair)
    +            .let { query ->
    +                client.sendQuery(query).assets[assetId.asAssetId()]?.value
    +            }.let { value ->
    +                value?.cast<AssetValue.Quantity>()?.u32
    +            } ?: throw RuntimeException("NOT FOUND")
    +    }

    The console output should contain similar information.

    Expand to see the expected output
    DOMAIN looking_glass_1684843200289 CREATED
    +ALL DOMAINS: [looking_glass, garden_of_live_flowers, genesis, looking_glass_1684843200289, looking_glass_1684842996549, wonderland, looking_glass_1684835731653]
    +ACCOUNT madHatter_1684843202389@looking_glass_1684843200289 CREATED
    +ALL ACCOUNTS: [carpenter@garden_of_live_flowers, genesis@genesis, madHatter_1684843202389@looking_glass_1684843200289, madHatter_1684842997930@looking_glass_1684842996549, alice@wonderland, bob@wonderland, madHatter_1684835733686@looking_glass_1684835731653]
    +ASSET DEFINITION asset_time_1684843203337#looking_glass_1684843200289 CREATED
    +ASSET asset_time_1684843203337#looking_glass_1684843200289#madHatter_1684843202389@looking_glass_1684843200289 CREATED
    +ACCOUNT whiteRabbit_1684843205383@looking_glass_1684843200289 CREATED
    +ASSET asset_time_1684843203337#looking_glass_1684843200289#whiteRabbit_1684843205383@looking_glass_1684843200289 CREATED
    +madHatter_1684843202389@looking_glass_1684843200289 TRANSFERRED FROM asset_time_1684843203337#looking_glass_1684843200289#madHatter_1684843202389@looking_glass_1684843200289 TO asset_time_1684843203337#looking_glass_1684843200289#whiteRabbit_1684843205383@looking_glass_1684843200289: 10
    +asset_time_1684843203337#looking_glass_1684843200289#madHatter_1684843202389@looking_glass_1684843200289 BALANCE: 90
    +asset_time_1684843203337#looking_glass_1684843200289#whiteRabbit_1684843205383@looking_glass_1684843200289 BALANCE: 10
    +ALL ASSETS: [asset_time_1684843203337#looking_glass_1684843200289#madHatter_1684843202389@looking_glass_1684843200289, cabbage#garden_of_live_flowers#alice@wonderland, rose#wonderland#alice@wonderland]

    7. Burning assets

    Burning assets is quite similar to minting them. To get started, let's add the following lines to the main() method:

    Kotlin
        sendTransaction.burnAssets(madHatterAsset, 10, madHatter.asAccountId(), madHatterKeyPair)
    +        .also { println("${madHatterAsset} WAS BURN") }
    +
    +    query.getAccountAmount(madHatter, madHatterAsset)
    +        .also { println("$madHatterAsset BALANCE: $it AFTER ASSETS BURNING") }

    Then implement a wrapper over the burnAssets() method in the sendTransaction class:

    Kotlin
        suspend fun burnAssets(
    +        assetId: String,
    +        value: Int,
    +        admin: AccountId = this.admin,
    +        keyPair: KeyPair = this.keyPair
    +    ) {
    +        client.sendTransaction {
    +            account(admin)
    +            this.burnAsset(assetId.asAssetId(), value)
    +            buildSigned(keyPair)
    +        }.also {
    +            withTimeout(timeout) { it.await() }
    +        }
    +    }
    Expand to see the expected output
    DOMAIN looking_glass_1684843511587 CREATED
    +ALL DOMAINS: [looking_glass, garden_of_live_flowers, looking_glass_1684843344208, genesis, looking_glass_1684843200289, looking_glass_1684842996549, wonderland, looking_glass_1684843511587, looking_glass_1684843451130, looking_glass_1684835731653]
    +ACCOUNT madHatter_1684843513272@looking_glass_1684843511587 CREATED
    +ALL ACCOUNTS: [carpenter@garden_of_live_flowers, madHatter_1684843345604@looking_glass_1684843344208, whiteRabbit_1684843348692@looking_glass_1684843344208, genesis@genesis, madHatter_1684835733686@looking_glass_1684835731653]
    +ASSET DEFINITION asset_time_1684843514251#looking_glass_1684843511587 CREATED
    +ASSET asset_time_1684843514251#looking_glass_1684843511587#madHatter_1684843513272@looking_glass_1684843511587 CREATED
    +ACCOUNT whiteRabbit_1684843516303@looking_glass_1684843511587 CREATED
    +ASSET asset_time_1684843514251#looking_glass_1684843511587#whiteRabbit_1684843516303@looking_glass_1684843511587 CREATED
    +madHatter_1684843513272@looking_glass_1684843511587 TRANSFERRED FROM asset_time_1684843514251#looking_glass_1684843511587#madHatter_1684843513272@looking_glass_1684843511587 TO asset_time_1684843514251#looking_glass_1684843511587#whiteRabbit_1684843516303@looking_glass_1684843511587: 10
    +asset_time_1684843514251#looking_glass_1684843511587#madHatter_1684843513272@looking_glass_1684843511587 BALANCE: 90
    +asset_time_1684843514251#looking_glass_1684843511587#whiteRabbit_1684843516303@looking_glass_1684843511587 BALANCE: 10
    +asset_time_1684843514251#looking_glass_1684843511587#madHatter_1684843513272@looking_glass_1684843511587 WAS BURN
    +asset_time_1684843514251#looking_glass_1684843511587#madHatter_1684843513272@looking_glass_1684843511587 BALANCE: 80 AFTER ASSETS BURNING
    +ALL ASSETS: [asset_time_1684843514251#looking_glass_1684843511587#whiteRabbit_1684843516303@looking_glass_1684843511587, asset_time_1684843454049#looking_glass_1684843451130#madHatter_1684843453085@looking_glass_1684843451130, asset_time_1684843454049#looking_glass_1684843451130#whiteRabbit_1684843456091@looking_glass_1684843451130]

    8. Visualizing outputs

    Finally, we should talk about visualising data. The Rust API is currently the most complete in terms of available queries and instructions. After all, this is the language in which Iroha 2 was built. Kotlin, by contrast, supports only some features.

    There are two possible event filters: PipelineEventFilter and DataEventFilter, we shall focus on the former. This filter sieves events pertaining to the process of submitting a transaction, executing a transaction and committing it to a block.

    kotlin
    import jp.co.soramitsu.iroha2.generated.datamodel.events.EventFilter.Pipeline
    +import jp.co.soramitsu.iroha2.generated.datamodel.events.pipeline.EventFilter
    +import jp.co.soramitsu.iroha2.generated.datamodel.events.pipeline.EntityType.Transaction
    +import jp.co.soramitsu.iroha2.generated.crypto.hash.Hash
    +
    +val hash: ByteArray
    +val eventFilter = Pipeline(EventFilter(Transaction(), Hash(hash)))

    What this short code snippet does is the following: It creates an event pipeline filter that checks if a transaction with the specified hash was submitted/rejected. This can then be used to see if the transaction we submitted was processed correctly and provide feedback to the end-user.

    9. Samples in pure Java

    java
    package jp.co.soramitsu.iroha2;
    +
    +import jp.co.soramitsu.iroha2.client.Iroha2AsyncClient;
    +import jp.co.soramitsu.iroha2.generated.datamodel.Value;
    +import jp.co.soramitsu.iroha2.generated.datamodel.account.Account;
    +import jp.co.soramitsu.iroha2.generated.datamodel.account.AccountId;
    +import jp.co.soramitsu.iroha2.generated.datamodel.asset.AssetId;
    +import jp.co.soramitsu.iroha2.generated.datamodel.asset.AssetValue;
    +import jp.co.soramitsu.iroha2.generated.datamodel.asset.AssetValueType;
    +import jp.co.soramitsu.iroha2.generated.datamodel.domain.Domain;
    +import jp.co.soramitsu.iroha2.generated.datamodel.domain.DomainId;
    +import jp.co.soramitsu.iroha2.generated.datamodel.metadata.Metadata;
    +import jp.co.soramitsu.iroha2.generated.datamodel.name.Name;
    +import jp.co.soramitsu.iroha2.generated.datamodel.transaction.VersionedSignedTransaction;
    +import jp.co.soramitsu.iroha2.query.QueryAndExtractor;
    +import jp.co.soramitsu.iroha2.query.QueryBuilder;
    +import jp.co.soramitsu.iroha2.testengine.DefaultGenesis;
    +import jp.co.soramitsu.iroha2.testengine.IrohaTest;
    +import jp.co.soramitsu.iroha2.testengine.WithIroha;
    +import jp.co.soramitsu.iroha2.transaction.TransactionBuilder;
    +import org.junit.jupiter.api.Assertions;
    +import org.junit.jupiter.api.Test;
    +
    +import java.util.ArrayList;
    +import java.util.HashMap;
    +import java.util.concurrent.CompletableFuture;
    +import java.util.concurrent.ExecutionException;
    +import java.util.concurrent.TimeUnit;
    +import java.util.concurrent.TimeoutException;
    +
    +import static jp.co.soramitsu.iroha2.testengine.TestConstsKt.*;
    +
    +public class JavaTest extends IrohaTest<Iroha2AsyncClient> {
    +
    +    @Test
    +    @WithIroha(sources = DefaultGenesis.class)
    +    public void instructionFailed() {
    +        final VersionedSignedTransaction transaction = TransactionBuilder.Companion
    +            .builder()
    +            .account(ALICE_ACCOUNT_ID)
    +            .fail("FAIL MESSAGE")
    +            .buildSigned(ALICE_KEYPAIR);
    +        final CompletableFuture<byte[]> future = client.sendTransactionAsync(transaction);
    +        Assertions.assertThrows(ExecutionException.class,
    +            () -> future.get(getTxTimeout().getSeconds(), TimeUnit.SECONDS)
    +        );
    +    }
    +
    +    @Test
    +    @WithIroha(sources = DefaultGenesis.class)
    +    public void registerDomainInstructionCommitted() throws ExecutionException, InterruptedException, TimeoutException {
    +        final DomainId domainId = new DomainId(new Name("new_domain_name"));
    +        final VersionedSignedTransaction transaction = TransactionBuilder.Companion
    +            .builder()
    +            .account(ALICE_ACCOUNT_ID)
    +            .registerDomain(domainId)
    +            .buildSigned(ALICE_KEYPAIR);
    +        client.sendTransactionAsync(transaction).get(getTxTimeout().getSeconds(), TimeUnit.SECONDS);
    +
    +        final QueryAndExtractor<Domain> query = QueryBuilder
    +            .findDomainById(domainId)
    +            .account(ALICE_ACCOUNT_ID)
    +            .buildSigned(ALICE_KEYPAIR);
    +        final CompletableFuture<Domain> future = client.sendQueryAsync(query);
    +        final Domain domain = future.get(getTxTimeout().getSeconds(), TimeUnit.SECONDS);
    +        Assertions.assertEquals(domain.getId(), domainId);
    +    }
    +
    +    @Test
    +    @WithIroha(sources = DefaultGenesis.class)
    +    public void registerAccountInstructionCommitted() throws Exception {
    +        final AccountId accountId = new AccountId(
    +            new Name("new_account"),
    +            DEFAULT_DOMAIN_ID
    +        );
    +        final VersionedSignedTransaction transaction = TransactionBuilder.Companion
    +            .builder()
    +            .account(ALICE_ACCOUNT_ID)
    +            .registerAccount(accountId, new ArrayList<>())
    +            .buildSigned(ALICE_KEYPAIR);
    +        client.sendTransactionAsync(transaction).get(getTxTimeout().getSeconds(), TimeUnit.SECONDS);
    +
    +        final QueryAndExtractor<Account> query = QueryBuilder
    +            .findAccountById(accountId)
    +            .account(ALICE_ACCOUNT_ID)
    +            .buildSigned(ALICE_KEYPAIR);
    +        final CompletableFuture<Account> future = client.sendQueryAsync(query);
    +        final Account account = future.get(getTxTimeout().getSeconds(), TimeUnit.SECONDS);
    +        Assertions.assertEquals(account.getId(), accountId);
    +    }
    +
    +    @Test
    +    @WithIroha(sources = DefaultGenesis.class)
    +    public void mintAssetInstructionCommitted() throws Exception {
    +        final VersionedSignedTransaction registerAssetTx = TransactionBuilder.Companion
    +            .builder()
    +            .account(ALICE_ACCOUNT_ID)
    +            .registerAssetDefinition(DEFAULT_ASSET_DEFINITION_ID, new AssetValueType.Quantity())
    +            .buildSigned(ALICE_KEYPAIR);
    +        client.sendTransactionAsync(registerAssetTx).get(getTxTimeout().getSeconds(), TimeUnit.SECONDS);
    +
    +        final VersionedSignedTransaction mintAssetTx = TransactionBuilder.Companion
    +            .builder()
    +            .account(ALICE_ACCOUNT_ID)
    +            .mintAsset(DEFAULT_ASSET_ID, 5)
    +            .buildSigned(ALICE_KEYPAIR);
    +        client.sendTransactionAsync(mintAssetTx).get(getTxTimeout().getSeconds(), TimeUnit.SECONDS);
    +
    +        final QueryAndExtractor<Account> query = QueryBuilder
    +            .findAccountById(ALICE_ACCOUNT_ID)
    +            .account(ALICE_ACCOUNT_ID)
    +            .buildSigned(ALICE_KEYPAIR);
    +        final CompletableFuture<Account> future = client.sendQueryAsync(query);
    +        final Account account = future.get(getTxTimeout().getSeconds(), TimeUnit.SECONDS);
    +        final AssetValue value = account.getAssets().get(DEFAULT_ASSET_ID).getValue();
    +        Assertions.assertEquals(5, ((AssetValue.Quantity) value).getU32());
    +    }
    +
    +    @Test
    +    @WithIroha(sources = DefaultGenesis.class)
    +    public void updateKeyValueInstructionCommitted() throws Exception {
    +        final Name assetMetadataKey = new Name("asset_metadata_key");
    +        final Value.String assetMetadataValue = new Value.String("some string value");
    +        final Value.String assetMetadataValue2 = new Value.String("some string value 2");
    +        final Metadata metadata = new Metadata(new HashMap<Name, Value>() {{
    +            put(assetMetadataKey, assetMetadataValue);
    +        }});
    +
    +        final VersionedSignedTransaction registerAssetTx = TransactionBuilder.Companion
    +            .builder()
    +            .account(ALICE_ACCOUNT_ID)
    +            .registerAssetDefinition(DEFAULT_ASSET_DEFINITION_ID, new AssetValueType.Store(), metadata)
    +            .buildSigned(ALICE_KEYPAIR);
    +        client.sendTransactionAsync(registerAssetTx).get(getTxTimeout().getSeconds(), TimeUnit.SECONDS);
    +
    +        final AssetId assetId = new AssetId(DEFAULT_ASSET_DEFINITION_ID, ALICE_ACCOUNT_ID);
    +        final VersionedSignedTransaction keyValueTx = TransactionBuilder.Companion
    +            .builder()
    +            .account(ALICE_ACCOUNT_ID)
    +            .setKeyValue(
    +                assetId,
    +                assetMetadataKey,
    +                assetMetadataValue2
    +            ).buildSigned(ALICE_KEYPAIR);
    +        client.sendTransactionAsync(keyValueTx).get(10, TimeUnit.SECONDS);
    +
    +        final QueryAndExtractor<Value> assetDefinitionValueQuery = QueryBuilder
    +            .findAssetKeyValueByIdAndKey(assetId, assetMetadataKey)
    +            .account(ALICE_ACCOUNT_ID)
    +            .buildSigned(ALICE_KEYPAIR);
    +        final CompletableFuture<Value> future = client.sendQueryAsync(assetDefinitionValueQuery);
    +
    +        final Value value = future.get(10, TimeUnit.SECONDS);
    +        Assertions.assertEquals(
    +            ((Value.String) value).getString(),
    +            assetMetadataValue2.getString()
    +        );
    +    }
    +
    +    @Test
    +    @WithIroha(sources = DefaultGenesis.class)
    +    public void setKeyValueInstructionCommitted() throws Exception {
    +        final Value.String assetValue = new Value.String("some string value");
    +        final Name assetKey = new Name("asset_metadata_key");
    +
    +        final VersionedSignedTransaction registerAssetTx = TransactionBuilder.Companion
    +            .builder()
    +            .account(ALICE_ACCOUNT_ID)
    +            .registerAssetDefinition(DEFAULT_ASSET_DEFINITION_ID, new AssetValueType.Store())
    +            .buildSigned(ALICE_KEYPAIR);
    +        client.sendTransactionAsync(registerAssetTx).get(getTxTimeout().getSeconds(), TimeUnit.SECONDS);
    +
    +        final VersionedSignedTransaction keyValueTx = TransactionBuilder.Companion
    +            .builder()
    +            .account(ALICE_ACCOUNT_ID)
    +            .setKeyValue(
    +                DEFAULT_ASSET_DEFINITION_ID,
    +                assetKey,
    +                assetValue
    +            ).buildSigned(ALICE_KEYPAIR);
    +        client.sendTransactionAsync(keyValueTx).get(10, TimeUnit.SECONDS);
    +
    +        final QueryAndExtractor<Value> assetDefinitionValueQuery = QueryBuilder
    +            .findAssetDefinitionKeyValueByIdAndKey(DEFAULT_ASSET_DEFINITION_ID, assetKey)
    +            .account(ALICE_ACCOUNT_ID)
    +            .buildSigned(ALICE_KEYPAIR);
    +        final CompletableFuture<Value> future = client.sendQueryAsync(assetDefinitionValueQuery);
    +
    +        final Value value = future.get(10, TimeUnit.SECONDS);
    +        Assertions.assertEquals(
    +            ((Value.String) value).getString(),
    +            assetValue.getString()
    +        );
    +    }
    +}
    + + + + \ No newline at end of file diff --git a/guide/get-started/launch-iroha-2.html b/guide/get-started/launch-iroha-2.html new file mode 100644 index 00000000..8da81ae5 --- /dev/null +++ b/guide/get-started/launch-iroha-2.html @@ -0,0 +1,69 @@ + + + + + + Launch Iroha 2 | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Launch Iroha 2

    This tutorial explains how to launch an Iroha 2 network.

    1. Prerequisites

    To launch an instance of the Iroha 2 network, install the following first:

    2. Launch Iroha Network

    1. In your terminal, navigate to the root directory of your local iroha repository:

      bash
      $ cd ~/Git/iroha
    2. Run the docker compose command with the docker-compose.yml network configuration file specified to deploy a network of four containerized peers:

      bash
      $ docker compose -f defaults/docker-compose.yml up

      Depending on your setup, this command will either pull an image from Docker Hub or build the container locally.

      Once the process completes, you will see an output similar to the following:

      [+] Running 9/9
      + irohad2 Pulled                                                          6.3s
      + irohad0 Pulled                                                          6.3s
      + irohad3 Pulled                                                          6.3s
      + irohad1 Pulled                                                          6.3s
      + ec99f8b99825 Already exists                                           0.0s
      + d3a0e7f5d646 Pull complete                                            1.4s
      + 1b1d5514cbbf Pull complete                                            2.1s
      + 86e58c28036c Pull complete                                            2.3s
      + 0d3b3367a826 Pull complete                                            2.5s
      +[+] Running 5/5
      + Network swarm_default      Created                                      0.1s
      + Container swarm-irohad3-1  Created                                      0.4s
      + Container swarm-irohad0-1  Created                                      0.5s
      + Container swarm-irohad1-1  Created                                      0.4s
      + Container swarm-irohad2-1  Created                                      0.5s
      +Attaching to irohad0-1, irohad1-1, irohad2-1, irohad3-1
      +irohad0-1  | 2024-07-15T05:51:39.204411Z  INFO irohad: Hyperledgerいろは2にようこそ!(translation) Welcome to Hyperledger Iroha! version="2.0.0-pre-rc.21" git_commit_sha="185ef76" peer=ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D@@0.0.0.0:1337 chain=00000000-0000-0000-0000-000000000000 listening_on=0.0.0.0:8080
      +irohad0-1  | 2024-07-15T05:51:39.204729Z  INFO init:start{listen_addr=WithOrigin { value: 0.0.0.0:1337, origin: Env { id: ParameterId(network.address), var: "P2P_ADDRESS" } } idle_timeout=60s}: iroha_p2p::network: Network bound to listener
      +irohad0-1  | 2024-07-15T05:51:39.209730Z  INFO init:kura_init: iroha_core::kura: Kura init complete mode=Strict block_count=0
      +irohad0-1  | 2024-07-15T05:51:39.210006Z  INFO init: irohad: Didn't find a state snapshot; creating an empty state
      +irohad0-1  | 2024-07-15T05:51:39.214759Z  INFO init: irohad: Telemetry not started due to absent configuration
      +irohad0-1  | 2024-07-15T05:51:39.215234Z  INFO iroha_core::sumeragi: Sumeragi has finished loading blocks and setting up the state
      +
      +...
      +
      + irohad2-1  | 2024-07-15T05:51:39.332824Z  INFO consensus: iroha_core::sumeragi::main_loop: Listening for genesis... peer_id=ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10@@0.0.0.0:1339 role=Leader
      + irohad0-1  | 2024-07-15T05:51:40.478714Z  INFO consensus: iroha_core::sumeragi::main_loop: Block committed peer_id=ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D@@0.0.0.0:1337 prev_role=ProxyTail next_role=ValidatingPeer block_hash=a638001762e365280677a5407bac9adaa119c8cb82c8afe377b72f85e71ed4a9 new_height=1
      + irohad0-1  | 2024-07-15T05:51:40.478761Z  INFO consensus: iroha_core::sumeragi::main_loop: Sumeragi initialized peer_id=ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D@@0.0.0.0:1337 role=ValidatingPeer
      + irohad2-1  | 2024-07-15T05:51:42.085522Z  INFO consensus: iroha_core::sumeragi::main_loop: Block committed peer_id=ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10@@0.0.0.0:1339 prev_role=Leader next_role=ProxyTail block_hash=a638001762e365280677a5407bac9adaa119c8cb82c8afe377b72f85e71ed4a9 new_height=1
      + irohad2-1  | 2024-07-15T05:51:42.085585Z  INFO consensus: iroha_core::sumeragi::main_loop: Sumeragi initialized peer_id=ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10@@0.0.0.0:1339 role=ProxyTail
      + irohad1-1  | 2024-07-15T05:51:42.109788Z  INFO consensus: iroha_core::sumeragi::main_loop: Block committed peer_id=ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D@@0.0.0.0:1338 prev_role=ValidatingPeer next_role=Leader block_hash=a638001762e365280677a5407bac9adaa119c8cb82c8afe377b72f85e71ed4a9 new_height=1
      + irohad1-1  | 2024-07-15T05:51:42.109858Z  INFO consensus: iroha_core::sumeragi::main_loop: Sumeragi initialized peer_id=ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D@@0.0.0.0:1338 role=Leader
      + irohad3-1  | 2024-07-15T05:51:42.117040Z  INFO consensus: iroha_core::sumeragi::main_loop: Block committed peer_id=ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE@@0.0.0.0:1340 prev_role=ObservingPeer next_role=ObservingPeer block_hash=a638001762e365280677a5407bac9adaa119c8cb82c8afe377b72f85e71ed4a9 new_height=1
      + irohad3-1  | 2024-07-15T05:51:42.117083Z  INFO consensus: iroha_core::sumeragi::main_loop: Sumeragi initialized peer_id=ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE@@0.0.0.0:1340 role=ObservingPeer
      + irohad0-1  | 2024-07-15T05:52:39.238596Z  INFO iroha_core::snapshot: Successfully created a snapshot of state at_height=1
      + irohad1-1  | 2024-07-15T05:52:39.266902Z  INFO iroha_core::snapshot: Successfully created a snapshot of state at_height=1
      + irohad3-1  | 2024-07-15T05:52:39.276634Z  INFO iroha_core::snapshot: Successfully created a snapshot of state at_height=1
      + irohad2-1  | 2024-07-15T05:52:39.349409Z  INFO iroha_core::snapshot: Successfully created a snapshot of state at_height=1

    After deploying the network, you can interact with it using the Iroha Client CLI.

    TIP

    You can monitor blockchain events in the terminal where the network runs.

    Docker Options

    The following options are also available for local compilation:

    • To test Iroha code quickly, use the docker-compose-single.yml network configuration file, which starts a container with a single peer.
    • To test Iroha code in normal conditions, use the docker-compose-local.yml network configuration file, which starts four connected containers with peers.

    Note

    There is ongoing work to make our configurations for Docker even more customizable with the help of Swarm.

    + + + + \ No newline at end of file diff --git a/guide/get-started/operate-iroha-2-via-cli.html b/guide/get-started/operate-iroha-2-via-cli.html new file mode 100644 index 00000000..6cfc7be3 --- /dev/null +++ b/guide/get-started/operate-iroha-2-via-cli.html @@ -0,0 +1,170 @@ + + + + + + Operate Iroha 2 via CLI | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Operate Iroha 2 via CLI

    You can perform most operations in an Iroha 2 network using the Iroha Client CLI. This tutorial guides you through setting it up, configuring it, and executing basic operations on the network.

    1. Set Up Iroha Client CLI

    INFO

    To set up the Iroha Client CLI, an instance of the Iroha network must be launched and operational.

    Create a new directory and copy the client.toml configuration file there:

    bash
    $ cp path_to_iroha_repo/defaults/client.toml path_to_new_directory/

    2. Configure Iroha Client CLI

    1. Navigate to the directory with the copied client.toml configuration file.

    2. Run the Iroha Client CLI:

      bash
      $ iroha
      Expected result
      bash
      Iroha CLI Client lets you interact with Iroha Peers Web API without direct network usage
      +
      +Usage: iroha [OPTIONS] <COMMAND>
      +
      +Commands:
      +  domain   The subcommand related to domains
      +  account  The subcommand related to accounts
      +  asset    The subcommand related to assets
      +  peer     The subcommand related to p2p networking
      +  events   The subcommand related to event streaming
      +  wasm     The subcommand related to Wasm
      +  blocks   The subcommand related to block streaming
      +  json     The subcommand related to multi-instructions as Json or Json5
      +  help     Print this message or the help of the given subcommand(s)
      +
      +Options:
      +  -c, --config <PATH>  Path to the configuration file [default: client.toml]
      +  -v, --verbose        More verbose output
      +  -h, --help           Print help
      +  -V, --version        Print version

    By default, the Iroha Client searches for a configuration in the client.toml file located in its current working directory. We already copied it there, so we're all set.

    TIP

    To run any of the Iroha client commands with some other configuration file, use the following syntax:

    bash
    $ iroha --config path/to/client.toml <COMMAND>

    This is a non-persistent configuration: each time you run iroha, you must add the --config path/to/client.toml command-line argument, unless the client.toml config file is in the working directory.

    The account specified in the [account] section of client.toml is preregistered in the default genesis block of the blockchain. Only it can interact with the blockchain for now. If you change the keys or the domain of the account in the configuration file, make sure that they are preregistered on the blockchain too.

    To check that a configuration works, run the following query:

    bash
    $ iroha domain list all

    The output should contain several preregistered domains.

    Expected result
    json
      {
    +    "id": "garden_of_live_flowers",
    +    "logo": null,
    +    "metadata": {},
    +    "owned_by": "ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4@genesis"
    +  },
    +  {
    +    "id": "genesis",
    +    "logo": null,
    +    "metadata": {},
    +    "owned_by": "ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4@genesis"
    +  },
    +  {
    +    "id": "wonderland",
    +    "logo": null,
    +    "metadata": {
    +      "key": "value"
    +    },
    +    "owned_by": "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland"
    +  }

    3. Register a Domain

    INFO

    A domain is a group of entities like asset definitions, accounts, and other objects grouped logically. These are described in greater detail in the Blockchain section of the documentation.

    To register a new domain, run:

    bash
    $ iroha domain register --id="looking_glass"

    Once executed, a confirmation message appears. However, since the details of the new domain are not directly readable in that message, to confirm that you have successfully created the new looking_glass domain, run:

    bash
    $ iroha domain list all
    Expected result
    json
      {
    +    "id": "looking_glass",
    +    "logo": null,
    +    "metadata": {},
    +    "owned_by": "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland"
    +  },

    Note that the owner of the new domain is the account specified in our config file. They performed the registration.

    With a domain available, it is time to register an account in it.

    4. Register an Account

    To register a new account, you need a cryptographic key pair consisting of a public and a private key. You will use it to establish a secure communication channel between yourself and the network.

    For users' convenience, Iroha comes with kagami, a built-in key generator tool. To generate a new key pair with kagami, run the following command:

    bash
    $ kagami crypto

    TIP

    To customize the generated keys, you can specify a number of parameters. For instance, kagami can use one of four available algorithms to generate cryptographic keys.

    To learn more about generating cryptographic keys with kagami, available algorithms, and other parameters, see Generating Cryptographic Keys with Kagami

    For the purposes of this tutorial, we iuse the following key pair:

    bash
    Public key (multihash): "ed0120ABA0446CFBD4E12627FFA870FB37993ED83EB1AE0588184B90D832A64C24C379"
    +Private key (multihash): "802620CBD3D701B561FE98463767729176404DC757D690F78980B8FDD40C171CCB8EB5"

    To register a new account within the looking_glass domain, run:

    bash
    $ iroha account register --id="ed0120ABA0446CFBD4E12627FFA870FB37993ED83EB1AE0588184B90D832A64C24C379@looking_glass"

    The --id argument in the above code snippet specifies the account id, the unique identifier of the account. It consists of the user public key (generated using kagami) and the domain it is associated with.

    If the account registration is successful, you receive a confirmation message. Similar to the domain registration, to confirm that you have successfully created a new account within the looking_glass domain, run:

    bash
    $ iroha account list all
    Expected result
    json
    [
    +  {
    +    "id": "ed0120E9F632D3034BAB6BB26D92AC8FD93EF878D9C5E69E01B61B4C47101884EE2F99@garden_of_live_flowers",
    +    "metadata": {}
    +  },
    +  {
    +    "id": "ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4@genesis",
    +    "metadata": {}
    +  },
    +  {
    +    "id": "ed0120ABA0446CFBD4E12627FFA870FB37993ED83EB1AE0588184B90D832A64C24C379@looking_glass",
    +    "metadata": {}
    +  },
    +  {
    +    "id": "ed012004FF5B81046DDCCF19E2E451C45DFB6F53759D4EB30FA2EFA807284D1CC33016@wonderland",
    +    "metadata": {
    +      "key": "value"
    +    }
    +  },
    +  {
    +    "id": "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland",
    +    "metadata": {
    +      "key": "value"
    +    }
    +  }
    +]

    5. Transfer a Domain

    The account we just created is part of the looking_glass domain but doesn't own it, so it can't manage the domain. To enable this, we'll transfer looking_glass ownership to our new account.

    We could change the keys and domain in client.toml at this point and continue working with the account we just created, but we wouldn't be able to do much in the looking_glass domain, as our new account is not the owner of the looking_glass domain, and therefore cannot manage it.

    To transfer a domain, perform the following:

    1. Run the transfer command:

      bash
      $ iroha domain transfer --id="looking_glass" --from "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland" --to "ed0120ABA0446CFBD4E12627FFA870FB37993ED83EB1AE0588184B90D832A64C24C379@looking_glass"
    2. Check that the ownership changed:

      bash
      $ iroha domain list all
    3. Switch to the newly created account. For this, we need to modify the public_key, private_key, and domain in the client.toml config file with the credentials of the user we want to act as.

    Note that here the domain of the user that we are switching to matches the one we just transferred. However, this is not a requirement. A user may be registered in one domain and own multiple others. When setting the domain in the configuration file, always use the one that your user is registered with.

    Expected result

    The account section of your updated client.toml file:

    toml
    [account]
    +domain = "looking_glass"
    +public_key = "ed0120ABA0446CFBD4E12627FFA870FB37993ED83EB1AE0588184B90D832A64C24C379"
    +private_key = "802620CBD3D701B561FE98463767729176404DC757D690F78980B8FDD40C171CCB8EB5"

    TIP

    Permissions determine accounts rights within Iroha. Domain owners have the most rights in a domain by default, but permission configuration in Iroha is very flexible and can be customized to your needs.

    Now that we control the domain, we can define and manage assets in it.

    6. Register and Mint Assets

    To mint an asset, its asset definition must be registered first.

    To register a tea token within the looking_glass domain, run:

    bash
    $ iroha asset definition register --id="tea#looking_glass" --type="Numeric"

    The numeric tea asset is now registered within the looking_glass domain.

    If you open the terminal where the Iroha network runs, you will see that all our activity caused numerous pipeline events there.

    To mint tea tokens run:

    bash
    $ iroha asset mint --id="tea##ed0120ABA0446CFBD4E12627FFA870FB37993ED83EB1AE0588184B90D832A64C24C379@looking_glass" --quantity="100"

    After minting one hundred tea, more pipeline events are expected, and you can also query the assets that you have just minted:

    bash
    $ iroha asset list all
    Expected result
    json
    [
    +  {
    +    "id": "tea##ed0120ABA0446CFBD4E12627FFA870FB37993ED83EB1AE0588184B90D832A64C24C379@looking_glass",
    +    "value": {
    +      "Numeric": "100"
    +    }
    +  },
    +  {
    +    "id": "cabbage#garden_of_live_flowers#ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland",
    +    "value": {
    +      "Numeric": "44"
    +    }
    +  },
    +  {
    +    "id": "rose##ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland",
    +    "value": {
    +      "Numeric": "13"
    +    }
    +  }
    +]

    7. Transfer Assets

    After minting the assets, you can transfer some of your tea to another account:

    bash
    $ iroha asset transfer --to="ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland" --id="tea##ed0120ABA0446CFBD4E12627FFA870FB37993ED83EB1AE0588184B90D832A64C24C379@looking_glass"  --quantity=33

    8. Burn Assets

    Burning assets is quite similar to minting them:

    bash
    $ iroha asset burn --id="tea##ed0120ABA0446CFBD4E12627FFA870FB37993ED83EB1AE0588184B90D832A64C24C379@looking_glass" --quantity="15"

    9. Visualize Outputs

    Although you will get a constant data feed of the network within the terminal running docker compose, you can also configure an output to listen to events of several types on the network: blocks generation, transactions, data events and triggers.

    We will set up an event listener for the block pipeline.

    From a new terminal tab/window run:

    bash
    $ iroha events block-pipeline
    Expected result
    json
    Listening to events with filter: Pipeline(Block(BlockEventFilter { height: None, status: None }))
    +{
    +  "Pipeline": {
    +    "Block": {
    +      "header": {
    +        "height": 14,
    +        "prev_block_hash": "AF1ABC889019971D4C4E8866C347367D63A024319E50AEF989DB255F761E9D1D",
    +        "transactions_hash": "7F2091D887BF9DBF6100DFEA696B06AE269C288AE55F1D281D9FDDAD93D1B8F1",
    +        "creation_time_ms": 1721132667162,
    +        "view_change_index": 1,
    +        "consensus_estimation_ms": 4000
    +      },
    +      "hash": "1CC6256356418D02F19B17487AD4F7F105AE6CD3FD129760C575066484F3EF97",
    +      "status": "Approved"
    +    }
    +  }
    +}
    +{
    +  "Pipeline": {
    +    "Block": {
    +      "header": {
    +        "height": 14,
    +        "prev_block_hash": "AF1ABC889019971D4C4E8866C347367D63A024319E50AEF989DB255F761E9D1D",
    +        "transactions_hash": "7F2091D887BF9DBF6100DFEA696B06AE269C288AE55F1D281D9FDDAD93D1B8F1",
    +        "creation_time_ms": 1721132667162,
    +        "view_change_index": 1,
    +        "consensus_estimation_ms": 4000
    +      },
    +      "hash": "99D30F9DD159A397A76E4A37143433BD302264F7509B6E154CA9C18263543857",
    +      "status": "Committed"
    +    }
    +  }
    +}
    +{
    +  "Pipeline": {
    +    "Block": {
    +      "header": {
    +        "height": 14,
    +        "prev_block_hash": "AF1ABC889019971D4C4E8866C347367D63A024319E50AEF989DB255F761E9D1D",
    +        "transactions_hash": "7F2091D887BF9DBF6100DFEA696B06AE269C288AE55F1D281D9FDDAD93D1B8F1",
    +        "creation_time_ms": 1721132667162,
    +        "view_change_index": 1,
    +        "consensus_estimation_ms": 4000
    +      },
    +      "hash": "99D30F9DD159A397A76E4A37143433BD302264F7509B6E154CA9C18263543857",
    +      "status": "Applied"
    +    }
    +  }
    +}

    TIP

    To find out how to listen to other types of events, run the iroha events help command.

    What's Next

    Now that you understand the basics, you can explore these advanced documentation:

    + + + + \ No newline at end of file diff --git a/guide/get-started/python.html b/guide/get-started/python.html new file mode 100644 index 00000000..bcf04e0b --- /dev/null +++ b/guide/get-started/python.html @@ -0,0 +1,67 @@ + + + + + + Python 3 Guide | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Python 3 Guide

    1. Iroha 2 Client Setup

    There are two versions of Iroha Python to choose from. In theory, the Iroha 1 version of Iroha Python (that also has the best documentation) should be compatible with an Iroha 2 deployment.

    Thus we should build and install the Iroha 2 compatible version of Iroha-python, using (for now) its GitHub repository.

    Let's create a separate folder for Iroha Python and clone its GitHub repository into it:

    bash
    $ cd ~/Git/
    +$ git clone https://github.com/hyperledger/iroha-python/ --branch iroha2
    +$ cd iroha-python

    Iroha Python is written in Rust using the PyO3 library. Thus, unlike most Python packages, you must build it first:

    bash
    $ pip install maturin
    +$ maturin build

    After the build is complete, install it into your system:

    bash
    $ pip install ./target/wheels/iroha_python-*.whl

    Finally, you will need a working client configuration:

    bash
    $ cp -vfr ~/Git/iroha/configs/client/config.json example/config.json

    TIP

    You can also use the provided config.json in the example folder if you also call docker compose up from that same folder. This has to do with the fact that the configuration for the Docker files in Iroha Python is slightly different.

    2. Configuring Iroha 2

    Unlike iroha binary, finding the configuration file in a scripting language is the responsibility of the person writing the script. The easiest method is to de-serialise a dictionary type from the provided config.json.

    This is an example of how you could do that in Python:

    python
    import json
    +from iroha2 import Client
    +
    +cfg = json.loads(open("config.json").read())
    +cl = Client(cfg)

    If the configuration file is malformed, you can expect an exception to notify you. However, the client doesn't do any verification: if the account used in config.json is not in the blockchain or has the wrong private key, you won't know that until you try and execute a simple instruction. More on that in the following section.

    INFO

    It should also be noted that Iroha Python is under heavy development. It severely lacks in documentation and its API can be made more idiomatically Python.

    3. Registering a Domain

    It is important to remember that Iroha Python is wrapping Rust code. As such, many of Python idioms are not yet accommodated; for example, there's no duck-typing of the Register instruction.

    python
    from iroha2.data_model.isi import *
    +from iroha2.data_model.domain import *
    +
    +domain = Domain("looking_glass")
    +register = Register(Expression(Value(Identifiable(domain))))

    Instead, we are creating a domain and wrapping it in multiple type-erasing constructs. A domain is wrapped in Identifiable (which would be a trait in Rust), which is wrapped in Value, which is wrapped in Expression, which finally is wrapped in the Register instruction. This is not entirely against Python conventions (it is strongly typed, after all), and not entirely counter-intuitive, once you see the corresponding Rust code.

    The instruction to register must be submitted, in order for anything to happen.

    python
    hash = cl.submit_isi(register)

    Note that we also keep track of the hash of the transaction. This will become useful when you visualize the output.

    4. Registering an Account

    Registering an account is similar to the process of registering a domain, except the wrapping structures are different. There are a couple of things to watch out for.

    First of all, we can only register an account to an existing domain. The best UX design practices dictate that you should check if the requested domain exists now, and if it doesn't, suggest a fix to the user.

    python
    from iroha2.data_model.isi import *
    +from iroha2.data_model.account import *
    +
    +public_key =# Get this from white_rabbit.
    +bunny = Account("white_rabbit@looking_glass", signatories=[public_key])
    +register = Register(Expression(Value(Identifiable(bunny))))

    Second, you should provide the account with a public key. It is tempting to generate both the public and the private key at this time, but it isn't the brightest idea. Remember that the white_rabbit trusts you, alice@wonderland, to create an account for them in the domain looking_glass, but doesn't want you to have access to that account after creation.

    If you gave white_rabbit a key that you generated yourself, how would they know if you don't have a copy of their private key? Instead, the best way is to ask white_rabbit to generate a new key-pair, and then give you the public half of it.

    After putting all of this together, we submit it as before:

    python
    hash = cl.submit_isi(register)

    5. Registering and minting assets

    Iroha has been built with few underlying assumptions about what the assets need to be in terms of their value type and characteristics (fungible or non-fungible, mintable or non-mintable).

    Asset creation is by far the most cumbersome:

    python
    import iroha2.data_model.asset as asset
    +from iroha2.sys.iroha_data_model import Value
    +
    +time = asset.Definition(
    +    value_type=asset.ValueType.Quantity,
    +    id=asset.DefinitionId(name="time", domain_name="looking_glass"),
    +    metadata={"a": Value.U32(10)},
    +    mintable=False
    +)

    Note the following; First, we used the **kwargs syntax to make everything more explicit.

    We have a value_type which must be specified. Python is duck-typed, while Rust isn't. Make sure that you track the types diligently, and make use of mypy annotations.

    The Quantity value type is an internal 32-bit unsigned integer. Your other options are BigQuantity, which is a 128-bit unsigned integer, and Fixed. All of these are unsigned. Any checked operation with a negative Fixed value (one that you got by converting a negative floating-point number), will result in an error.

    Continuing the theme of explicit typing, the asset.DefinitionId is its own type. We could have also written asset.DefinitionId.parse("time#looking_glass"), but making sure that you know what's going on is more useful in this case.

    Finally, we have mintable. By default this is set to True, however, setting it to False means that any attempt to mint more of time#looking_glass is doomed to fail. Unfortunately, since we didn't add any time at genesis, the white_rabbit will never have time. There just isn't any in his domain, and more can't be minted.

    OK. So how about a mint demonstration? Fortunately, alice@wonderland has an asset called roses#wonderland, which can be minted. For that we need to do something much simpler.

    python
    amount = Expression(Value(U32(42)))
    +destination = Expression(Value(Identifiable(asset.DefinitionId.parse("rose#wonderland"))))
    +mint_amount = Mint(amount, destination)
    +cl.submit_isi(mint_amount)

    This would add 42 to the current tally of roses that Alice has.

    6. Visualizing outputs

    The paradigm that Iroha chose to allow monitoring some events is the filter-map paradigm. Let's look at what we need to do in order to know e.g. what happened to a submitted instruction.

    First, we'll need to remember the hash of the transaction that we want to track, next we create a filter:

    python
    filter = EventFilter.Pipeline(
    +    pipeline.EventFilter(
    +        entity=pipeline.EntityType.Transaction(),
    +        hash=None,
    +    ))

    And add a listener on that filter. Don't worry, the Rust side of the process is asynchronous, so barring issues with the GIL, you won't lock up your interpreter.

    Note the types. The EventFilter is a type that filters out anything that isn't an event (and non-event types are beyond the scope of this tutorial). The pipeline module helps us by providing a concrete type of EventFilter, namely one that listens for transactions. Note that we haven't used the hash here.

    Finally, we add a listening filter to the client:

    python
    listener = cl.listen(filter)

    Now we must actually listen for events:

    python
    for event in listener:
    +    print(event)
    +
    +    if event["Pipeline"]["status"] == "Committed" \
    +        and event["Pipeline"]["hash"] == hash:
    +        break

    And now, we have an infinite loop that will not quit until the event gets committed.

    WARNING

    Nobody should do this in production code, and instead monitor the event queue for (at least) the possibility that the transaction gets Rejected.

    + + + + \ No newline at end of file diff --git a/guide/get-started/rust.html b/guide/get-started/rust.html new file mode 100644 index 00000000..da99841a --- /dev/null +++ b/guide/get-started/rust.html @@ -0,0 +1,112 @@ + + + + + + Rust Guide | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Rust Guide

    1. Iroha 2 Client Setup

    In this part we shall cover the process of using the Iroha 2 Rust libraries. Instead of providing the complete basics, we shall assume knowledge of the most widely used concepts, explain what's unusual about Iroha 2 specifically, and provide a step-by-step guide to creating your own Rust client for it.

    We assume that you know how to create a new package and have basic understanding of the fundamental Rust code; async functions, enum types, traits and borrowing/ownership, as well as the libraries that we use: serde, tokio, tracing, etc.

    TIP

    If you don't feel comfortable with any of the above, we recommend consulting the Rust book and docs.rs.

    Iroha 2 makes extensive use of workspaces. Currently, there are two workspaces, the one that contains the WASM support library and the one that contains the core support libraries, which go in a domain-first order. What that means is that instead of having a global constants crate, we have a crate for the blockchain data model (iroha_data_model), a crate with cryptographic primitives (iroha_crypto), and so on. These, individually, have a module for constants.

    If you add iroha_client to the other two crates, you get the minimum number of dependencies to start your own client, similar to iroha binary.

    Once the initial v2.0.0 release is complete, we plan to create a package on crates.io with all the documentation. In the meantime, you could use the local copy that you've just created in the previous step as a local installation in your client's Cargo.toml:

    toml
    [dependencies]
    +iroha_client = { version = "=2.0.0-pre-rc.13", path = "~/Git/iroha/client" }
    +iroha_data_model = { version = "=2.0.0-pre-rc.13", path = "~/Git/iroha/data_model" }
    +iroha_crypto = { version = "=2.0.0-pre-rc.13", path = "~/Git/iroha/crypto" }
    +iroha_config = { version = "=2.0.0-pre-rc.13", path = "~/Git/iroha/config" }

    The added benefit of using a local copy is that you have access to the minimal BFT network in the form of docker-compose.yml, which allows you to experiment. The drawbacks are mitigated by the fact that Rust links statically by default, so we recommend you experiment with the local set up first.

    INFO

    You could also make use of our test_network crate, which is available via GitHub but not via crates.io.

    You would also benefit from having immediate access to the example configurations in the ~/Git/iroha/configs folder.

    So let's copy the example client configuration somewhere useful:

    bash
    $ cp -vfr ~/Git/iroha/configs/client/config.json example/config.json

    We recommend looking through it to familiarise yourself with the key pieces of information that every Iroha 2 client needs. Specifically, each client operates on behalf of a pre-existing account. These accounts are identified by a name@domain_name ID and can only be accessed provided that you know their specific key.

    2. Configuring Iroha 2

    Your application written in Rust needs to instantiate a client. The client typically needs specific configuration options, which you could either generate or load from the provided config.json. Let's do that now:

    rs
    rs
    let config = Config::load("../configs/swarm/client.toml").unwrap();

    Using said configuration, instantiate a client:

    rs
    // Create an Iroha client
    +let iroha_client = Client::new(config);

    Note that it used to be necessary to create a mutable client. Sending and receiving messages affects the client's internal state, but now that state is hidden behind interior mutable smart pointers.

    Of course, depending on your application, you might want to de-serialise your ClientConfiguration structure from a different location. Perhaps, you might want to build the configuration in place using the command-line arguments, or perhaps, you're using the XDG specification to store the file persistently in a different location. For this purpose, it's useful to try and construct an instance of ClientConfiguration:

    rust
    use iroha_core::prelude::*;
    +use iroha_data_model::prelude::*;
    +
    +let kp = KeyPair::new(
    +    PublicKey::from_str(
    +        r#"ed01207233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0"#,
    +    )?,
    +    PrivateKey::from_hex(
    +        Algorithm::Ed25519,
    +        "9ac47abf59b356e0bd7dcbbbb4dec080e302156a48ca907e47cb6aea1d32719e7233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0"
    +            .into(),
    +    )?
    +)?;
    +
    +let (public_key, private_key) = kp.clone().into();
    +let account_id: AccountId = "alice@wonderland".parse()?;
    +
    +let config = ClientConfiguration {
    +    public_key,
    +    private_key,
    +    account_id,
    +    torii_api_url: SmallStr::from_string(iroha_config::torii::uri::DEFAULT_API_URL.to_owned()),
    +    ..ClientConfiguration::default()
    +};

    INFO

    Note that the keys in client configuration are given in multi-hash format. If you are experiencing issues parsing the keys in this format, check the troubleshooting section.

    3. Registering a Domain

    Registering a domain is a relatively easy operation. Most of the boilerplate code has to do with setting up the Iroha 2 client and deserialising its configuration.

    rs
    use iroha_client::{
    +    client::Client,
    +    data_model::{
    +        metadata::UnlimitedMetadata,
    +        prelude::{Domain, DomainId, InstructionBox, Register},
    +    },
    +};

    To register a domain, you need the domain name:

    rs
    // Create a domain Id
    +let looking_glass: DomainId = "looking_glass".parse()?;

    Which we convert into an instruction:

    rs
    // Create an ISI
    +let create_looking_glass = Register::domain(Domain::new(looking_glass));

    Note that we use RegisterBox and IdentifiableBox. Despite what your instincts as a Rust developer might suggest, we're not actually using any kind of dynamic dispatch. There's no dyn anywhere, and RegisterBox isn't an alias for Box<dyn Register>.

    A RegisterBox is a specialised enum that uses static dispatch to achieve what looks like dynamic dispatch, without any heap allocation. If you want to add more types to RegisterBox you must either open an issue on GitHub, or do that by yourself on a local fork of Iroha.

    The instruction is then batched into a transaction:

    rs
    // Prepare a transaction
    +let metadata = UnlimitedMetadata::default();
    +let instructions: Vec<InstructionBox> = vec![create_looking_glass.into()];
    +let tx = iroha_client.build_transaction(instructions, metadata);

    Which is then submitted into the pipeline:

    rs
    // Submit a prepared domain registration transaction
    +iroha_client
    +    .submit_transaction(&tx)
    +    .wrap_err("Failed to submit transaction")?;

    Note the question mark here. This will return an Err variant if there's something immediately and obviously wrong with the transaction: for example, if it couldn't submit the transaction to the peer (e.g. there's no connection), or if the transaction got rejected with an error. The cost is that the submit_transaction function is synchronous.

    We could have also done the following:

    rust
    iroha_client
    +    .submit_with_metadata(create_looking_glass, UnlimitedMetadata::default())?;

    or

    rust
    iroha_client.submit(create_looking_glass)?;

    The latter style is just syntactic sugar. Every submission comes in the form of a transaction that has metadata.

    While the latter is a convenient shorthand that we shall use frequently, we strongly advise using explicit construction in production code.

    INFO

    It is likely that we shall replace most if not all instances of submit in our code base with explicit transactions.

    4. Registering an Account

    Registering an account is a bit more involved than registering a domain. With a domain, the only concern is the domain name. However, with an account, there are a few more things to worry about.

    First of all, we need to create an AccountId. Note that we can only register an account to an existing domain. The best UX design practices dictate that you should check if the requested domain exists now, and if it doesn't, suggest a fix to the user. After that, we can create a new account named white_rabbit.

    rs
    use iroha_client::data_model::prelude::AccountId;
    +
    +// Create an `iroha_client::data_model::AccountId` instance
    +// with a DomainId instance and a Domain ID for an account
    +let longhand_account_id = AccountId::new("white_rabbit".parse()?, "looking_glass".parse()?);
    +let account_id: AccountId = "white_rabbit@looking_glass"
    +    .parse()
    +    .expect("Valid, because the string contains no whitespace, has a single '@' character and is not empty after");
    +
    +// Check that two ways to define an account match
    +assert_eq!(account_id, longhand_account_id);

    Second, you should provide the account with a public key. It is tempting to generate both it and the private key at this time, but it isn't the brightest idea. Remember, that the white_rabbit trusts you, alice@wonderland, to create an account for them in the domain _looking_glass, but doesn't want you to have access to that account after creation.

    If you gave white_rabbit a key that you generated yourself, how would they know if you don't have a copy of their private key? Instead, the best way is to ask white_rabbit to generate a new key-pair, and give you the public half of it:

    rust
    let key: PublicKey = get_key_from_white_rabbit();

    Only then do we build an instruction from it:

    rust
    let create_account =
    +    RegisterBox::new(IdentifiableBox::from(NewAccount::with_signatory(id, key)));

    Which is then wrapped in a transaction and submitted to the peer as in the previous section.

    5. Registering and minting assets

    Iroha has been built with few underlying assumptions about what the assets need to be in terms of their value type and characteristics (fungible or non-fungible, mintable or non-mintable).

    To register an asset, we first construct an iroha_data_model::asset::DefinitionId like so:

    rs
    // Create an asset
    +let asset_def_id = AssetDefinitionId::from_str("time#looking_glass")
    +    .expect("Valid, because the string contains no whitespace, has a single '#' character and is not empty after");

    INFO

    Note that we use # symbol to separate the name of the asset from the domain to which it belongs. This is intentional. This reflects the rule that there can be many alices in many domains, with only one alice per domain, and there can be an asset that is also named alice, but there can be only one, regardless of type.

    Then construct an instruction:

    rs
    // Initialise the registration time
    +let register_time =
    +    Register::asset_definition(AssetDefinition::numeric(asset_def_id.clone()).mintable_once());
    +
    +// Submit a registration time
    +iroha_client.submit(register_time)?;

    This creates an asset time that can only be minted once and has the type fixed. AssetDefinition::fixed just like its other cousins (quantity and big_quantity) returns a builder of an AssetDefinition.

    This asset is mintable_once, which means that the next time we mint it, we have to specify the entire amount that is going to exist for the rest of the existence of the blockchain.

    rs
    // Create a MintBox using a previous asset and account
    +let mint = Mint::asset_numeric(numeric!(12.34), AssetId::new(asset_def_id, account_id));
    +
    +// Submit a minting transaction
    +iroha_client.submit_all([mint])?;

    Now imagine that the white_rabbit@looking_glass was not very keen and didn't notice that he wanted 123.4_f64 as the amount of time. Now white rabbit notices the problem and thinks "oh dear, not a lot of time has passed, perhaps I can give myself some more", and submits another mint request with 111.06_f64 instead of the original 12.34_f64. But, alas, no such luck. The white rabbit cannot mint more time and is thus perpetually late.

    Roses, by contrast, are already registered in the network during the genesis round, and belong to alice@wonderland. Moreover, when they were registered, we didn't add the restriction, so we can mint them again and again as alice:

    rs
    let mint_roses = Mint::asset_numeric(42u32, AssetId::new(roses, alice));

    Then submit the instruction as usual:

    rs
    iroha_client
    +    .submit(mint_roses)
    +    .wrap_err("Failed to submit transaction")?;

    INFO

    Our assets are strongly typed. As such, when you create a MintBox, you need to check that the asset has the correct underlying type. If you don't know the type, query it. This is also why we specifically annotate numerical literals with their type.

    Contrary to what you might think, this restriction isn't just for pedantry. Implicit conversion errors are the bane of all programmers, if you got the AssetValueType incorrect, how do you know that it was the only mistake in that transaction?

    6. Transferring assets

    Transferring assets is a bit more involved than minting them. First, you need to know the account ID of the account that you're transferring from and the account ID of the account that you're transferring to.

    rust
    let from_account_id: AccountId = "alice@wonderland".parse().unwrap();
    +let to_id: AccountId = "bob@wonderland".parse().unwrap();

    You also need to know the asset ID of the asset that you're transferring:

    rust
    let asset_definition_id: AssetDefinitionId = "time#looking_glass".parse().unwrap();
    +let from_asset_id = AssetId::new(asset_definition_id, from_account_id);

    Then you need to specify the amount that you're transferring:

    rust
    let amount = 1 as u32;
    +let value: Value = amount.into();

    Then you can create a transfer instruction and submit it:

    rust
    let from_id_box = IdBox::AssetId(from_asset_id);
    +let to_id_box = IdBox::AccountId(to_id);
    +let transfer_expr = TransferExpr::new(from_id_box, value, to_id_box);
    +client.submit(transfer_expr);

    7. Burning assets

    Burning assets is quite similar to minting. First, you create the burn instruction indicating which asset to burn and its quantity.

    rs
    // Burn the Asset instance
    +let burn_roses = Burn::asset_numeric(10u32, AssetId::new(roses, alice));

    Then submit this instruction:

    rust
    iroha_client.submit(burn_roses)?;

    8. Visualising outputs

    Finally, we should talk about visualising data. The Rust API is currently the most complete in terms of available queries and instructions. After all, this is the language in which Iroha 2 was built.

    We shall, however, leave most of the aforementioned advanced features down the rabbit hole, up to the reader's own devices to discover. This document can easily get out of sync with the state of the API features. By contrast, the online documentation is always up to date. Plus a short tutorial wouldn't be able to do all these features justice. Instead, we shall retain parity with other language tutorials and introduce you to pipeline filters.

    There are two possible event filters: PipelineEventFilter and DataEventFilter, we shall focus on the former. This filter sieves events pertaining to the process of submitting a transaction, executing a transaction, and committing it to a block.

    First, let's build a filter:

    rust
    use iroha_data_model::prelude::*;
    +
    +let filter = FilterBox::Pipeline(PipelineEventFilter::identity());

    Then, we start listening for events in an infinite loop:

    rust
    for event in iroha_client.listen_for_events(filter)? {
    +    match event {
    +        Ok(event) => println!("Success: {:#?}", event),
    +        Err(err) => println!("Sadness:( {:#?}",  err),
    +    }
    +};

    Needless to say, an synchronous infinite blocking loop is bad UX for anything but a command-line program, but for illustration purposes, this would create a nice printout, just like in iroha binary.

    + + + + \ No newline at end of file diff --git a/guide/get-started/tutorials.html b/guide/get-started/tutorials.html new file mode 100644 index 00000000..fe2639b6 --- /dev/null +++ b/guide/get-started/tutorials.html @@ -0,0 +1,31 @@ + + + + + + Introduction | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Introduction

    Welcome to the Hyperledger Iroha 2 tutorial. This document is designed to help you get started with Iroha 2, regardless of your knowledge of Hyperledger technology, coding experience or familiarity with blockchains.

    Preamble

    This tutorial is suitable for both experienced developers, prospective users, and people casually curious about blockchain technology. The level of detail is sufficient so that you wouldn't need any supplementary guide. However, should you want to learn more, we have more detailed documentation in the works.

    In this guide, we shall

    • walk you through starting an Iroha network, either with docker (recommended) or using one of the provided scripts;
    • introduce you to the client libraries;
    • take a small detour into the basic concepts of Iroha special instructions, and how they interact with the world state.

    We invite you to follow the tutorial in this order:

    1. If you are already familiar with Hyperledger Iroha, read about the differences between the two versions of Iroha.
    2. Install Iroha 2.
    3. Follow one of the language-specific guides to learn how to set up and configure Iroha 2, register a domain and an account, register and mind assets, and visualize outputs:

    Tutorial Updates

    The current iteration of the Iroha 2 tutorial is a constant work in progress. We are updating the tutorial with each release to reflect the state of Iroha and the newly added features. While we do our best to keep this tutorial up to date, it can go out of sync by a few days or maybe a week.

    + + + + \ No newline at end of file diff --git a/guide/iroha-2.html b/guide/iroha-2.html new file mode 100644 index 00000000..87ac7e47 --- /dev/null +++ b/guide/iroha-2.html @@ -0,0 +1,31 @@ + + + + + + Iroha 2 vs. Iroha 1 | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Iroha 2 vs. Iroha 1

    Iroha 2 is a complete rewrite of Hyperledger Iroha in Rust.

    In this introduction we outline the differences between the two versions of Iroha and highlight the new features of Iroha 2. It should be of particular interest to those who are already familiar with Iroha but wish to upgrade and start using the newer version.

    Note

    Iroha 1 and Iroha 2 are not compatible. Both projects are very different in their approaches and implementations as evident from the comparisons below.

    Among other changes, cryptography and account structures are implemented differently, meaning that users would have to generate new keys and link their new account with the old one through a centralized service, and no data from Iroha 1 would be accessible from Iroha 2.

    Fault Tolerance

    Iroha 2 learned a great deal from the development of the original Iroha. Of particular importance is the new and improved Byzantine-fault-tolerant consensus algorithm—Sumeragi—that allowed us to expand what could be done on a blockchain without any security risks.

    INFO

    Iroha 1 uses a consensus algorithm called Yac. Yac is crash-fault-tolerant, which means that it can survive a set number of nodes crashing, i.e., losing power, being cut off from the network, or being destroyed with a sledgehammer.

    Sumeragi, by contrast, was designed to be Byzantine-fault-tolerant. This means that Iroha 2 can tolerate not only peers being inactive on the network, but also running malicious software and actively trying to falsify data in the blockchain.

    We can mathematically prove that Iroha 2 can work when up to 33% of its nodes are actively trying to stop Iroha 2 from working properly or at all. In other words, even if someone gained control of a third of all of your network nodes, an Iroha 2 deployment is mathematically guaranteed to keep working.

    Minimalist Code Base

    Iroha 2 utilizes a minimalist code base. We take great care to vet our dependencies and avoid large interdependent chunks of code.

    We provide a few telemetry APIs, including prometheus tooling, structured logging in JSON, as well as compatibility with standard tools used in Parity Substrate.

    Our data is strongly-typed, our methods are statically dispatched. We make use of the best that Rust has to offer: serde and parity_scale_codec for serialisation, tokio for co-operative multi-threading, as well as testing, bench-marking, static analysis and code auditing tools that come packaged with the exemplary cargo.

    Our code is easy to reason about, and quick to compile, whilst also being ergonomic to use and thoughtfully crafted. We have no panics and no unsafe code.

    Flexibility

    Iroha 2 is also more flexible than the original Iroha due to its modular design.

    It is possible to add or remove features based on a particular use-case. If you want the blockchain to be extremely fast and work on embedded hardware, just compile Iroha 2 without the expensive metrics feature. Don't use telemetry at all? Remove it entirely and enjoy even more performance. Permission sets are plugins that can be upgraded during run-time.

    We have an extensive module system as well as a robust WASM runtime framework.

    Smart Contracts

    Iroha 2 is an event-driven ledger. Each change in the state of the blockchain is necessarily accompanied by its own event that can trigger a smart contract: complex logic designed for use in on-chain scripting.

    For smart contracts, Iroha 2 supports two approaches:

    The first approach is useful when you want very simple transparent logic and also want to minimize the footprint in the blockchain. All interactions with the World state, that is, the state of the blockchain at any given point in time, has to be done using the aforementioned instructions. There is also rudimentary support for domain-specific conditional logic.

    If you want to learn more about smart contracts in Iroha 2, please consult our Wiki.

    Static and Dynamic Linking

    Iroha 2 smartly chooses when to use dynamic linking. This strikes a balance between it being easy to patch a critical security vulnerability in a vendored library like OpenSSL, but also remaining reproducible and portable across platforms, architectures, and deployments.

    INFO

    You get the best of both worlds. Patching a security vulnerability is as easy as running sudo apt upgrade. On the other hand, only security-critical dependencies are linked dynamically, so it is highly unlikely that any of the smaller and less important libraries can break Iroha after an upgrade.

    Testing

    Iroha 2 is extensively tested. Despite being in active development, Iroha has 80% line coverage. Keep in mind that line coverage includes documentation comments, some of which are also tests.

    INFO

    There are plans to include Fuzz testing, property-based testing, and failure-point testing to ensure that Iroha is reliable.

    + + + + \ No newline at end of file diff --git a/guide/reports/csd-rtgs.html b/guide/reports/csd-rtgs.html new file mode 100644 index 00000000..d8a59e64 --- /dev/null +++ b/guide/reports/csd-rtgs.html @@ -0,0 +1,31 @@ + + + + + + CSD/RTGS linkages Proof of concept | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    CSD/RTGS linkages Proof of concept

    In this document we will describe the CSD/RTGS linkages PoC execution via Iroha. This is a project which was done in collaboration with the Asian Development Bank, and Fujitsu. Other participants used technologies such as R3 Corda, Hyperledger Cactus (Cacti), Hyperledger Fabric and many other popular blockchain solutions.

    + + + + \ No newline at end of file diff --git a/guide/security/generating-cryptographic-keys.html b/guide/security/generating-cryptographic-keys.html new file mode 100644 index 00000000..2b08e726 --- /dev/null +++ b/guide/security/generating-cryptographic-keys.html @@ -0,0 +1,77 @@ + + + + + + Generating Cryptographic Keys | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Generating Cryptographic Keys

    In the realm of blockchain technology, cryptographic keys play a crucial role in upholding the security and authenticity of data transactions. With Iroha 2, you can create these vital keys to safeguard your digital assets and communications.

    This section describes how to generate keys using the kagami tool, shipped alongside Iroha 2.

    In the future, alternative methods of generating public keys shall be added.

    Generating Cryptographic Keys with Kagami

    TIP

    Since kagami does not come with a manual page, you can use the --help (-h) command to retrieve a brief summary of all the usable kagami parameters within the CLI you are using.

    After installing Iroha, run the following command from the project's root directory to generate a new key pair:

    bash
    $ cargo run --bin kagami --release -- crypto

    You can specify a number of different parameters to tailor the generated key pair to your specific needs. The following parameters are available:

    • --algorithm (-a): Specifies the algorithm used for the key pair generation and encryption. If no algorithm is specified, ed25519 is used by default. Can be one of the following:

      • ed25519ECC an algorithm that utilises the Ed25519 curve, offering efficient and secure cryptographic operations for digital signatures and key exchange. If no algorithm is specified in a request, then ed25519 is used by default. Learn more:

      • secp256k1ECC an algorithm known for its application in blockchain systems like Bitcoin. It provides a robust foundation for secure key generation, digital signatures, and encryption.

      Learn more:
      Secp256k1 (Bitcoin Wiki)

      • bls_small — The Boneh-Lynn-Shacham algorithm with a small parameter configuration. This variant of the BLS cryptographic scheme is optimised for efficiency in certain resource-constrained environments while maintaining fundamental security properties.

      Learn more:
      BLS digital signature (Wikipedia)

      • bls_normal — The Boneh-Lynn-Shacham algorithm with a standard parameter configuration. This configuration of the BLS cryptographic scheme offers a balanced approach between efficiency and security, making it suitable for a wide range of applications in blockchain and cryptographic protocols.

      Learn more:
      BLS digital signature (Wikipedia)

    • --seed (-s): Specifies a string that serves as a deterministic starting point for the key pair generation. If a seed string is specified, kagami will generate the same key for the same string. If no seed is specified, a random seed value is chosen, and each invocation of kagami crypto will result in a different key. This parameter accepts a valid string of Unicode characters. For example, the seed string can contain not only numeric and latin, but also cyrillic, logographic (e.g., Japanese kanji characters) and ideographic (e.g., emojis) characters, as well as any font-related variations of those characters introduced to Unicode over the years.

      TIP

      If one chooses to use a seed, it must be treated as if it were a password: more randomness and longer seed strings make the cryptographic keys more resilient to dictionary attacks.

    • --private-key (-p): Specifies an existing private key as a string in the multihash format that is used to generate a public key.

    • --json (-j): Specifies that the output must be generated in the JSON format, which is mostly helpful for copy-and-pasting into the config.json file.

    • --compact (-c): Specifies that the output private and public keys are displayed on separate lines and are not labeled.

    Examples

    bash
    
    +# Input
    +$ cargo run --bin kagami crypto
    +
    +# Possible Output (same layout, different keys)
    +Public key (multihash): "ed01206B0F56F58761060056355DBA0E0FC489CFB2F974481ED64873082E6032796235"
    +Private key (ed25519): "F71EA9D897C4338CBF4F1DC7B492AAD0BF6CE896B803D7CDB9CF25ECC15109826B0F56F58761060056355DBA0E0FC489CFB2F974481ED64873082E6032796235"
    bash
    # Input
    +$ kagami crypto -a secp256k1
    +
    +# Possible output
    +Public key (multihash): "e70121022A9D6E0D54022C0E2752E43ADD91ADA28259E1F2CE0C6D4E9183FB2882DE6749"
    +Private key (secp256k1): "7687B1433FB6731E6DC635A376B3EB3B5FCD1E02C9775C1642E7FD5DA035EC75"
    bash
    # Input
    +$ kagami crypto -s 1729
    +
    +# Exact output
    +Public key (multihash): "ed0120B678073CFAE6E247A58B442661C7DA0E13BAC5031CBC6343EF566B8718D47D04"
    +Private key (ed25519): "2669BB1099477B970E1D7D7C54E345A64A54213FCFBA2465CBCD6D4E5091A71DB678073CFAE6E247A58B442661C7DA0E13BAC5031CBC6343EF566B8718D47D04"
    bash
    
    +# Input
    +$ kagami crypto -p 2669BB1099477B970E1D7D7C54E345A64A54213FCFBA2465CBCD6D4E5091A71DB678073CFAE6E247A58B442661C7DA0E13BAC5031CBC6343EF566B8718D47D04
    +
    +# Exact output
    +Public key (multihash): "ed0120B678073CFAE6E247A58B442661C7DA0E13BAC5031CBC6343EF566B8718D47D04"
    +Private key (ed25519): "2669BB1099477B970E1D7D7C54E345A64A54213FCFBA2465CBCD6D4E5091A71DB678073CFAE6E247A58B442661C7DA0E13BAC5031CBC6343EF566B8718D47D04"
    bash
    # Input
    +$ cargo run --bin kagami crypto -j
    +
    +# Possible output
    +{
    +  "public_key": "ed0120B678073CFAE6E247A58B442661C7DA0E13BAC5031CBC6343EF566B8718D47D04",
    +  "private_key": {
    +    "digest_function": "ed25519",
    +    "payload": "2669bb1099477b970e1d7d7c54e345a64a54213fcfba2465cbcd6d4e5091a71db678073cfae6e247a58b442661c7da0e13bac5031cbc6343ef566b8718d47d04"
    +  }
    +}
    bash
    # Input
    +$ cargo run --bin kagami crypto -c
    +
    +# Possible output
    +ed0120B678073CFAE6E247A58B442661C7DA0E13BAC5031CBC6343EF566B8718D47D04
    +2669BB1099477B970E1D7D7C54E345A64A54213FCFBA2465CBCD6D4E5091A71DB678073CFAE6E247A58B442661C7DA0E13BAC5031CBC6343EF566B8718D47D04
    +ed25519
    bash
    # Input
    +$ cargo run --bin kagami crypto -a bls_normal -s 2048
    +
    +# Exact output
    +Public key (multihash): "ea01610402A54ABCC40819F15E3553CC8D42D628EEAD7E1B10724BD2AFE523A7C0446EB1CB3F14D4500BD68C997784136FD056BA04215DFD2D3FDC7883B43AE94AC52B7D01525F5A80B41C01701502B46DBB9F0384CC7BE037DC2CBC928014E52A4C5C3B"
    +Private key (bls_normal): "0000000000000000000000000000000035D9120A174E35E966DD92DE90B2446D4B060C8B72018B3917A1C97D7E93EAEC"

    Other Operations with Kagami

    1. Building kagami

    The Iroha 2 node binary and all supporting tools are supplied in the official docker image. However, using it like this is cumbersome, as kagami is meant to be used as a standalone external tool, so building it from a source may be helpful.

    To build kagami, run the following:

    bash
    $ cargo build --bin kagami

    This will produce a single statically linked executable in the target/debug directory, that still links dynamically against the system-provided standard C-library.

    Note

    Iroha and all supporting tools can also be built to statically link against the musl standard library, which allows the application to run on any POSIX-compliant ELF-capable system (all GNU+Linux distributions, some BSD variants).

    2. Installing the source-built kagami into /bin

    There are multiple ways to make your command line be able to use the kagami version that you have just compiled. One of the easiest ways that should work on most systems is to move or link the binary into the /bin directory on UNIX systems.

    bash
    $ sudo mv target/debug/kagami /bin

    3. Moving kagami to the .local/bin directory

    To circumvent the requirement of having the binary in the global binary folder, and thus necessarily exposing the binary to all other users, as well as requiring root authentication (which is not always available), one can instead install the application as a regular user.

    To move kagami to the authenticated user's .local/bin directory, making it uniquely accessible only by that user, run the following:

    bash
    $ mv target/debug/kagami ~/.local/bin

    This method works on most GNU Linux distributions, but is not guaranteed to do so. If it doesn't, consult the next subtopic.

    Making the <username>/.local/bin directory available to the shell

    To make the <username>/.local/bin directory explicitly available to your shell's .rc file, perform the following:

    1. Check if kagami is available by running the following:
    bash
    $ whereis kagami
    +kagami:
    1. Depending on the shell that you are using, perform one of the following:
    • If using Bash: Fix the PATH variable for the shell and then reload the .bashrc script by running the following:

      bash
      $ echo "export PATH='${HOME}/.local/bin:${PATH}'" >> ~/.bashrc
      +$ source ~/.bashrc
    • If using Zsh: Fix the PATH variable for the shell and reload the .zshrc script by running the following:

      bash
      $ echo "export PATH='${HOME}/.local/bin:${PATH}'" >> ~/.zshrc
      +$ source ~/.zshrc
    • If using fish: Fix the PATH variable for the shell variable permanently by running the following:

      bash
      $ fish_add_path ~/.local/bin

    INFO

    In addition to the methods listed above, consult documentation for the shell you're using or consider adding the PATH variant to your terminal's session configuration.

    + + + + \ No newline at end of file diff --git a/guide/security/index.html b/guide/security/index.html new file mode 100644 index 00000000..b1242367 --- /dev/null +++ b/guide/security/index.html @@ -0,0 +1,31 @@ + + + + + + Security | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Security

    When utilizing Iroha 2—or any other blockchain ledger for that matter—security is paramount for financial organizations, as it forms the foundation of trust in an industry where sensitive financial data and transactions are routine. A successful security breach performed by a malicious party can lead to devastating consequences for you. Therefore establishing preemptive security measures is essential to protect the integrity and confidentiality of your sensitive data.

    In this section you can learn about various aspects of securing your Iroha 2 network. To learn more, choose one of the following topics:

    • Security Principles:

      The core security principles that individuals and organizations can adopt to protect their data and decrease the chance of a breach and/or leak.

    • Operational Security:

      Best practices for securing the day-to-day operations of your network, including access controls, monitoring, incident responses, the use of browsers, etc.

    • Password Security:

      A deep-dive into password entropy, creating strong passwords and avoiding password vulnerabilities.

    • Public Key Cryptography:

      An introduction into public key cryptography, encryption, signatures, and their role in establishing secure communication within the blockchain.

      • Generating Cryptographic Keys:

        Instructions on how to generate cryptographic keys and use kagami (a supporting tool shipped alongside Iroha 2).

      • Storing Cryptographic Keys:

        Best practices for securing your cryptographic keys with a number of different approaches that can also be combined.

    + + + + \ No newline at end of file diff --git a/guide/security/operational-security.html b/guide/security/operational-security.html new file mode 100644 index 00000000..3c7a3a31 --- /dev/null +++ b/guide/security/operational-security.html @@ -0,0 +1,31 @@ + + + + + + Operational Security | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Operational Security

    Operational Security (OPSEC) is a systematic approach to security and risk management, which is essentially a collection of strategies and advice adopted for specific use-cases with the aim of preventing unauthorized access and data leakage.

    OPSEC is the standard practice for most companies to guarantee the availability and stability of their assets. This includes considering such factors as physical security (e.g., making sure that unattended post-it notes do not contain sensitive data), secure communication protocols (e.g., not sending sensitive data over unencrypted SMS), threat analysis (e.g., determining potential malicious parties, learning about the latest attack methods), personnel training (e.g., without employees following OPSEC measures, they will, sooner or later, prove to be ineffective), and risk mitigation (e.g., encrypting your hard drives and USB devices).

    Since Iroha 2 is likely to be deployed as a financial ledger, OPSEC measures and practices must be taken seriously. This topic describes strategies and approaches that individuals and organizations using Iroha 2 in their operations should consider as part of their extensive security protocol.

    Following and adopting the guidelines in this topic is a necessary step towards achieving total security, however, it is not sufficient on its own. To further improve your security, learn more throughout the rest of the Security section and specifically the following topics:

    • Stay vigilant. The most likely way in which one can lose their assets in a blockchain is by giving away their sensitive details.

    • Encrypt your disks. Encrypting boot devices allows them to protect your data even if an attacker have gained access to the hardware. Doing it for your portable devices is twice as important.

    • Use trusted software. Software that ships via reproducible binary builds, and that you build from source, is the most trustworthy. Proprietary or open-source software that hasn't been audited is a potential risk that must be taken seriously.

    • Never leave portable devices with sensitive data unattended. A split second is enough to steal your device.

    • Verify the signatures on binary packages. This is not too different from the public key cryptography used inside Iroha v2.

    • To prevent unauthorized access, always secure your laptop or personal computer when leaving it unattended. Use strong passwords, lock the screen, and follow best practices for securing your devices.

    • Establish a secure air-gapped location for your keys. First, encrypt the keys, then store them in an offline-only device, ideally with electromagnetic shielding installed. Hardware keys are specifically designed this purpose.

    • Always keep your software updated to their latest version across all devices, including computers and phones. Regular updates help patch vulnerabilities and minimise potential risks associated with outdated software, even before such vulnerabilities are disclosed.

    • Develop a routine for periodically updating passwords and cryptographic keys. This proactive approach significantly contributes to enhancing overall security posture, since it is much harder to hit a moving target.

    Using Browsers

    If an application connected to Iroha 2 features a web UI, your browser can either aid the security or pose a potential threat. It is essential to exercise caution, especially when it comes to the plugins you choose to install.

    Consider the following measures to enhance your browsing security:

    • Avoid using browsers that are known for having bad security models and for leaking their users' data.

      You can look up privacy violations and security issues for any browser. For example, this article on browser privacy discusses a variety of browsers and how secure they are. Note that proprietary browsers (such as Chrome, Safari, Opera, Vivaldi, Edge, and others) are generally tremendously harder to audit due to their code being hidden from public, which means that you cannot be sure how secure they are.

    • Give preference to browsers with solid history of valuing and protecting their users' privacy and security:

      • Librewolf, Icecat, Firedragon, etc. — well established forks of Mozilla Firefox with added security features.
      • Ungoogled chromium — a highly audited open-source version of Google Chrome that is enhanced with additional security measures and has all of the Google-related web services removed.
      • Brave — a highly audited open-source version of Google Chromium that is enhanced with additional security measures; has a built-in VPN and ad blocker functionality.
      • Falkon — an open-source Qt-based web browser (built on QtWebEngine, a wrapper for Google Chromium) with known track record of being secure; has a number of extensions available for download from its KDE store page.
      • Qutebrowser — an open-source Qt-based web browser (built on QtWebEngine, a wrapper for Google Chromium) with known track record of being secure; has a unique keyboard-focused approach with minimalist GUI; considered to be a browser of choice for many security specialists.
    • Avoid enabling JavaScript unless necessary.

    • Use the browser's built-in confinement mechanism for plugins to restrict the access rights that the installed plugins have.

    • Clear cookies before and after important operations. Be mindful not to enable the Keep Me Signed In or Remember me feature. Keep in mind that some websites have this feature enabled by default.

    • Use an ad blocker. These not only block ads but also disable site tracking features. Depending on the browser you use, an ad blocker may not be a built-in feature.

    • Be mindful of lookalike characters (e.g., 0, θ, O, О, and ߀ are six different characters). Paying attention to details like this may save you from a phishing attack.

    • Avoid web UI email clients in favour of desktop clients. Before using it, set up your desktop email client to sign and verify GPG key signatures.

    • Avoid using web-based messaging services. For instance, Discord (built with the infamous electron framework) is susceptible to many of the same attacks as would a Google Chromium window with the web version of Discord open.

    • Update your browser to the latest version whenever possible. Updates often include critical security patches that address vulnerabilities.

    • Be cautious of what browser extensions you install. Only use well-known and trusted extensions from reputable sources. Rogue extensions can compromise your data and privacy.

    • Create separate browser profiles for various tasks. Use one profile for everyday browsing and another for activities involving high security and sensitive data. This way, extensions installed on the profile for everyday browsing cannot access the sensitive data from the secure one.

    • Use a portable version of your browser copied to a USB flash drive. This method ensures that even if a security bug grants one of the installed plugins with access to data between the profiles, your security-related profile remains on a separate and removable device.

    • Periodically clear your browser's cache and cookies to remove potentially sensitive data that may accidentally be stored on your device.

    Recovery Plan

    In the event of an emergency, such as losing a key or facing a security breach, a well-structured and prepared in advance recovery plan is an essential lifeline. Creating a clear set of steps to follow can help mitigate potential damage and promptly reinstate security.

    Organizations should consider the following key aspects when developing their recovery plan:

    • Outline step-by-step procedures to be followed in case of key loss or other security incidents. Ensure that these steps are easily accessible and understandable by the users and/or employees.

    • Establish a communication channel that may be used to promptly report security breaches and potential threats, such as leaked or lost cryptographic keys and password.

    • If you utilize hardware keys (e.g., YubiKey or SoloKeys Solo) as a security measure, consider adopting redundancy strategy. Keep two keys: one for daily use and another stored in a secure location. This precaution ensures access even if the primary key is compromised or lost.

    • When security breaches or leaks are reported, react promptly by replacing or disabling affected keys and passwords. This proactive response minimizes the potential risks and damage.

    • Periodically review and update your recovery plan. This ensures that the plan remains relevant and effective as your security landscape evolves.

    WARNING

    Remember that a recovery plan is not just another document. Rather, it's a lifeline that helps navigate unexpected challenges. By anticipating potential scenarios and establishing a clear roadmap for action, you fortify your operational security and enhance your readiness to respond effectively to any security incident.

    + + + + \ No newline at end of file diff --git a/guide/security/password-security.html b/guide/security/password-security.html new file mode 100644 index 00000000..c0cdb8d8 --- /dev/null +++ b/guide/security/password-security.html @@ -0,0 +1,33 @@ + + + + + + Password Security | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Password Security

    In the realm of blockchain security, protecting passwords is paramount. To ensure your data and everything it represents remain impervious to unauthorized access, let's delve into the nuances of password security.

    Password Strength

    Likely enough, you may have previously encountered recommendations on how to come up with a strong password. These may entail such advice as minimum password length, addition of special characters, etc. Such recommendations aim to increase the strength of your password that hinges on entropy, i.e. randomness of the password.

    So, what defines a strong password? A strong password is a password with high entropy.

    To calculate the entropy of a password, we may follow the Entropy formula:

    Entropy formula

    LL — Password length; number of symbols in the password.
    SS — Character set; size of the pool of unique possible symbols.
    SLS^L — Number of possible combinations.

    Entropy=log2(SL) Entropy=log_2(S^L)

    The resulting number is the amount of entropy bits in a password. The higher the number, the harder the password is to crack.

    Knowing the entropy value, the amount of attempts required to brute-force a password with said entropy can be derived by using the following formula:

    SL=2Entropy S^L=2^Entropy

    There is no universal answer as to how high the entropy of a password should be. For financial organizations, it is advised to keep the entropy of their passwords in the range from 64 to 127 bits (128 bits or more is generally considered to be an overkill). However, keep in mind that GPUs keep constantly evolving, and the time required for password cracking keeps decreasing over time.

    Following the entropy formula, let us compare the following two examples:

    1. A 16-character password with the character set utilizing only lowercase letters of the modern English alphabet (26 characters) yields approximately 43 sextillion (43102143*10^21) possible combinations.
    $$Entropy=log_2(26^{16})=log_2(43,608,742,899,428,874,059,776)=75.20703...$$
    +
    1. A 16-character password with the character set expanded to 96, including uppercase letters and special symbols, inflates the number of possible combinations to a staggering 52 nonillion (52103052*10^30), improving entropy significantly.
    $$Entropy=log_2(96^{16})=log_2(52,040,292,466,647,269,602,037,015,248,896)=105.35940... $$
    +

    As can be seen, even by only expanding the character set from 26 to 96 symbols, the number of possible combinations that a malicious party would need to bruteforce has expanded by 1.19331091.1933*10^9 times.

    Additionally increasing the length of the password, will grow the number of possible combinations even further, therefore enhancing the entropy—strength—of the password.

    However, instead of wrestling with complexities, we advise using a password manager program—like KeePassXC (for more details, see Adding a Password Manager Program and Configuring KeePassXC)—to generate and securely store your passwords.

    TIP

    Certain websites limit the maximum possible entropy of passwords, i.e., either limit the maximum password length or the set of accepted characters, or both.

    Keep this in mind when using such websites and aim to periodically update your passwords.

    Password Vulnerabilities

    Passwords can fall victim to brute-force attacks, typically executed using powerful GPUs in conjunction with dictionaries or exhaustive iteration through all possibilities. To thwart such attempts, craft a unique password devoid of personal information like birthdays, addresses, phone numbers, or social security numbers. Avoid providing attackers with easily guessable clues.

    So, how hard it is to crack a modern password? It really depends on who you ask.

    With a setup like Kevin Mitnick's cluster setup housing 24 NVIDIA® GeForce RTX 4090's and 6 NVIDIA® GeForce RTX 2080's, all of them running Hashtopolis software, he used to crack passwords that supposed to take a year in mere half a month.

    However, let's now compare it to a single RTX 4090, capable of processing through 300 H/s using NTLM and 200 H/s using bcrypt, as outlined in this tweet.

    As an extension of our previous entropy calculations, let's now examine the following projected cracking times:

    1. There are 31,540,00031,540,000 seconds in a regular non-leap year. Assuming the worst-case scenario with NTLM, at the speed of 300109300*10^9 H/s, it would take a single RTX 4090 approximately 4,608.834,608.83 years to crack a 16-character password with a character set of 26 letters of the modern English alphabet.

    2. If instead of NTLM we use bcrypt, therefore reducing the iteration speed to 200103200*10^3 H/s, while also expanding the character set to 96, including uppercase letters and special symbols, the time to crack soars to about 8,249,887,835,549,662,270.4568,249,887,835,549,662,270.456 years, far surpassing the age of the universe.

    So, simply picking higher entropy raised the time it takes to crack a password to unfathomable numbers. Yes, the process may be sped up by using multiple GPUs, however this method pales in comparison with the XKCD approach.

    It is important to note that an extensive character set isn't always necessary to reach high entropy. It can be obtained by using multi-word passwords, or lengthy sentences in particular. The classic XKCD comic illustrates this concept eloquently.

    WARNING

    Avoid writing your password down anywhere. Store your password recovery phrase securely. If the phrase is too long, you may write it down, ensuring that you can read it out and type it out later. Store the physical copy of the phrase in a secure location and/or container.

    + + + + \ No newline at end of file diff --git a/guide/security/public-key-cryptography.html b/guide/security/public-key-cryptography.html new file mode 100644 index 00000000..b757dafc --- /dev/null +++ b/guide/security/public-key-cryptography.html @@ -0,0 +1,31 @@ + + + + + + Public Key Cryptography | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Public Key Cryptography

    Public key cryptography provides the means for secure communication and data protection, enabling activities such as secure online transactions, encrypted email communications, etc.

    Public key cryptography employs a pair of cryptographic keys—a public key and a private key—to create a highly secure method of transmitting information over online networks.

    It's easy to make a public key from a private key, but the opposite is rather difficult, if not impossible. This keeps things safe. You can freely share your public key without risking your private key, which remains secure.

    Encryption and Signatures

    Public key cryptography allows individuals to send encrypted messages and data that can only be deciphered by the intended recipient possessing their corresponding private key. In other words, the public key functions as a lock, and the private key serves as an actual unique key that unlocks the encrypted data.

    This encryption process not only ensures the privacy and confidentiality of sensitive information but also establishes the authenticity of the sender. By combining the sender's private key with the public key, a digital signature is created. This signature serves as a digital stamp of approval, verifying the sender's identity and the validity of the transferred data. Anyone with your public key can verify that the person who initiated the transaction used your private key.

    Keys on the Client Side

    Since every transaction must be signed on behalf of a peer, every operation requires a private key that is kept secret (hence the name). Therefore, the client program must handle both the storage and secure signing of transactions.

    WARNING

    All clients are different, but iroha binary is the least secure in this regard, as it stores a peer's private key in the multihash format saved to a plain text file that could be overridden with an environment variable.

    This is currently a reference implementation that will not be a part of the production release.

    One needs to register a user on behalf of another already registered user (just like you need to already have a pair of scissors to cut off the tag from a new one). Suppose that we want to register a user on behalf of mad_hatter@wonderland.

    This entails generating a new private key, and sending its public key to the network so that said network can verify that it's indeed the trustworthy mad_hatter@wonderland, and not some impostor (e.g. mad_hatter@wünderbar). In this case, the client application must prompt you, the user, to provide a key pair and verify the authenticity of the transactions: belonging to mad_hatter@wonderland and having a signature derived from the appropriate public key.

    For public key cryptography to work effectively, avoid re-using keys when you need to specify a new key. While there's nothing stopping you from doing that, the public keys are public, which means that if an attacker sees the same public key being used, they will know that the private keys are also identical.

    Even though private keys operate on slightly different principles than passwords, the advice—to make them as random as possible, never store them unencrypted and never share them with anyone under any circumstances—applies.

    + + + + \ No newline at end of file diff --git a/guide/security/security-principles.html b/guide/security/security-principles.html new file mode 100644 index 00000000..cbcc5bd7 --- /dev/null +++ b/guide/security/security-principles.html @@ -0,0 +1,31 @@ + + + + + + Security Principles | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Security Principles

    Organisations and individual users need to work together to ensure secure interactions with Iroha installations. This topic explains the basic principles behind this cooperation.

    General Security Principles

    1. Use a Virtual Private Network (VPN):

      • Whenever accessing sensitive data or resources, especially over public networks, use a VPN to establish a secure connection that safeguards your information.
    2. Use a firewall for network protection:

      • Strengthen home and/or office networks by setting up a firewall that helps to counter unauthorized access and protect the connected devices from viruses and malware.
    3. Secure physical and digital information:

      • Safeguard physical documents containing sensitive information in a secure location, and ensure digital documents are encrypted and stored in password-protected folders.
    4. Keep Regular Data Backups:

      • Always have copies of your important information saved somewhere safe. This way, if you lose your data or something goes wrong, you can quickly get everything back on track. Keep these backups in a different secure place from where you usually keep your data.

    Security Principles for Individual Users

    1. Adopt robust authentication rules:

      • Utilise strong and unique passwords for all accounts.

      • Never reuse passwords.

      • Set up 2FA whenever possible. 2FA improves the overall security by not only requiring a password, but also an additional factor such as an OTP, fingerprint, or a third-party app-based authentication (e.g., Google Authenticator).

      • Avoid using SMS authentication as the second factor. There is no guarantee that malicious software is not monitoring all of your SMS messages. For example, Android applications cannot be limited to only accessing the messages intended specifically for them.

    2. Exercise caution in digital communication:

      • Set up an email client to sign and verify signatures of all the received emails. While it is possible to impersonate the sender's address and even pose as a bank, it is not possible to fake a signature.

      • Disable both HTML messages and loading of external resources from unknown or unverified addresses.

      • Learn about common phishing techniques to recognise and avoid suspicious emails, links, and requests for personal information.

      • Set up an email client to sign and verify signatures of all the received emails. While it is possible to impersonate the sender's address and even pose as a bank, it is not possible to fake a signature.

    3. Safeguard personal information:

      • When communicating with unfamiliar individuals, especially on the phone or online, be careful about sharing private information.

      • Consider independently researching the individuals or organizations you are communicating with to confirm the legitimacy of their identity.

      • Be mindful of the personal information you share on social media platforms, as malicious parties can exploit this information.

    Security Principles for Organisations

    1. Establish clear security policies and procedures:

      • Develop well-defined security policies and protocols for all employees dealing with sensitive data. Thoroughly train employees to adhere to these guidelines, mitigating the risk of negligent actions.

      • Ensure that security policies are accessible to all employees and are regularly reviewed and updated to reflect changing security landscapes.

      • Provide the security policies with examples and scenarios to make them more relatable and actionable for employees.

    2. Cultivate employee awareness:

      • Educate employees about data and operational security measures. Heightened awareness and comprehensive training are pivotal in fortifying organizational security.

      • Encourage employees to report any suspicious activities or security concerns promptly.

    3. Protect physical infrastructure:

      • Restrict physical entry to servers and infrastructure. Set up access controls that only allow authorised personnel to enter restricted areas.

      • Ensure that access control measures are regularly reviewed and updated to align with evolving security needs.

      • Consider implementing biometric access controls for sensitive areas to enhance physical security.

    4. Deploy security monitoring:

      • Enforce a comprehensive security monitoring system that scrutinizes activities and identifies potential security breaches.

      • Implement automated alerts to promptly notify security personnel of any unusual or unauthorized activities.

      • Consider using machine learning algorithms to enhance the system's ability to detect anomalies and potential threats.

      • Employ staff or designate personnel to oversee database security, identify, track and address software vulnerabilities, and conduct regular checks on critical machines for the presence of unauthorized software not included in the approved list.

    5. Conduct recurring security audits:

      • Perform routine security audits to evaluate vulnerabilities and confirm that established security measures align with the commonly-accepted standards and regulations.

      • Consider hiring external security experts for periodic assessments to gain an impartial evaluation of your organization's security condition.

    6. Implement an access control system:

      • Set up a role-based access control system to ensure that employees only have access to the resources and information necessary for their roles.
    7. Embrace Continuous Improvement:

      • Recognize that security is a continuous process. Maintain ongoing assessment of security measures and proactively enhance them to address emerging threats and challenges.

      • Consider establishing a feedback loop that encourages employees to contribute security improvement suggestions, fostering the culture of continuous enhancement.

    + + + + \ No newline at end of file diff --git a/guide/security/storing-cryptographic-keys.html b/guide/security/storing-cryptographic-keys.html new file mode 100644 index 00000000..e3df3fac --- /dev/null +++ b/guide/security/storing-cryptographic-keys.html @@ -0,0 +1,31 @@ + + + + + + Storing Cryptographic Keys | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Storing Cryptographic Keys

    Your sensitive data only remains private if you adopt OPSEC practices to protect the cryptographic keys. Social engineering threats, where someone posing as a figure with authority tries to manipulate you into giving them your private cryptographic key, are real. Always be cautious and avoid sharing your private key, treating it as you would your apartment keys—reserved for trusted individuals only.

    For more information on OPSEC and its best practices, see Operational Security.

    Storing Cryptographic Keys Digitally

    When it comes to protecting cryptographic keys digitally, mainly only two approaches—SSH and GPG—are available. These methods provide layers of security to prevent unauthorized access to your cryptographic keys.

    Many of Iroha 2's architectural decisions have been influenced by the principles of the Secure Shell (SSH) protocol, which is why this section primarily focuses on the SSH approach, offering instructions on how to effectively implement the protocol for storing your cryptographic keys within the Iroha 2 ecosystem.

    Using SSH and SSH Agent

    Secure Shell Protocol (SSH) is a cryptographic network protocol that serves as a virtual gateway, enabling secure access to remote machines via potentially not-so-secure networks by using SSH keys—access credentials. It provides an efficient way to remotely interact with systems without the necessity of physical presence. In this context, SSH offers two primary authentication mechanisms: the conventional password-based approach and the more secure public-private key pair method.

    For more information on SSH, see the related SSH Academy topic.

    To streamline the login process and bypass the need for repetitive input, it is possible to pair the SSH keys with the SSH Agent (ssh-agent)—the assistant program that remembers your SSH keys and/or password for the duration of a session. This setup permits the SSH gateway to effortlessly access the keys whenever it connects to other machines.

    The workflow here is as follows: you have your public key stored on a remote system and keep your private key secure. Whenever you want to access a remote system, the ssh-agent steps in to communicate your public key to the accessed system. The remote system then sends back a challenge that only your private key can properly respond to. Your ssh-agent handles this challenge by using your private key and sends the correct response back to the remote system. If the response matches what the system expected, you're granted access.

    The beauty of the ssh-agent is that it holds onto your private key during your session, so there is no need to keep entering your password or private key passphrase every time you connect to a remote system.

    For more information on the ssh-agent, see the related SSH Academy topic.

    Note

    For a detailed overview of the SSH protocol and the ssh-agent tool, see the following SSH Academy topics:

    Adding a Password Manager Program

    It is recommended to enhance the security of your SSH keys by protecting them with a password, which acts as an additional obstacle in the way of malicious parties aiming to obtain your sensitive information.

    A variety of password managers can be used to store user passwords and SSH keys temporarily. For the sake of clarity, KeePass is used as an example password manager, specifically, the KeePassXC port running on Linux-based operating systems.

    For instructions on how to set up KeePassXC see the Configuring KeePassXC section below.

    KeePassXC:  screen UI

    KeePassXC offers enhanced security, flexibility, and control. It not only stores passwords but also the SSH keys. When used for key storage, this password manager provides the ssh-agent with the stored keys, which are then promptly removed from its memory once the KeePassXC window is closed.

    TIP

    Theoretically, any of the KeePass ports listed on the official website can be utilized for key storage purposes. We recommend any of the following: KeePassX or KeePassXC.

    Configuring KeePassXC

    To configure KeePassXC, perform the following steps:

    1. Launch KeePassXC, then go to Tools > Settings, or select the Gear button from the top UI panel.

    2. In the Application Settings tab that appears, select SSH Agent from the left menu, and then select the Enable SSH Agent integration checkbox.

      Show reference screenshot

      KeePassXC  tab: Enabling SSH Agent

    3. Create a new KeePassXC Database. For instructions, see KeePassXC User Guide > Creating Your First Database.

    4. For every key that you would like to store in the KeePassXC Database you created, perform the following steps:

      • Add a new entry in the database. For instructions, see KeePassXC User Guide > Creating Your First Database.

      • When adding a new entry, attach the file containing the key by doing the following: select Advanced from the left menu, then select Add in the Attachments section, choose the required file in the Select files window that appears.

      • When adding a new entry, select SSH Agent from the left menu, then select the key file you added from the Attachment menu in the Private key section; then select the following checkboxes:

        • Add key to agent when database is opened/unlocked

        • Remove key from agent when database is closed/locked

        • Require user confirmation when this key is used

      • If necessary, make other changes to the entry.

      • When ready, select OK to save the entry.

      Show reference screenshots

      KeePassXC  tab: Adding a private key attachment

      KeePassXC  tab: Adding a private key attachment

    Expected Results
    • Cryptographic and shh keys are stored as entries in a KeePassXC Database that can be accessed while the KeePassXC window is open.

    • Stored cryptographic and ssh keys can be used whenever they are required for authorization.

    • Stored cryptographic and ssh keys are removed from the ssh-agent once the KeePassXC window is closed.

    Note

    Without enabling the Require user confirmation when this key is used option, the ssh-agent may not monitor the process that provided it with a key. In the event that the password manager process is terminated by malware or a system service through a SIGKILL signal, the key is likely to remain in the ssh-agent, as Unix system programs cannot intercept SIGKILL.

    Storing Cryptographic Keys Physically

    For those who seek the highest level of offline security, the option of storing cryptographic keys physically ensures that the keys remain completely disconnected from digital networks, thus minimizing the risk of unauthorized access. Acknowledging the physical option underscores our commitment to catering to diverse security needs.

    Using a Hardware Key

    Our team considers hardware keys to be one of the best safety measures. A hardware key—a compact device that connects via a USB port and has the size of a typical flash drive—only processes security-related events when it is connected to a machine. This allows you to easily disconnect the device in case of a security breach, or simply reconnect it to a different machine whenever it is required.

    However, since there are many brands of hardware keys—each with their unique APIs—it is important to research the market to find the key that best suits your needs.

    So far, our team has internally tested the YubiKey 5C hardware key which proved to have many positive features, including versatile API functionality.

    However, there's a potential drawback to consider. Implementing the HMAC challenge-response authentication and storing a corresponding private key for this response could create a vulnerability. This setup might inadvertently enable attackers to make educated guesses about the information stored within the YubiKey 5C's memory, thereby compromising the overall security.

    Luckily, this vulnerability can be mitigated by adopting an alternative approach to utilizing the YubiKey 5C. The idea is to use YubiKey 5C to securely access a KeePassXC database storing your cryptographic and SSH keys. This method can even be considered beneficial, since it surpasses the security of most passwords and makes it necessary for the malicious party to be in possession of your hardware key in case the KeePassXC database is leaked.

    INFO

    To read more about the method above, see the answer by one of the KeePassXC developers—Janek Bevendorff—to the following StackExchange question:

    Is it reasonable to use KeePassXC with YubiKey?

    Using a Mnemonic Phrase

    Alternatively, you can memorize a private key as a series of words, known as a mnemonic phrase. This method, used in many wallets, requires remembering around 25 specific words. Most password managers, including the previously discussed KeePassXC, offer mnemonic passphrase generation.

    + + + + \ No newline at end of file diff --git a/guide/support.html b/guide/support.html new file mode 100644 index 00000000..c2b3b322 --- /dev/null +++ b/guide/support.html @@ -0,0 +1,31 @@ + + + + + + Receive support | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Receive support

    From time to time, you may have questions about Iroha that you would like to discuss in detail with others. There are three ways to quickly get in touch with our community: Telegram, Discord, and GitHub.

    A large part of the community currently uses Telegram for communication. The Hyperledger part of the team prefers Discord, with two dedicated channels: iroha and iroha-2-contributors. The Discord and Telegram channels are synchronized, so users of both media see your messages.

    Finally, you can create a GitHub issue, whether it's a request to update documentation, a suggestion for the core team, or a bug you have found.

    + + + + \ No newline at end of file diff --git a/guide/troubleshooting/configuration-issues.html b/guide/troubleshooting/configuration-issues.html new file mode 100644 index 00000000..e89e696e --- /dev/null +++ b/guide/troubleshooting/configuration-issues.html @@ -0,0 +1,31 @@ + + + + + + Troubleshooting Configuration Issues | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Troubleshooting Configuration Issues

    This section offers troubleshooting tips for issues with Iroha 2 configuration. Make sure you checked the keys first, as it is the most common source of issues in Iroha.

    If the issue you are experiencing is not described here, contact us via Telegram.

    Outdated genesis on a Docker-compose setup

    When you are using the Docker-compose version of Iroha, you might encounter the issue of one of the peer containers failing with the Failed to deserialize raw genesis block error. This happens if there is a mismatch between Iroha versions, meaning an Iroha peer cannot be initialized with the given genesis file.

    If one of the peers is failing and it's been a while since you pulled the Iroha code for the first time, it's safe to assume the outdated genesis file is the cause. Here is how you can make sure Iroha is working incorrectly for exactly this reason:

    1. Use docker ps to check the current containers. Depending on the version, you will see either hyperledger/iroha2:dev or hyperledger/iroha2:lts containers. Check the number of Iroha peer containers in the docker ps output. By default, there are 4 peers configured in docker-compose.yml for Iroha, although you may have changed that value. You will see that the first container that should have been running Iroha just exited with an error, while three other containers remain active.

    2. Check the logs and look for the Failed to deserialize raw genesis block error. If you started your Iroha in daemon mode with docker compose up -d, use docker compose logs command.

    The way to troubleshoot such an issue depends on the use of Iroha.

    If this is a basic demo and you don't need the peer data to be restored, you can simply reset the genesis file to its latest state. To do this, use the git checkout configs/peer/genesis.json command.

    If you need to restore the Iroha instance data, do the following:

    1. Connect the second Iroha peer that will copy the data from the first (failed) peer.
    2. Wait for the new peer to synchronize the data with the first peer.
    3. Leave the new peer active.
    4. Update the genesis file of the first peer.

    INFO

    The features needed to monitor the copying progress between peers and a migration tool to update the genesis file are to be implemented in future releases.

    Multihash Format of Private and Public Keys

    If you look at the client configuration, you will notice that the keys there are given in multi-hash format.

    If you've never worked with multi-hash before, it is natural to assume that the right-hand-side is not a hexadecimal representation of the key bytes (two symbols per byte), but rather the bytes encoded as ASCII (or UTF-8), and call from_hex on the string literal in both the public_key and private_key instantiation.

    It is also natural to assume that calling PrivateKey::try_from_str on the string literal would yield only the correct key. So if you get the number of bits in the key wrong, e.g. 32 bytes vs 64, that it would raise an error message.

    Both of these assumptions are wrong. Unfortunately, the error messages don't help in de-bugging this particular kind of failure.

    How to fix: use hex_literal. This will also turn an ugly string of characters into a nice small table of obviously hexadecimal numbers.

    WARNING

    Even the try_from_str implementation cannot verify if a given string is a valid PrivateKey and warn you if it isn't.

    It will catch some obvious errors, e.g. if the string contains an invalid symbol. However, since we aim to support many key formats, it can't do much else. It cannot tell if the key is the correct private key for the given account either, unless you submit an instruction.

    These sorts of subtle mistakes can be avoided, for example, by deserialising directly from string literals, or by generating a fresh key-pair in places where it makes sense.

    + + + + \ No newline at end of file diff --git a/guide/troubleshooting/deployment-issues.html b/guide/troubleshooting/deployment-issues.html new file mode 100644 index 00000000..8fe7b7ab --- /dev/null +++ b/guide/troubleshooting/deployment-issues.html @@ -0,0 +1,31 @@ + + + + + + Troubleshooting Deployment Issues | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Troubleshooting Deployment Issues

    This section offers troubleshooting tips for issues with Iroha 2 deployment. If the issue you are experiencing is not described here, contact us via Telegram.

    Docker

    TBD

    Kubernetes

    TBD

    + + + + \ No newline at end of file diff --git a/guide/troubleshooting/installation-issues.html b/guide/troubleshooting/installation-issues.html new file mode 100644 index 00000000..d3ae92a2 --- /dev/null +++ b/guide/troubleshooting/installation-issues.html @@ -0,0 +1,39 @@ + + + + + + Troubleshooting Installation Issues | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Troubleshooting Installation Issues

    This section offers troubleshooting tips for issues with Iroha 2 installation. If the issue you are experiencing is not described here, contact us via Telegram.

    Troubleshooting Rust Toolchain

    Sometimes, things don’t go as planned. Especially if you had rust on your system a while ago, but didn’t upgrade. A similar problem can occur in Python: XKCD has a famous example of what that might look like:

    Untitled

    Check Rust version

    In the interest of preserving both your and our sanity, make sure that you have the right version of cargo paired with the right version of rustc (1.57 and 1.57) respectively. To show the versions, do

    bash
    $ cargo -V
    +$ cargo 1.60.0 (d1fd9fe 2022-03-01)

    and then

    bash
    $ rustc --version
    +$ rustc 1.60.0 (7737e0b5c 2022-04-04)

    If you have higher versions, you're fine. If you have lower versions, you can run the following command to update it:

    bash
    $ rustup toolchain update stable

    Check installation location

    If you get lower version numbers and you updated the toolchain and it didn’t work… let’s just say it’s a common problem, but it doesn’t have a common solution.

    Firstly, you should establish where the version that you want to use is installed:

    bash
    $ rustup which rustc
    +$ rustup which cargo

    User installations of the toolchains are usually in ~/.rustup/toolchains/stable-*/bin/. If that is the case, you should be able to run

    bash
    $ rustup toolchain update stable

    and that should fix your problems.

    Check the default Rust version

    Another option is that you have the up-to-date stable toolchain, but it is not set as the default. Run:

    bash
    $ rustup default stable

    This can happen if you installed a nightly version, or set a specific Rust version, but forgot to un-set it.

    Check if there are other Rust versions

    Continuing down the troubleshooting rabbit-hole, we could have shell aliases:

    bash
    $ type rustc
    +$ type cargo

    If these point to locations other than the one you saw when running rustup which *, then you have a problem. Note that it’s not enough to just

    bash
    $ alias rustc "~/.rustup/toolchains/stable-*/bin/rustc"
    +$ alias cargo "~/.rustup/toolchains/stable-*/bin/cargo"

    because there is an internal logic that could break, regardless of how you re-arrange your shell aliases.

    The simplest solution would be to remove the versions that you don’t use.

    It’s easier said than done, however, since it entails tracking all the versions of rustup installed and available to you. Usually, there are only two: the system package manager version and the one that got installed into the standard location in your home folder when you ran the command in the beginning of this tutorial. For the former, consult your (Linux) distribution’s manual, (apt remove rust). For the latter, run:

    bash
    $ rustup toolchain list

    And then, for every <toolchain> (without the angle brackets of course):

    bash
    $ rustup remove <toolchain>

    After that, make sure that

    bash
    $ cargo --help

    results in a command-not-found error, i.e. that you have no active Rust toolchain installed. Then, run:

    bash
    $ rustup toolchain install stable

    Troubleshooting Python toolchain

    When you install the Python Wheel package using pip on the "client setup" step, you may encounter an error like: "iroha_python-*.whl is not a supported wheel on this platform".

    This error means that pip is outdated, so you need to update it. First of all, it is recommended to check your OS for updates and perform a system upgrade.

    If this doesn't work, you can try updating pip for your user directory.

    python -m pip install --upgrade pip

    Make sure that pip that is installed in your home directory. To do this, run whereis pip and check if /home/username/.local/bin/pip is among the paths. If not, update your shell's PATH variable.

    If the issue persists, please contact us and report the outputs.

    python --version
    +python3 --version
    +pip --version
    +pip3 --version
    + + + + \ No newline at end of file diff --git a/guide/troubleshooting/integration-issues.html b/guide/troubleshooting/integration-issues.html new file mode 100644 index 00000000..b07be099 --- /dev/null +++ b/guide/troubleshooting/integration-issues.html @@ -0,0 +1,31 @@ + + + + + + Troubleshooting Integration Issues | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/guide/troubleshooting/overview.html b/guide/troubleshooting/overview.html new file mode 100644 index 00000000..6c89b0b8 --- /dev/null +++ b/guide/troubleshooting/overview.html @@ -0,0 +1,31 @@ + + + + + + Troubleshooting | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Troubleshooting

    This section is intended to help if you encounter issues while working with Iroha. If something goes wrong, please check the keys first. If that doesn't help, check the troubleshooting instructions for each stage:

    If the issue you are experiencing is not described here, contact us via Telegram.

    Check the keys

    Most issues arise as a result of unmatched keys. This is why we recommend to follow this rule: If something goes wrong, check the keys first.

    Here's a quick explanation: It is not possible to differentiate the error messages that arise when peers' keys do not match the keys in the array of trusted peers, because it would expose the peers' public key. As such, if you have Helm charts or K8s deployed with keys defined via the environment variables, you should check for Key definitions.

    If in doubt, generate a new pair of keys.

    + + + + \ No newline at end of file diff --git a/hashmap.json b/hashmap.json new file mode 100644 index 00000000..2dc6908f --- /dev/null +++ b/hashmap.json @@ -0,0 +1 @@ +{"guide_configure_peer-management.md":"DhMQe9u_","guide_blockchain_domains.md":"D61leQdc","guide_blockchain_events.md":"BcgNDCpt","guide_blockchain_expressions.md":"CxFP2yxO","guide_blockchain_filters.md":"4e4lTrE8","guide_blockchain_how-iroha-works.md":"DCXmnzDS","guide_blockchain_consensus.md":"C3NI_nji","guide_blockchain_accounts.md":"BXCA0c6W","guide_blockchain_world.md":"1jfOivt1","guide_blockchain_data-model.md":"UR0FZlta","documenting_snippets.md":"C4z1KoPs","guide_blockchain_assets.md":"C7z8RvOt","guide_blockchain_metadata.md":"Cmsp_0-E","guide_configure_metadata-and-store-assets.md":"D9AcB5Vs","guide_get-started_tutorials.md":"Czean8cR","guide_advanced_running-iroha-on-bare-metal.md":"B38eu74b","guide_advanced_metrics.md":"U5tv47Y-","guide_troubleshooting_integration-issues.md":"Drm7WPT6","guide_blockchain_transactions.md":"BW0UeSYo","guide_get-started_operate-iroha-2-via-cli.md":"D3UDHgAT","guide_blockchain_permissions.md":"B5iiNWDU","guide_security_security-principles.md":"DIghKKgf","guide_iroha-2.md":"Bj0eOTQ9","reference_compatibility-matrix.md":"PV7SJ-rB","guide_advanced_hot-reload.md":"DCdI8k4h","guide_troubleshooting_installation-issues.md":"D56PejpD","guide_configure_configuration-types.md":"D9Ifeq5f","guide_blockchain_instructions.md":"B0jSwXfH","guide_blockchain_wasm.md":"qnYECiWT","guide_configure_sample-configuration.md":"B3LcukXt","guide_troubleshooting_configuration-issues.md":"FQp4rSwT","guide_support.md":"BVe2ZRzv","guide_security_password-security.md":"BYbpZhLC","guide_get-started_rust.md":"DD6cfJYD","guide_troubleshooting_deployment-issues.md":"2-b_HLFn","guide_configure_keys-for-network-deployment.md":"Du4srmTx","guide_security_index.md":"CyMsOmKt","guide_security_operational-security.md":"DtcsL8SB","guide_security_public-key-cryptography.md":"CKYeyqvW","guide_security_storing-cryptographic-keys.md":"CSvApCcZ","guide_get-started_index.md":"CX985dei","reference_permissions.md":"BVVaIEI3","reference_queries.md":"BS7G0mCP","reference_torii-endpoints.md":"C7pQt57Z","guide_configure_genesis.md":"CufogGXy","guide_get-started_kotlin-java.md":"BJnusMRj","guide_get-started_install-iroha-2.md":"BAHP3axq","guide_configure_modes.md":"DEYMQiV1","guide_blockchain_triggers.md":"BTamJcLJ","guide_security_generating-cryptographic-keys.md":"yXKGjTVS","guide_configure_overview.md":"D6DO6mJ9","guide_get-started_javascript.md":"yo9AwBf0","guide_reports_csd-rtgs.md":"DeBNoVPL","guide_configure_peer-configuration.md":"PLGB4drn","reference_ffi.md":"CSR1g8Hj","guide_configure_client-configuration.md":"22mv4OvP","index.md":"CQwI35wr","guide_get-started_python.md":"DD-VCkqN","reference_glossary.md":"Bvar2yPY","reference_naming.md":"Braqk8fU","guide_get-started_launch-iroha-2.md":"BYWYF67e","reference_data-model-schema.md":"Ncq8wG4o","guide_troubleshooting_overview.md":"43cANCE4","guide_blockchain_queries.md":"CKZBqEyL","reference_instructions.md":"BQavKnbm"} diff --git a/icon-192.png b/icon-192.png new file mode 100644 index 00000000..914b582c Binary files /dev/null and b/icon-192.png differ diff --git a/icon-512.png b/icon-512.png new file mode 100644 index 00000000..9763292b Binary files /dev/null and b/icon-512.png differ diff --git a/icon.svg b/icon.svg new file mode 100644 index 00000000..56115da8 --- /dev/null +++ b/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 00000000..b265d0df --- /dev/null +++ b/index.html @@ -0,0 +1,31 @@ + + + + + + Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/manifest.webmanifest b/manifest.webmanifest new file mode 100644 index 00000000..985a7aa3 --- /dev/null +++ b/manifest.webmanifest @@ -0,0 +1,9 @@ +{ + "name": "Iroha 2 Documentation", + "start_url": "https://hyperledger.github.io/iroha-2-docs/", + "display": "standalone", + "icons": [ + { "src": "icon-192.png", "type": "image/png", "sizes": "192x192" }, + { "src": "icon-512.png", "type": "image/png", "sizes": "512x512" } + ] +} diff --git a/reference/compatibility-matrix.html b/reference/compatibility-matrix.html new file mode 100644 index 00000000..9f22511d --- /dev/null +++ b/reference/compatibility-matrix.html @@ -0,0 +1,31 @@ + + + + + + Compatibility Matrix | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Compatibility Matrix

    In our continuous efforts to provide clear documentation and to ensure seamless compatibility across multiple SDKs, we present the SDK Compatibility Matrix. This matrix provides an instantaneous overview of how different stories, sourced from TestOps API, fare across varying SDKs.

    The matrix consists of:

    • Stories: Represented in the first column of the matrix, these are directly fetched from the TestOps API.
    • SDKs: Each subsequent column represents an SDK, such as "Java/Kotlin", "JavaScript", "Swift", etc.
    • Status Symbols: The status of each story for an SDK is denoted with:
      • indicating the story passed.
      • indicating the story failed to pass.
      • indicating the data is missing.
    Loading data...

    INFO

    The data for this matrix is retrieved dynamically from our backend service, balancing the latest information with a swift response for documentation readers.

    + + + + \ No newline at end of file diff --git a/reference/data-model-schema.html b/reference/data-model-schema.html new file mode 100644 index 00000000..1c371458 --- /dev/null +++ b/reference/data-model-schema.html @@ -0,0 +1,31 @@ + + + + + + Data Model Schema | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Data Model Schema

    TODO: explain what this page contains

    Account

    Type: Struct

    Declarations:

    Field nameField value
    idAccountId
    assetsSortedMap<AssetId, Asset>
    signatoriesSortedVec<PublicKey>
    signature_check_conditionSignatureCheckCondition
    metadataMetadata

    AccountEvent

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    AssetAssetEvent0
    CreatedAccount1
    DeletedAccountId2
    AuthenticationAddedAccountId3
    AuthenticationRemovedAccountId4
    PermissionAddedAccountPermissionChanged5
    PermissionRemovedAccountPermissionChanged6
    RoleRevokedAccountRoleChanged7
    RoleGrantedAccountRoleChanged8
    MetadataInsertedMetadataChanged<AccountId>9
    MetadataRemovedMetadataChanged<AccountId>10

    AccountEventFilter

    Type: Struct

    Declarations:

    Field nameField value
    id_matcherOption<AccountId>
    event_setAccountEventSet

    AccountEventSet

    Type: Bitmap

    Repr: u32

    Masks:

    Field nameField value
    AnyAsset0x1
    Created0x2
    Deleted0x4
    AuthenticationAdded0x8
    AuthenticationRemoved0x10
    PermissionAdded0x20
    PermissionRemoved0x40
    RoleRevoked0x80
    RoleGranted0x100
    MetadataInserted0x200
    MetadataRemoved0x400

    AccountId

    Type: Struct

    Declarations:

    Field nameField value
    domain_idDomainId
    nameName

    AccountMintBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    PublicKeyMint<PublicKey, Account>0
    SignatureCheckConditionMint<SignatureCheckCondition, Account>1

    AccountPermissionChanged

    Type: Struct

    Declarations:

    Field nameField value
    account_idAccountId
    permission_idName

    AccountRoleChanged

    Type: Struct

    Declarations:

    Field nameField value
    account_idAccountId
    role_idRoleId

    Action

    Type: Struct

    Declarations:

    Field nameField value
    executableExecutable
    repeatsRepeats
    authorityAccountId
    filterTriggeringEventFilterBox
    metadataMetadata

    Algorithm

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    Ed255190
    Secp256k11
    BlsNormal2
    BlsSmall3

    Array<u16, 8>

    Type: Array

    Length: 8

    Value: u16

    Array<u8, 32>

    Type: Array

    Length: 32

    Value: u8

    Array<u8, 4>

    Type: Array

    Length: 4

    Value: u8

    Asset

    Type: Struct

    Declarations:

    Field nameField value
    idAssetId
    valueAssetValue

    AssetChanged

    Type: Struct

    Declarations:

    Field nameField value
    asset_idAssetId
    amountAssetValue

    AssetDefinition

    Type: Struct

    Declarations:

    Field nameField value
    idAssetDefinitionId
    value_typeAssetValueType
    mintableMintable
    logoOption<IpfsPath>
    metadataMetadata
    owned_byAccountId

    AssetDefinitionEvent

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    CreatedAssetDefinition0
    MintabilityChangedAssetDefinitionId1
    OwnerChangedAssetDefinitionOwnerChanged2
    DeletedAssetDefinitionId3
    MetadataInsertedMetadataChanged<AssetDefinitionId>4
    MetadataRemovedMetadataChanged<AssetDefinitionId>5
    TotalQuantityChangedAssetDefinitionTotalQuantityChanged6

    AssetDefinitionEventFilter

    Type: Struct

    Declarations:

    Field nameField value
    id_matcherOption<AssetDefinitionId>
    event_setAssetDefinitionEventSet

    AssetDefinitionEventSet

    Type: Bitmap

    Repr: u32

    Masks:

    Field nameField value
    Created0x1
    MintabilityChanged0x2
    OwnerChanged0x4
    Deleted0x8
    MetadataInserted0x10
    MetadataRemoved0x20
    TotalQuantityChanged0x40

    AssetDefinitionId

    Type: Struct

    Declarations:

    Field nameField value
    domain_idDomainId
    nameName

    AssetDefinitionOwnerChanged

    Type: Struct

    Declarations:

    Field nameField value
    asset_definition_idAssetDefinitionId
    new_ownerAccountId

    AssetDefinitionTotalQuantityChanged

    Type: Struct

    Declarations:

    Field nameField value
    asset_definition_idAssetDefinitionId
    total_amountNumeric

    AssetEvent

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    CreatedAsset0
    DeletedAssetId1
    AddedAssetChanged2
    RemovedAssetChanged3
    MetadataInsertedMetadataChanged<AssetId>4
    MetadataRemovedMetadataChanged<AssetId>5

    AssetEventFilter

    Type: Struct

    Declarations:

    Field nameField value
    id_matcherOption<AssetId>
    event_setAssetEventSet

    AssetEventSet

    Type: Bitmap

    Repr: u32

    Masks:

    Field nameField value
    Created0x1
    Deleted0x2
    Added0x4
    Removed0x8
    MetadataInserted0x10
    MetadataRemoved0x20

    AssetId

    Type: Struct

    Declarations:

    Field nameField value
    definition_idAssetDefinitionId
    account_idAccountId

    AssetTransferBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    NumericTransfer<Asset, Numeric, Account>0
    StoreTransfer<Asset, Metadata, Account>1

    AssetValue

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    NumericNumeric0
    StoreMetadata1

    AssetValueType

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    NumericNumericSpec0
    Store1

    AtIndex

    Type: Struct

    Declarations:

    Field nameField value
    indexu32
    predicateQueryOutputPredicate

    BatchedResponse<QueryOutputBox>

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    V1BatchedResponseV1<QueryOutputBox>1

    BatchedResponseV1<QueryOutputBox>

    Type: Struct

    Declarations:

    Field nameField value
    batchQueryOutputBox
    cursorForwardCursor

    BlockEvent

    Type: Struct

    Declarations:

    Field nameField value
    headerBlockHeader
    hashHashOf<SignedBlock>
    statusBlockStatus

    BlockEventFilter

    Type: Struct

    Declarations:

    Field nameField value
    heightOption<u64>
    statusOption<BlockStatus>

    BlockHeader

    Type: Struct

    Declarations:

    Field nameField value
    heightu64
    previous_block_hashOption<HashOf<SignedBlock>>
    transactions_hashOption<HashOf<MerkleTree<SignedTransaction>>>
    timestamp_msu64
    view_change_indexu64
    consensus_estimation_msu64

    BlockMessage

    Type: Alias

    To: SignedBlock

    BlockPayload

    Type: Struct

    Declarations:

    Field nameField value
    headerBlockHeader
    commit_topologyVec<PeerId>
    transactionsVec<TransactionValue>
    event_recommendationsVec<EventBox>

    BlockRejectionReason

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    ConsensusBlockRejection0

    BlockStatus

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    Approved0
    RejectedBlockRejectionReason1
    Committed2
    Applied3

    BlockSubscriptionRequest

    Type: Alias

    To: NonZero<u64>

    Burn<Numeric, Asset>

    Type: Struct

    Declarations:

    Field nameField value
    objectNumeric
    destination_idAssetId

    Burn<PublicKey, Account>

    Type: Struct

    Declarations:

    Field nameField value
    objectPublicKey
    destination_idAccountId

    Burn<u32, Trigger>

    Type: Struct

    Declarations:

    Field nameField value
    objectu32
    destination_idTriggerId

    BurnBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    AccountPublicKeyBurn<PublicKey, Account>0
    AssetBurn<Numeric, Asset>1
    TriggerRepetitionsBurn<u32, Trigger>2

    ChainId

    Type: Alias

    To: String

    Compact<u128>

    Type: Int

    Kind: Compact

    Compact<u32>

    Type: Int

    Kind: Compact

    ConfigurationEvent

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    ChangedParameterId0
    CreatedParameterId1
    DeletedParameterId2

    ConfigurationEventFilter

    Type: Struct

    Declarations:

    Field nameField value
    id_matcherOption<ParameterId>
    event_setConfigurationEventSet

    ConfigurationEventSet

    Type: Bitmap

    Repr: u32

    Masks:

    Field nameField value
    Changed0x1
    Created0x2
    Deleted0x4

    Container

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    AnyQueryOutputPredicate0
    AllQueryOutputPredicate1
    AtIndexAtIndex2

    DataEvent

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    PeerPeerEvent0
    DomainDomainEvent1
    TriggerTriggerEvent2
    RoleRoleEvent3
    PermissionTokenPermissionTokenSchemaUpdateEvent4
    ConfigurationConfigurationEvent5
    ExecutorExecutorEvent6

    DataEventFilter

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    Any0
    PeerPeerEventFilter1
    DomainDomainEventFilter2
    AccountAccountEventFilter3
    AssetAssetEventFilter4
    AssetDefinitionAssetDefinitionEventFilter5
    TriggerTriggerEventFilter6
    RoleRoleEventFilter7
    PermissionTokenSchemaUpdate8
    ConfigurationConfigurationEventFilter9
    ExecutorExecutorEventFilter10

    Domain

    Type: Struct

    Declarations:

    Field nameField value
    idDomainId
    accountsSortedMap<AccountId, Account>
    asset_definitionsSortedMap<AssetDefinitionId, AssetDefinition>
    asset_total_quantitiesSortedMap<AssetDefinitionId, Numeric>
    logoOption<IpfsPath>
    metadataMetadata
    owned_byAccountId

    DomainEvent

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    AccountAccountEvent0
    AssetDefinitionAssetDefinitionEvent1
    CreatedDomain2
    DeletedDomainId3
    MetadataInsertedMetadataChanged<DomainId>4
    MetadataRemovedMetadataChanged<DomainId>5
    OwnerChangedDomainOwnerChanged6

    DomainEventFilter

    Type: Struct

    Declarations:

    Field nameField value
    id_matcherOption<DomainId>
    event_setDomainEventSet

    DomainEventSet

    Type: Bitmap

    Repr: u32

    Masks:

    Field nameField value
    AnyAccount0x1
    AnyAssetDefinition0x2
    Created0x4
    Deleted0x8
    MetadataInserted0x10
    MetadataRemoved0x20
    OwnerChanged0x40

    DomainId

    Type: Struct

    Declarations:

    Field nameField value
    nameName

    DomainOwnerChanged

    Type: Struct

    Declarations:

    Field nameField value
    domain_idDomainId
    new_ownerAccountId

    Duration

    Type: Tuple

    Values: (u64, u32)

    EventBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    PipelinePipelineEventBox0
    DataDataEvent1
    TimeTimeEvent2
    ExecuteTriggerExecuteTriggerEvent3
    TriggerCompletedTriggerCompletedEvent4

    EventFilterBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    PipelinePipelineEventFilterBox0
    DataDataEventFilter1
    TimeTimeEventFilter2
    ExecuteTriggerExecuteTriggerEventFilter3
    TriggerCompletedTriggerCompletedEventFilter4

    EventMessage

    Type: Alias

    To: EventBox

    EventSubscriptionRequest

    Type: Alias

    To: Vec<EventFilterBox>

    Executable

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    InstructionsVec<InstructionBox>0
    WasmWasmSmartContract1

    ExecuteTrigger

    Type: Struct

    Declarations:

    Field nameField value
    trigger_idTriggerId

    ExecuteTriggerEvent

    Type: Struct

    Declarations:

    Field nameField value
    trigger_idTriggerId
    authorityAccountId

    ExecuteTriggerEventFilter

    Type: Struct

    Declarations:

    Field nameField value
    trigger_idOption<TriggerId>
    authorityOption<AccountId>

    ExecutionTime

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    PreCommit0
    ScheduleSchedule1

    Executor

    Type: Struct

    Declarations:

    Field nameField value
    wasmWasmSmartContract

    ExecutorEvent

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    Upgraded0

    ExecutorEventFilter

    Type: Struct

    Declarations:

    Field nameField value
    event_setExecutorEventSet

    ExecutorEventSet

    Type: Bitmap

    Repr: u32

    Masks:

    Field nameField value
    Upgraded0x1

    Fail

    Type: Struct

    Declarations:

    Field nameField value
    messageString

    FindAccountById

    Type: Struct

    Declarations:

    Field nameField value
    idAccountId

    FindAccountKeyValueByIdAndKey

    Type: Struct

    Declarations:

    Field nameField value
    idAccountId
    keyName

    FindAccountsByDomainId

    Type: Struct

    Declarations:

    Field nameField value
    domain_idDomainId

    FindAccountsByName

    Type: Struct

    Declarations:

    Field nameField value
    nameName

    FindAccountsWithAsset

    Type: Struct

    Declarations:

    Field nameField value
    asset_definition_idAssetDefinitionId

    FindAllAccounts

    Type: Zero-Size Type (unit type, null type)

    FindAllActiveTriggerIds

    Type: Zero-Size Type (unit type, null type)

    FindAllAssets

    Type: Zero-Size Type (unit type, null type)

    FindAllAssetsDefinitions

    Type: Zero-Size Type (unit type, null type)

    FindAllBlockHeaders

    Type: Zero-Size Type (unit type, null type)

    FindAllBlocks

    Type: Zero-Size Type (unit type, null type)

    FindAllDomains

    Type: Zero-Size Type (unit type, null type)

    FindAllParameters

    Type: Zero-Size Type (unit type, null type)

    FindAllPeers

    Type: Zero-Size Type (unit type, null type)

    FindAllRoleIds

    Type: Zero-Size Type (unit type, null type)

    FindAllRoles

    Type: Zero-Size Type (unit type, null type)

    FindAllTransactions

    Type: Zero-Size Type (unit type, null type)

    FindAssetById

    Type: Struct

    Declarations:

    Field nameField value
    idAssetId

    FindAssetDefinitionById

    Type: Struct

    Declarations:

    Field nameField value
    idAssetDefinitionId

    FindAssetDefinitionKeyValueByIdAndKey

    Type: Struct

    Declarations:

    Field nameField value
    idAssetDefinitionId
    keyName

    FindAssetKeyValueByIdAndKey

    Type: Struct

    Declarations:

    Field nameField value
    idAssetId
    keyName

    FindAssetQuantityById

    Type: Struct

    Declarations:

    Field nameField value
    idAssetId

    FindAssetsByAccountId

    Type: Struct

    Declarations:

    Field nameField value
    account_idAccountId

    FindAssetsByAssetDefinitionId

    Type: Struct

    Declarations:

    Field nameField value
    asset_definition_idAssetDefinitionId

    FindAssetsByDomainId

    Type: Struct

    Declarations:

    Field nameField value
    domain_idDomainId

    FindAssetsByDomainIdAndAssetDefinitionId

    Type: Struct

    Declarations:

    Field nameField value
    domain_idDomainId
    asset_definition_idAssetDefinitionId

    FindAssetsByName

    Type: Struct

    Declarations:

    Field nameField value
    nameName

    FindBlockHeaderByHash

    Type: Struct

    Declarations:

    Field nameField value
    hashHashOf<SignedBlock>

    FindDomainById

    Type: Struct

    Declarations:

    Field nameField value
    idDomainId

    FindDomainKeyValueByIdAndKey

    Type: Struct

    Declarations:

    Field nameField value
    idDomainId
    keyName

    FindError

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    AssetAssetId0
    AssetDefinitionAssetDefinitionId1
    AccountAccountId2
    DomainDomainId3
    MetadataKeyName4
    BlockHashOf<SignedBlock>5
    TransactionHashOf<SignedTransaction>6
    PeerPeerId7
    TriggerTriggerId8
    RoleRoleId9
    PermissionTokenName10
    ParameterParameterId11
    PublicKeyPublicKey12

    FindPermissionTokenSchema

    Type: Zero-Size Type (unit type, null type)

    FindPermissionTokensByAccountId

    Type: Struct

    Declarations:

    Field nameField value
    idAccountId

    FindRoleByRoleId

    Type: Struct

    Declarations:

    Field nameField value
    idRoleId

    FindRolesByAccountId

    Type: Struct

    Declarations:

    Field nameField value
    idAccountId

    FindTotalAssetQuantityByAssetDefinitionId

    Type: Struct

    Declarations:

    Field nameField value
    idAssetDefinitionId

    FindTransactionByHash

    Type: Struct

    Declarations:

    Field nameField value
    hashHashOf<SignedTransaction>

    FindTransactionsByAccountId

    Type: Struct

    Declarations:

    Field nameField value
    account_idAccountId

    FindTriggerById

    Type: Struct

    Declarations:

    Field nameField value
    idTriggerId

    FindTriggerKeyValueByIdAndKey

    Type: Struct

    Declarations:

    Field nameField value
    idTriggerId
    keyName

    FindTriggersByDomainId

    Type: Struct

    Declarations:

    Field nameField value
    domain_idDomainId

    ForwardCursor

    Type: Struct

    Declarations:

    Field nameField value
    query_idOption<String>
    cursorOption<NonZero<u64>>

    GenericPredicateBox<QueryOutputPredicate>

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    AndNonTrivial<GenericPredicateBox<QueryOutputPredicate>>0
    OrNonTrivial<GenericPredicateBox<QueryOutputPredicate>>1
    NotGenericPredicateBox<QueryOutputPredicate>2
    RawQueryOutputPredicate3

    Grant<PermissionToken, Account>

    Type: Struct

    Declarations:

    Field nameField value
    objectPermissionToken
    destination_idAccountId

    Grant<PermissionToken, Role>

    Type: Struct

    Declarations:

    Field nameField value
    objectPermissionToken
    destination_idRoleId

    Grant<RoleId, Account>

    Type: Struct

    Declarations:

    Field nameField value
    objectRoleId
    destination_idAccountId

    GrantBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    PermissionTokenGrant<PermissionToken, Account>0
    RoleGrant<RoleId, Account>1
    RolePermissionTokenGrant<PermissionToken, Role>2

    Hash

    Type: Alias

    To: Array<u8, 32>

    HashOf<MerkleTree<SignedTransaction>>

    Type: Alias

    To: Hash

    HashOf<SignedBlock>

    Type: Alias

    To: Hash

    HashOf<SignedTransaction>

    Type: Alias

    To: Hash

    IdBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    DomainIdDomainId0
    AccountIdAccountId1
    AssetDefinitionIdAssetDefinitionId2
    AssetIdAssetId3
    PeerIdPeerId4
    TriggerIdTriggerId5
    RoleIdRoleId6
    PermissionTokenIdName7
    ParameterIdParameterId8

    IdentifiableBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    NewDomainNewDomain0
    NewAccountNewAccount1
    NewAssetDefinitionNewAssetDefinition2
    NewRoleNewRole3
    PeerPeer4
    DomainDomain5
    AccountAccount6
    AssetDefinitionAssetDefinition7
    AssetAsset8
    TriggerTrigger9
    RoleRole10
    ParameterParameter11

    InstructionBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    RegisterRegisterBox0
    UnregisterUnregisterBox1
    MintMintBox2
    BurnBurnBox3
    TransferTransferBox4
    SetKeyValueSetKeyValueBox5
    RemoveKeyValueRemoveKeyValueBox6
    GrantGrantBox7
    RevokeRevokeBox8
    ExecuteTriggerExecuteTrigger9
    SetParameterSetParameter10
    NewParameterNewParameter11
    UpgradeUpgrade12
    LogLog13
    FailFail14

    InstructionEvaluationError

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    UnsupportedInstructionType0
    PermissionParameterString1
    TypeTypeError2

    InstructionExecutionError

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    EvaluateInstructionEvaluationError0
    QueryQueryExecutionFail1
    ConversionString2
    FindFindError3
    RepetitionRepetitionError4
    MintabilityMintabilityError5
    MathMathError6
    MetadataMetadataError7
    FailString8
    InvalidParameterInvalidParameterError9
    InvariantViolationString10

    InstructionExecutionFail

    Type: Struct

    Declarations:

    Field nameField value
    instructionInstructionBox
    reasonString

    InstructionType

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    Register0
    Unregister1
    Mint2
    Burn3
    Transfer4
    SetKeyValue5
    RemoveKeyValue6
    Grant7
    Revoke8
    ExecuteTrigger9
    SetParameter10
    NewParameter11
    Upgrade12
    Log13
    Fail14

    InvalidParameterError

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    WasmString0
    NameLength1

    IpfsPath

    Type: Alias

    To: String

    Ipv4Addr

    Type: Alias

    To: Array<u8, 4>

    Ipv6Addr

    Type: Alias

    To: Array<u16, 8>

    JsonString

    Type: Alias

    To: String

    LengthLimits

    Type: Struct

    Declarations:

    Field nameField value
    minu32
    maxu32

    Level

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    TRACE0
    DEBUG1
    INFO2
    WARN3
    ERROR4

    Limits

    Type: Struct

    Declarations:

    Field nameField value
    capacityu32
    max_entry_lenu32

    Log

    Type: Struct

    Declarations:

    Field nameField value
    levelLevel
    msgString

    MathError

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    Overflow0
    NotEnoughQuantity1
    DivideByZero2
    NegativeValue3
    DomainViolation4
    Unknown5
    FixedPointConversionString6

    MerkleTree<SignedTransaction>

    Type: Vec

    Value: HashOf<SignedTransaction>

    Metadata

    Type: Alias

    To: SortedMap<Name, MetadataValueBox>

    MetadataChanged<AccountId>

    Type: Struct

    Declarations:

    Field nameField value
    target_idAccountId
    keyName
    valueMetadataValueBox

    MetadataChanged<AssetDefinitionId>

    Type: Struct

    Declarations:

    Field nameField value
    target_idAssetDefinitionId
    keyName
    valueMetadataValueBox

    MetadataChanged<AssetId>

    Type: Struct

    Declarations:

    Field nameField value
    target_idAssetId
    keyName
    valueMetadataValueBox

    MetadataChanged<DomainId>

    Type: Struct

    Declarations:

    Field nameField value
    target_idDomainId
    keyName
    valueMetadataValueBox

    MetadataChanged<TriggerId>

    Type: Struct

    Declarations:

    Field nameField value
    target_idTriggerId
    keyName
    valueMetadataValueBox

    MetadataError

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    EmptyPath0
    EntryTooBigSizeError1
    MaxCapacitySizeError2
    MissingSegmentName3
    InvalidSegmentName4

    MetadataValueBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    Boolbool0
    StringString1
    NameName2
    BytesVec<u8>3
    NumericNumeric4
    LimitedMetadataMetadata5
    VecVec<MetadataValueBox>6

    Mint<Numeric, Asset>

    Type: Struct

    Declarations:

    Field nameField value
    objectNumeric
    destination_idAssetId

    Mint<PublicKey, Account>

    Type: Struct

    Declarations:

    Field nameField value
    objectPublicKey
    destination_idAccountId

    Mint<SignatureCheckCondition, Account>

    Type: Struct

    Declarations:

    Field nameField value
    objectSignatureCheckCondition
    destination_idAccountId

    Mint<u32, Trigger>

    Type: Struct

    Declarations:

    Field nameField value
    objectu32
    destination_idTriggerId

    MintBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    AccountAccountMintBox0
    AssetMint<Numeric, Asset>1
    TriggerRepetitionsMint<u32, Trigger>2

    MintabilityError

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    MintUnmintable0
    ForbidMintOnMintable1

    Mintable

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    Infinitely0
    Once1
    Not2

    Mismatch<AssetValueType>

    Type: Struct

    Declarations:

    Field nameField value
    expectedAssetValueType
    actualAssetValueType

    Name

    Type: Alias

    To: String

    NewAccount

    Type: Struct

    Declarations:

    Field nameField value
    idAccountId
    signatoriesSortedVec<PublicKey>
    metadataMetadata

    NewAssetDefinition

    Type: Struct

    Declarations:

    Field nameField value
    idAssetDefinitionId
    value_typeAssetValueType
    mintableMintable
    logoOption<IpfsPath>
    metadataMetadata

    NewDomain

    Type: Struct

    Declarations:

    Field nameField value
    idDomainId
    logoOption<IpfsPath>
    metadataMetadata

    NewParameter

    Type: Struct

    Declarations:

    Field nameField value
    parameterParameter

    NewRole

    Type: Struct

    Declarations:

    Field nameField value
    innerRole

    NonTrivial<GenericPredicateBox<QueryOutputPredicate>>

    Type: Alias

    To: Vec<GenericPredicateBox<QueryOutputPredicate>>

    NonZero<u32>

    Type: Alias

    To: u32

    NonZero<u64>

    Type: Alias

    To: u64

    Numeric

    Type: Struct

    Declarations:

    Field nameField value
    mantissaCompact<u128>
    scaleCompact<u32>

    NumericSpec

    Type: Struct

    Declarations:

    Field nameField value
    scaleOption<u32>

    Option<AccountId>

    Type: Option

    Some: AccountId

    Option<AssetDefinitionId>

    Type: Option

    Some: AssetDefinitionId

    Option<AssetId>

    Type: Option

    Some: AssetId

    Option<BlockStatus>

    Type: Option

    Some: BlockStatus

    Option<DomainId>

    Type: Option

    Some: DomainId

    Option<Duration>

    Type: Option

    Some: Duration

    Option<HashOf<MerkleTree<SignedTransaction>>>

    Type: Option

    Some: HashOf<MerkleTree<SignedTransaction>>

    Option<HashOf<SignedBlock>>

    Type: Option

    Some: HashOf<SignedBlock>

    Option<HashOf<SignedTransaction>>

    Type: Option

    Some: HashOf<SignedTransaction>

    Option<IpfsPath>

    Type: Option

    Some: IpfsPath

    Option<NonZero<u32>>

    Type: Option

    Some: NonZero<u32>

    Option<NonZero<u64>>

    Type: Option

    Some: NonZero<u64>

    Option<Option<u64>>

    Type: Option

    Some: Option<u64>

    Option<ParameterId>

    Type: Option

    Some: ParameterId

    Option<PeerId>

    Type: Option

    Some: PeerId

    Option<RoleId>

    Type: Option

    Some: RoleId

    Option<String>

    Type: Option

    Some: String

    Option<TimeInterval>

    Type: Option

    Some: TimeInterval

    Option<TransactionRejectionReason>

    Type: Option

    Some: TransactionRejectionReason

    Option<TransactionStatus>

    Type: Option

    Some: TransactionStatus

    Option<TriggerCompletedOutcomeType>

    Type: Option

    Some: TriggerCompletedOutcomeType

    Option<TriggerId>

    Type: Option

    Some: TriggerId

    Option<u32>

    Type: Option

    Some: u32

    Option<u64>

    Type: Option

    Some: u64

    Parameter

    Type: Struct

    Declarations:

    Field nameField value
    idParameterId
    valParameterValueBox

    ParameterId

    Type: Struct

    Declarations:

    Field nameField value
    nameName

    ParameterValueBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    TransactionLimitsTransactionLimits0
    MetadataLimitsLimits1
    LengthLimitsLengthLimits2
    NumericNumeric3

    Peer

    Type: Struct

    Declarations:

    Field nameField value
    idPeerId

    PeerEvent

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    AddedPeerId0
    RemovedPeerId1

    PeerEventFilter

    Type: Struct

    Declarations:

    Field nameField value
    id_matcherOption<PeerId>
    event_setPeerEventSet

    PeerEventSet

    Type: Bitmap

    Repr: u32

    Masks:

    Field nameField value
    Added0x1
    Removed0x2

    PeerId

    Type: Struct

    Declarations:

    Field nameField value
    addressSocketAddr
    public_keyPublicKey

    PermissionToken

    Type: Struct

    Declarations:

    Field nameField value
    definition_idName
    payloadJsonString

    PermissionTokenSchema

    Type: Struct

    Declarations:

    Field nameField value
    token_idsVec<Name>
    schemaString

    PermissionTokenSchemaUpdateEvent

    Type: Struct

    Declarations:

    Field nameField value
    old_schemaPermissionTokenSchema
    new_schemaPermissionTokenSchema

    PipelineEventBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    TransactionTransactionEvent0
    BlockBlockEvent1

    PipelineEventFilterBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    TransactionTransactionEventFilter0
    BlockBlockEventFilter1

    PublicKey

    Type: Struct

    Declarations:

    Field nameField value
    algorithmAlgorithm
    payloadVec<u8>

    QueryBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    FindAllAccountsFindAllAccounts0
    FindAccountByIdFindAccountById1
    FindAccountKeyValueByIdAndKeyFindAccountKeyValueByIdAndKey2
    FindAccountsByNameFindAccountsByName3
    FindAccountsByDomainIdFindAccountsByDomainId4
    FindAccountsWithAssetFindAccountsWithAsset5
    FindAllAssetsFindAllAssets6
    FindAllAssetsDefinitionsFindAllAssetsDefinitions7
    FindAssetByIdFindAssetById8
    FindAssetDefinitionByIdFindAssetDefinitionById9
    FindAssetsByNameFindAssetsByName10
    FindAssetsByAccountIdFindAssetsByAccountId11
    FindAssetsByAssetDefinitionIdFindAssetsByAssetDefinitionId12
    FindAssetsByDomainIdFindAssetsByDomainId13
    FindAssetsByDomainIdAndAssetDefinitionIdFindAssetsByDomainIdAndAssetDefinitionId14
    FindAssetQuantityByIdFindAssetQuantityById15
    FindTotalAssetQuantityByAssetDefinitionIdFindTotalAssetQuantityByAssetDefinitionId16
    FindAssetKeyValueByIdAndKeyFindAssetKeyValueByIdAndKey17
    FindAssetDefinitionKeyValueByIdAndKeyFindAssetDefinitionKeyValueByIdAndKey18
    FindAllDomainsFindAllDomains19
    FindDomainByIdFindDomainById20
    FindDomainKeyValueByIdAndKeyFindDomainKeyValueByIdAndKey21
    FindAllPeersFindAllPeers22
    FindAllBlocksFindAllBlocks23
    FindAllBlockHeadersFindAllBlockHeaders24
    FindBlockHeaderByHashFindBlockHeaderByHash25
    FindAllTransactionsFindAllTransactions26
    FindTransactionsByAccountIdFindTransactionsByAccountId27
    FindTransactionByHashFindTransactionByHash28
    FindPermissionTokensByAccountIdFindPermissionTokensByAccountId29
    FindPermissionTokenSchemaFindPermissionTokenSchema30
    FindAllActiveTriggerIdsFindAllActiveTriggerIds31
    FindTriggerByIdFindTriggerById32
    FindTriggerKeyValueByIdAndKeyFindTriggerKeyValueByIdAndKey33
    FindTriggersByDomainIdFindTriggersByDomainId34
    FindAllRolesFindAllRoles35
    FindAllRoleIdsFindAllRoleIds36
    FindRoleByRoleIdFindRoleByRoleId37
    FindRolesByAccountIdFindRolesByAccountId38
    FindAllParametersFindAllParameters39

    QueryExecutionFail

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    SignatureString0
    FindFindError1
    ConversionString2
    UnknownCursor3
    FetchSizeTooBig4

    QueryOutputBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    IdIdBox0
    IdentifiableIdentifiableBox1
    TransactionTransactionQueryOutput2
    PermissionTokenPermissionToken3
    PermissionTokenSchemaPermissionTokenSchema4
    LimitedMetadataMetadataValueBox5
    NumericNumeric6
    BlockHeaderBlockHeader7
    BlockSignedBlock8
    VecVec<QueryOutputBox>9

    QueryOutputPredicate

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    IdentifiableStringPredicate0
    ContainerContainer1
    DisplayStringPredicate2
    NumericalSemiRange3
    TimeStampSemiInterval<u128>4
    Pass5

    QueryPayload

    Type: Struct

    Declarations:

    Field nameField value
    authorityAccountId
    queryQueryBox
    filterGenericPredicateBox<QueryOutputPredicate>

    Register<Account>

    Type: Struct

    Declarations:

    Field nameField value
    objectNewAccount

    Register<Asset>

    Type: Struct

    Declarations:

    Field nameField value
    objectAsset

    Register<AssetDefinition>

    Type: Struct

    Declarations:

    Field nameField value
    objectNewAssetDefinition

    Register<Domain>

    Type: Struct

    Declarations:

    Field nameField value
    objectNewDomain

    Register<Peer>

    Type: Struct

    Declarations:

    Field nameField value
    objectPeer

    Register<Role>

    Type: Struct

    Declarations:

    Field nameField value
    objectNewRole

    Register<Trigger>

    Type: Struct

    Declarations:

    Field nameField value
    objectTrigger

    RegisterBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    PeerRegister<Peer>0
    DomainRegister<Domain>1
    AccountRegister<Account>2
    AssetDefinitionRegister<AssetDefinition>3
    AssetRegister<Asset>4
    RoleRegister<Role>5
    TriggerRegister<Trigger>6

    RemoveKeyValue<Account>

    Type: Struct

    Declarations:

    Field nameField value
    object_idAccountId
    keyName

    RemoveKeyValue<Asset>

    Type: Struct

    Declarations:

    Field nameField value
    object_idAssetId
    keyName

    RemoveKeyValue<AssetDefinition>

    Type: Struct

    Declarations:

    Field nameField value
    object_idAssetDefinitionId
    keyName

    RemoveKeyValue<Domain>

    Type: Struct

    Declarations:

    Field nameField value
    object_idDomainId
    keyName

    RemoveKeyValue<Trigger>

    Type: Struct

    Declarations:

    Field nameField value
    object_idTriggerId
    keyName

    RemoveKeyValueBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    DomainRemoveKeyValue<Domain>0
    AccountRemoveKeyValue<Account>1
    AssetDefinitionRemoveKeyValue<AssetDefinition>2
    AssetRemoveKeyValue<Asset>3
    TriggerRemoveKeyValue<Trigger>4

    Repeats

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    Indefinitely0
    Exactlyu321

    RepetitionError

    Type: Struct

    Declarations:

    Field nameField value
    instruction_typeInstructionType
    idIdBox

    Revoke<PermissionToken, Account>

    Type: Struct

    Declarations:

    Field nameField value
    objectPermissionToken
    destination_idAccountId

    Revoke<PermissionToken, Role>

    Type: Struct

    Declarations:

    Field nameField value
    objectPermissionToken
    destination_idRoleId

    Revoke<RoleId, Account>

    Type: Struct

    Declarations:

    Field nameField value
    objectRoleId
    destination_idAccountId

    RevokeBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    PermissionTokenRevoke<PermissionToken, Account>0
    RoleRevoke<RoleId, Account>1
    RolePermissionTokenRevoke<PermissionToken, Role>2

    Role

    Type: Struct

    Declarations:

    Field nameField value
    idRoleId
    permissionsSortedVec<PermissionToken>

    RoleEvent

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    CreatedRole0
    DeletedRoleId1
    PermissionRemovedRolePermissionChanged2
    PermissionAddedRolePermissionChanged3

    RoleEventFilter

    Type: Struct

    Declarations:

    Field nameField value
    id_matcherOption<RoleId>
    event_setRoleEventSet

    RoleEventSet

    Type: Bitmap

    Repr: u32

    Masks:

    Field nameField value
    Created0x1
    Deleted0x2
    PermissionRemoved0x4
    PermissionAdded0x8

    RoleId

    Type: Struct

    Declarations:

    Field nameField value
    nameName

    RolePermissionChanged

    Type: Struct

    Declarations:

    Field nameField value
    role_idRoleId
    permission_token_idName

    Schedule

    Type: Struct

    Declarations:

    Field nameField value
    startDuration
    periodOption<Duration>

    SemiInterval<Numeric>

    Type: Struct

    Declarations:

    Field nameField value
    startNumeric
    limitNumeric

    SemiInterval<u128>

    Type: Struct

    Declarations:

    Field nameField value
    startu128
    limitu128

    SemiRange

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    NumericSemiInterval<Numeric>0

    SetKeyValue<Account>

    Type: Struct

    Declarations:

    Field nameField value
    object_idAccountId
    keyName
    valueMetadataValueBox

    SetKeyValue<Asset>

    Type: Struct

    Declarations:

    Field nameField value
    object_idAssetId
    keyName
    valueMetadataValueBox

    SetKeyValue<AssetDefinition>

    Type: Struct

    Declarations:

    Field nameField value
    object_idAssetDefinitionId
    keyName
    valueMetadataValueBox

    SetKeyValue<Domain>

    Type: Struct

    Declarations:

    Field nameField value
    object_idDomainId
    keyName
    valueMetadataValueBox

    SetKeyValue<Trigger>

    Type: Struct

    Declarations:

    Field nameField value
    object_idTriggerId
    keyName
    valueMetadataValueBox

    SetKeyValueBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    DomainSetKeyValue<Domain>0
    AccountSetKeyValue<Account>1
    AssetDefinitionSetKeyValue<AssetDefinition>2
    AssetSetKeyValue<Asset>3
    TriggerSetKeyValue<Trigger>4

    SetParameter

    Type: Struct

    Declarations:

    Field nameField value
    parameterParameter

    Signature

    Type: Struct

    Declarations:

    Field nameField value
    public_keyPublicKey
    payloadVec<u8>

    SignatureCheckCondition

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    AnyAccountSignatureOrVec<PublicKey>0
    AllAccountSignaturesAndVec<PublicKey>1

    SignatureOf<BlockPayload>

    Type: Alias

    To: Signature

    SignatureOf<QueryPayload>

    Type: Alias

    To: Signature

    SignatureOf<TransactionPayload>

    Type: Alias

    To: Signature

    SignaturesOf<BlockPayload>

    Type: Struct

    Declarations:

    Field nameField value
    signaturesSortedVec<SignatureOf<BlockPayload>>

    SignaturesOf<TransactionPayload>

    Type: Struct

    Declarations:

    Field nameField value
    signaturesSortedVec<SignatureOf<TransactionPayload>>

    SignedBlock

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    V1SignedBlockV11

    SignedBlockV1

    Type: Struct

    Declarations:

    Field nameField value
    signaturesSignaturesOf<BlockPayload>
    payloadBlockPayload

    SignedQuery

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    V1SignedQueryV11

    SignedQueryV1

    Type: Struct

    Declarations:

    Field nameField value
    signatureSignatureOf<QueryPayload>
    payloadQueryPayload

    SignedTransaction

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    V1SignedTransactionV11

    SignedTransactionV1

    Type: Struct

    Declarations:

    Field nameField value
    signaturesSignaturesOf<TransactionPayload>
    payloadTransactionPayload

    SizeError

    Type: Struct

    Declarations:

    Field nameField value
    limitsLimits
    actualu64

    SocketAddr

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    Ipv4SocketAddrV40
    Ipv6SocketAddrV61
    HostSocketAddrHost2

    SocketAddrHost

    Type: Struct

    Declarations:

    Field nameField value
    hostString
    portu16

    SocketAddrV4

    Type: Struct

    Declarations:

    Field nameField value
    ipIpv4Addr
    portu16

    SocketAddrV6

    Type: Struct

    Declarations:

    Field nameField value
    ipIpv6Addr
    portu16

    SortedMap<AccountId, Account>

    Type: Map

    Key: AccountId

    Value: Account

    SortedMap<AssetDefinitionId, AssetDefinition>

    Type: Map

    Key: AssetDefinitionId

    Value: AssetDefinition

    SortedMap<AssetDefinitionId, Numeric>

    Type: Map

    Key: AssetDefinitionId

    Value: Numeric

    SortedMap<AssetId, Asset>

    Type: Map

    Key: AssetId

    Value: Asset

    SortedMap<Name, MetadataValueBox>

    Type: Map

    Key: Name

    Value: MetadataValueBox

    SortedVec<PermissionToken>

    Type: Vec

    Value: PermissionToken

    SortedVec<PublicKey>

    Type: Vec

    Value: PublicKey

    SortedVec<SignatureOf<BlockPayload>>

    Type: Vec

    Value: SignatureOf<BlockPayload>

    SortedVec<SignatureOf<TransactionPayload>>

    Type: Vec

    Value: SignatureOf<TransactionPayload>

    String

    Type: Alias

    To: String

    StringPredicate

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    ContainsString0
    StartsWithString1
    EndsWithString2
    IsString3

    TimeEvent

    Type: Struct

    Declarations:

    Field nameField value
    prev_intervalOption<TimeInterval>
    intervalTimeInterval

    TimeEventFilter

    Type: Alias

    To: ExecutionTime

    TimeInterval

    Type: Struct

    Declarations:

    Field nameField value
    sinceDuration
    lengthDuration

    TransactionEvent

    Type: Struct

    Declarations:

    Field nameField value
    hashHashOf<SignedTransaction>
    block_heightOption<u64>
    statusTransactionStatus

    TransactionEventFilter

    Type: Struct

    Declarations:

    Field nameField value
    hashOption<HashOf<SignedTransaction>>
    block_heightOption<Option<u64>>
    statusOption<TransactionStatus>

    TransactionLimitError

    Type: Struct

    Declarations:

    Field nameField value
    reasonString

    TransactionLimits

    Type: Struct

    Declarations:

    Field nameField value
    max_instruction_numberu64
    max_wasm_size_bytesu64

    TransactionPayload

    Type: Struct

    Declarations:

    Field nameField value
    chain_idChainId
    authorityAccountId
    creation_time_msu64
    instructionsExecutable
    time_to_live_msOption<NonZero<u64>>
    nonceOption<NonZero<u32>>
    metadataSortedMap<Name, MetadataValueBox>

    TransactionQueryOutput

    Type: Struct

    Declarations:

    Field nameField value
    block_hashHashOf<SignedBlock>
    transactionTransactionValue

    TransactionRejectionReason

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    AccountDoesNotExistFindError0
    LimitCheckTransactionLimitError1
    ValidationValidationFail2
    InstructionExecutionInstructionExecutionFail3
    WasmExecutionWasmExecutionFail4

    TransactionStatus

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    Queued0
    Expired1
    Approved2
    RejectedTransactionRejectionReason3

    TransactionValue

    Type: Struct

    Declarations:

    Field nameField value
    valueSignedTransaction
    errorOption<TransactionRejectionReason>

    Transfer<Account, AssetDefinitionId, Account>

    Type: Struct

    Declarations:

    Field nameField value
    source_idAccountId
    objectAssetDefinitionId
    destination_idAccountId

    Transfer<Account, DomainId, Account>

    Type: Struct

    Declarations:

    Field nameField value
    source_idAccountId
    objectDomainId
    destination_idAccountId

    Transfer<Asset, Metadata, Account>

    Type: Struct

    Declarations:

    Field nameField value
    source_idAssetId
    objectMetadata
    destination_idAccountId

    Transfer<Asset, Numeric, Account>

    Type: Struct

    Declarations:

    Field nameField value
    source_idAssetId
    objectNumeric
    destination_idAccountId

    TransferBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    DomainTransfer<Account, DomainId, Account>0
    AssetDefinitionTransfer<Account, AssetDefinitionId, Account>1
    AssetAssetTransferBox2

    Trigger

    Type: Struct

    Declarations:

    Field nameField value
    idTriggerId
    actionAction

    TriggerCompletedEvent

    Type: Struct

    Declarations:

    Field nameField value
    trigger_idTriggerId
    outcomeTriggerCompletedOutcome

    TriggerCompletedEventFilter

    Type: Struct

    Declarations:

    Field nameField value
    trigger_idOption<TriggerId>
    outcome_typeOption<TriggerCompletedOutcomeType>

    TriggerCompletedOutcome

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    Success0
    FailureString1

    TriggerCompletedOutcomeType

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    Success0
    Failure1

    TriggerEvent

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    CreatedTriggerId0
    DeletedTriggerId1
    ExtendedTriggerNumberOfExecutionsChanged2
    ShortenedTriggerNumberOfExecutionsChanged3
    MetadataInsertedMetadataChanged<TriggerId>4
    MetadataRemovedMetadataChanged<TriggerId>5

    TriggerEventFilter

    Type: Struct

    Declarations:

    Field nameField value
    id_matcherOption<TriggerId>
    event_setTriggerEventSet

    TriggerEventSet

    Type: Bitmap

    Repr: u32

    Masks:

    Field nameField value
    Created0x1
    Deleted0x2
    Extended0x4
    Shortened0x8
    MetadataInserted0x10
    MetadataRemoved0x20

    TriggerId

    Type: Struct

    Declarations:

    Field nameField value
    domain_idOption<DomainId>
    nameName

    TriggerNumberOfExecutionsChanged

    Type: Struct

    Declarations:

    Field nameField value
    trigger_idTriggerId
    byu32

    TriggeringEventFilterBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    PipelinePipelineEventFilterBox0
    DataDataEventFilter1
    TimeTimeEventFilter2
    ExecuteTriggerExecuteTriggerEventFilter3

    TypeError

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    AssetValueTypeMismatch<AssetValueType>0
    NumericAssetValueTypeExpectedAssetValueType1
    StoreAssetValueTypeExpectedAssetValueType2

    Unregister<Account>

    Type: Struct

    Declarations:

    Field nameField value
    object_idAccountId

    Unregister<Asset>

    Type: Struct

    Declarations:

    Field nameField value
    object_idAssetId

    Unregister<AssetDefinition>

    Type: Struct

    Declarations:

    Field nameField value
    object_idAssetDefinitionId

    Unregister<Domain>

    Type: Struct

    Declarations:

    Field nameField value
    object_idDomainId

    Unregister<Peer>

    Type: Struct

    Declarations:

    Field nameField value
    object_idPeerId

    Unregister<Role>

    Type: Struct

    Declarations:

    Field nameField value
    object_idRoleId

    Unregister<Trigger>

    Type: Struct

    Declarations:

    Field nameField value
    object_idTriggerId

    UnregisterBox

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    PeerUnregister<Peer>0
    DomainUnregister<Domain>1
    AccountUnregister<Account>2
    AssetDefinitionUnregister<AssetDefinition>3
    AssetUnregister<Asset>4
    RoleUnregister<Role>5
    TriggerUnregister<Trigger>6

    Upgrade

    Type: Struct

    Declarations:

    Field nameField value
    executorExecutor

    ValidationFail

    Type: Enum

    Variants:

    Variant nameVariant valueDiscriminant
    NotPermittedString0
    InstructionFailedInstructionExecutionError1
    QueryFailedQueryExecutionFail2
    TooComplex3
    InternalError4

    Vec<EventBox>

    Type: Vec

    Value: EventBox

    Vec<EventFilterBox>

    Type: Vec

    Value: EventFilterBox

    Vec<GenericPredicateBox<QueryOutputPredicate>>

    Type: Vec

    Value: GenericPredicateBox<QueryOutputPredicate>

    Vec<InstructionBox>

    Type: Vec

    Value: InstructionBox

    Vec<MetadataValueBox>

    Type: Vec

    Value: MetadataValueBox

    Vec<Name>

    Type: Vec

    Value: Name

    Vec<PeerId>

    Type: Vec

    Value: PeerId

    Vec<PublicKey>

    Type: Vec

    Value: PublicKey

    Vec<QueryOutputBox>

    Type: Vec

    Value: QueryOutputBox

    Vec<TransactionValue>

    Type: Vec

    Value: TransactionValue

    Vec<u8>

    Type: Vec

    Value: u8

    WasmExecutionFail

    Type: Struct

    Declarations:

    Field nameField value
    reasonString

    WasmSmartContract

    Type: Alias

    To: Vec<u8>

    bool

    Type: Alias

    To: bool

    u128

    Type: Int

    Kind: FixedWidth

    u16

    Type: Int

    Kind: FixedWidth

    u32

    Type: Int

    Kind: FixedWidth

    u64

    Type: Int

    Kind: FixedWidth

    u8

    Type: Int

    Kind: FixedWidth

    + + + + \ No newline at end of file diff --git a/reference/ffi.html b/reference/ffi.html new file mode 100644 index 00000000..50843bb2 --- /dev/null +++ b/reference/ffi.html @@ -0,0 +1,46 @@ + + + + + + Foreign Function Interfaces (FFI) | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Foreign Function Interfaces (FFI)

    To reduce the sizes of smartcontracts, we provide a dynamic library in the execution environment. We shall detail how to link against that library and use the functions at a later date, but for now, let's explore how to include functions and trait implementations into that library.

    Why FFI

    A function is a rather abstract entity, and while most languages agree on what a function should do, the way in which said functions are represented is very different. Moreover, in some languages (like Rust), the consequences of calling a function, and the things that it is allowed to do are different. Because one can use any language to create a WASM smartcontract, we need to level the playing field. This is where the concept of foreign function interface (FFI) comes in.

    The main standard used today is the C application binary interface. It's simple, it's guaranteed to be available even in languages which can't compile to WASM, and it's stable. In principle, you could do everything manually, but Iroha provides you with a crate iroha_ffi which contains all you need to generate FFI-compliant functions out of your existing Rust API.

    You can, of course, do this your way. The iroha_ffi crate merely generates the code that you would need to generate anyway. Writing the necessary boilerplate requires quite a bit of diligence and discipline. Every function call over the FFI boundary is unsafe with a potential to cause undefined behaviour. The method by which we managed to solve it, revolves around using robust repr(C) types.

    INFO

    The only exception are pointers. The null check and the validity cannot be enforced globally, so raw pointers (as always) are only used in exceptional cases. Given that we provide wrappers around almost every instance of an object in the Iroha data model, you shouldn't have to use raw pointers at all.

    Example

    Here is an example of generating a binding:

    rust
    #[derive(FfiType)]
    +struct DaysSinceEquinox(u32);
    +
    +#[ffi_export]
    +impl DaysSinceEquinox {
    +    pub fn update_value(&mut self, a: &u8) {
    +        self.0 = *a as u32;
    +    }
    +}

    The example above will generate the following binding with DaysSinceEquinox represented as an opaque pointer:

    rust
    pub extern fn DaysSinceEquinox__update_value(handle: *mut DaysSinceEquinox, a: *const u8) -> FfiReturn {
    +    // function implementation
    +}

    FFI Binding Generation

    The iroha_ffi crate is used to generate functions that are callable via FFI. Given Rust structs and methods, they generate the unsafe code that you would need in order to cross the linking boundary.

    A Rust type is converted into a robust repr(C) type that can cross the FFI boundary with FfiType::into_ffi. This goes the other way around as well: FFI ReprC type is converted into a Rust type via FfiType::try_from_ffi.

    WARNING

    Note that the opposite conversion is fallible and can cause undefined behaviour. While we can make the best effort to avoid the most obvious mistakes, you must ensure the program's correctness on your end.

    The diagram below uses the creation of a new domain as an example to show the conversion process (more on the name mangling semantics in a separate section).

    Untitled

    The main traits that enable binding generation are ReprC, FfiType and FfiConvert

    TraitDescription
    ReprCThis trait represents a robust type that conforms to C ABI. The type can be safely shared across FFI boundaries.
    FfiTypeThis trait defines a corresponding ReprC type for a given Rust type. The defined ReprC type is used in place of the Rust type in the API of the generated FFI function.
    FfiConvertThis trait defines two methods into_ffi and try_from_ffi that are used to perform the conversion of the Rust type to or from ReprC type.

    Note that there is no ownership transfer over FFI except for opaque pointer types. All other types that carry ownership, such as Vec<T>, are cloned.

    Name Mangling

    Note the use of double underscores in generated names of FFI objects:

    • For the inherent_fn method defined on the StructName struct, the FFI name would be StructName__inherent_fn.

    • For the MethodName method from the TraitName trait in the StructName struct, the FFI name would be StructName__TraitName__MethodName.

    • To set the field_name field in the StructName struct, the FFI function name would be StructName__set_field_name.

    • To get the field_name field in the StructName struct, the FFI function name would be StructName__field_name.

    • To get the mutable field_name field in the StructName struct, the FFI function name would be StrucuName__field_name_mut.

    • For the freestanding module_name::fn_name, the FFI name would be module_name::__fn_name.

    • For the traits that are not generic and allow sharing their implementation in the FFI (see Clone below), the FFI name would be module_name::__clone.

      rust
      impl Clone for Type1 {
      +    fn clone(&self) -> Self;
      +}
      +impl Clone for Type2 {
      +    fn clone(&self) -> Self;
      +}
    + + + + \ No newline at end of file diff --git a/reference/glossary.html b/reference/glossary.html new file mode 100644 index 00000000..1597a16b --- /dev/null +++ b/reference/glossary.html @@ -0,0 +1,31 @@ + + + + + + Glossary | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Glossary

    Here you can find definitions of all Iroha-related entities.

    Blockchain ledgers

    Blockchain ledgers are digital record-keeping systems that use blockchain technology to keep financial records. These are named after old-fashioned books that were used for financial records such as prices, news, and transaction information.

    During medieval times, ledger books were open for public viewing and accuracy verification. This idea is reflected in the blockchain-based systems that can check the stored data for validity.

    Peer

    A peer in Iroha means an Iroha process instance to which other Iroha processes and client applications can connect. A single machine can host several Iroha peers. Peers are equal regarding their resources and capabilities, with an important exception: only one of the peers runs the genesis block at the bootstrapping stage of the Iroha network.

    Other blockchains may refer to the same concept as a node or a validator.

    A peer can be a process on its host system. It also can be contained in a Docker container and a Kubernetes pod.

    Asset

    In the context of blockchains, an asset is the representation of a valuable object on the blockchain.

    Additional information on assets is available here.

    Fungible assets

    Such assets can be easily swapped for other assets of the same type because they are interchangeable.

    As an example, all units of the same currency are equal in their value and can be used to purchase goods. Typically, fungible assets are identical in appearance, aside from the wear of banknotes and coins.

    Non-fungible assets

    Non-fungible assets are unique and valuable due to their specific characteristics and rarity; their value cannot be compared to other assets.

    • A painting's value can vary based on the artist, the time period it was painted, and the public's interest in it.
    • Two houses on the same street may have differing levels of maintenance.
    • Jewellery manufacturers typically offer a range of different designs.

    Mintable assets

    An asset is mintable if more of the same type can be issued.

    Non-mintable assets

    If the initial amount of an asset is specified once and doesn't change, it is considered non-mintable.

    The Genesis block sets this information for the Iroha configuration.

    Byzantine fault-tolerance (BFT)

    The property of being able to properly function with a network containing a certain percentage of malicious actors. Iroha is capable of functioning with up to 33% malicious actors in its peer-to-peer network.

    Iroha Components

    Rust modules containing Iroha functionality.

    Sumeragi (Emperor)

    The Iroha module responsible for consensus.

    Torii (Gate)

    Module with the incoming request handling logic for the peer. It is used to receive, accept and route incoming instructions, and HTTP queries, as well as run-time configuration updates.

    Kura (Warehouse)

    Persistence-related logic. It handles storing the blocks, log rotation, block storage folder rotation, etc.

    Kagami(Teacher and Exemplar and/or looking glass)

    Generator for commonly used data. It can generate cryptographic key pairs, genesis blocks, documentation, etc.

    Merkle tree (hash tree)

    A data structure used to validate and verify the state at each block height. Iroha's current implementation is a binary tree. See Wikipedia for more details.

    Smart contracts

    Smart contracts are blockchain-based programs that run when a specific set of conditions is met. In Iroha smart contracts are implemented using core Iroha special instructions.

    Triggers

    An event type that allows invoking an Iroha special instruction at specific block commit, time (with some caveats), etc. More on triggers here.

    Versioning

    Each request is labelled with the API version to which it belongs. It allows a combination of different binary versions of Iroha client/peer software to interoperate, which in turn allows software upgrades in the Iroha network.

    Hijiri (peer reputation system)

    Iroha's reputation system. It allows prioritising communication with peers that have a good track-record, and reducing the harm that can be caused by malicious peers.

    Iroha Modules

    Third party extensions to Iroha that provide custom functionality.

    Iroha Special Instructions (ISI)

    A library of smart contracts provided with Iroha. These can be invoked via either transactions or registered event listeners. More on ISI here.

    Utility Iroha Special Instructions

    This set of isi contains logical instructions like If, I/O related like Notify and compositions like Sequence. They are mostly used as custom instructions.

    Core Iroha Special Instructions

    Special instructions provided with every Iroha deployment. These include some domain-specific as well as utility instructions.

    Domain-specific Iroha Special Instructions

    Instructions related to domain-specific activities: assets, accounts, domains, peer management). These provide the tools necessary to make changes to the World State View in a secure and safe manner.

    Custom Iroha Special Instruction

    Instructions provided in Iroha Modules, by clients or 3rd parties. These can only be built using the Core Instructions. Forking and modifying the Iroha source code is not recommended, as special instructions not agreed-upon by peers in an Iroha deployment will be treated as faults, thus peers running a modified instance will have their access revoked.

    Iroha Query

    A request to read the World State View without modifying said view. More on queries here.

    View change

    A process that takes place in case of a failed attempt at consensus. Usually this entails the election of a new Leader.

    World state view (WSV)

    In-memory representation of the current blockchain state. This includes all currently loaded blocks, with all of their contents, as well as peers elected for the current epoch.

    Leader

    In an iroha network, a peer is selected randomly and granted the special privilege of forming the next block. This privilege can be revoked in networks that achieve Byzantine fault-torelance via view change.

    + + + + \ No newline at end of file diff --git a/reference/instructions.html b/reference/instructions.html new file mode 100644 index 00000000..ae38a12d --- /dev/null +++ b/reference/instructions.html @@ -0,0 +1,31 @@ + + + + + + Iroha Special Instructions | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Iroha Special Instructions

    The following instructions are supported in Iroha 2:

    InstructionDescriptions
    Register/UnregisterGive an ID to a new entity on the blockchain.
    Mint/BurnMint/burn assets, triggers, or permission tokens.
    SetKeyValue/RemoveKeyValueUpdate blockchain object metadata.
    NewParameter/SetParameterCreate/set a chain-wide config parameter.
    Grant/RevokeGive or remove certain permissions from accounts.
    TransferTransfer assets between accounts.
    ExecuteTriggerExecute triggers.
    If, Pair, SequenceUse to create composite instructions.
    Diagram: Iroha Special Instructions
    + + + + \ No newline at end of file diff --git a/reference/naming.html b/reference/naming.html new file mode 100644 index 00000000..0de13701 --- /dev/null +++ b/reference/naming.html @@ -0,0 +1,31 @@ + + + + + + Naming Conventions | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Naming Conventions

    When you are naming accounts, domains, or assets, you have to keep in mind the following conventions used in Iroha 2:

    1. There is a number of reserved characters that are used for specific types of constructs:

      • @ is reserved for account@domain constructs
      • # is reserved for asset#domain constructs
      • $ is reserved for trigger$domain constructs
      • % is reserved for validator%account constructs
    2. The maximum number of characters (including UTF-8 characters) a name can have is limited by two factors: [0, u32::MAX] and the currently allocated stack space.

    + + + + \ No newline at end of file diff --git a/reference/permissions.html b/reference/permissions.html new file mode 100644 index 00000000..d4962e7e --- /dev/null +++ b/reference/permissions.html @@ -0,0 +1,45 @@ + + + + + + Permissions | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Permissions

    This section provides details about pre-configured permission tokens in Iroha 2. For more general information on permission tokens and permission groups (roles), refer to the Permissions chapter in Guide.

    Permission Tokens

    The following permission tokens are pre-configured in Iroha 2:

    Permission TokenCategoryOperation
    [CanUnregisterDomain]DomainAllows to unregister a domain
    [CanSetKeyValueInDomain]DomainAllows to add domain's metadata key value
    [CanRemoveKeyValueInDomain]DomainAllows to remove domain's metadata key value
    [CanUnregisterAccount]AccountAllows to unregister an account
    [CanMintUserPublicKeys]AccountAllows to add a public key to an account
    [CanBurnUserPublicKeys]AccountAllows to remove a public key from an account
    [CanMintUserSignatureCheckConditions]AccountAllows to set check conditions for a signature
    [CanSetKeyValueInUserAccount]AccountAllows to add user's metadata key value
    [CanRemoveKeyValueInUserAccount]AccountAllows to remove user's metadata key value
    [CanRegisterAssetsWithDefinition]AssetAllows to register a new asset with this definition
    [CanUnregisterAssetsWithDefinition]AssetAllows to unregister a new asset with this definition
    [CanUnregisterUserAsset]AssetAllows to remove asset from a user
    [CanMintAssetsWithDefinition]AssetAllows to mint quantity of assets with this definition
    [CanBurnAssetsWithDefinition]AssetAllows to burn quantity of assets with this definition
    [CanTransferAssetsWithDefinition]AssetAllows to transfer quantity of assets with this definition
    [CanBurnUserAsset]AssetAllows to burn user's asset quantity
    [CanTransferUserAsset]AssetAllows to transfer user's asset quantity
    [CanSetKeyValueInUserAsset]AssetAllows to set key value to user's asset metadata
    [CanRemoveKeyValueInUserAsset]AssetAllows to remove key value from user's asset metadata
    [CanSetKeyValueInAssetDefinition]Asset DefinitionAllows to add key value to metadata for this asset definition
    [CanRemoveKeyValueInAssetDefinition]Asset DefinitionAllows to remove key value from metadata for this asset definition
    [CanUnregisterAssetDefinition]Asset DefinitionAllows to unregister this asset definition

    INFO

    The way permissions work in Iroha 2 is subject to change. Only an owner of the subject can grant permissions for the subject.

    By default, all assets and accounts defined in the genesis block configuration file are created by genesis@genesis account. This means that alice@wonderland is not the owner of rose#wonderland and cannot grant permission for rose#wonderland.

    To avoid this you can:

    1. Edit the genesis.json file to only include the creation of alice@wonderland, and then redeploy Iroha 2.
    2. Create a subject (e.g., an asset definition) on behalf of alice@wonderland, and then give another account the permission to manage this subject.

    General example

    With this example, the owner-account can give permission for its subject to another account. The example is based on the following pre-conditions: The subject is created by the owner-account The recipient account is created

    rust
    // Define the asset definition owner
    +let asset_definition_owner = AccountId::from_str("alice@wonderland").unwrap();
    +// Define the asset definition id which was created by the owner
    +let asset_definition_id = AssetDefinitionId::from_str("coolAsset#wonderland").unwrap();
    +// Define the account which we want to give the permission
    +let recipient_account = AccountId::from_str("actor@wonderland").unwrap();
    +// Create a token that we chose. And define its structure according to `iroha_executor\smart_contract\executor\src\default.rs`
    +let can_mint_asset_with_definition_token = PermissionToken::new(
    +"CanMintAssetsWithDefinition".parse().unwrap(),
    +&json!({ "asset_definition_id": asset_definition_id }),
    +);
    +// Create a permission expression (Grant\Revoke)
    +let permission_expression = GrantExpr::new(can_mint_asset_with_definition_token, recipients_account);
    +// Submit the transaction with the permission expression
    +iroha_client.submit_blocking(permission_expression).unwrap();
    + + + + \ No newline at end of file diff --git a/reference/queries.html b/reference/queries.html new file mode 100644 index 00000000..ad172a15 --- /dev/null +++ b/reference/queries.html @@ -0,0 +1,45 @@ + + + + + + Queries | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Queries

    In the following section we mirror the module structure of the queries and present to you what they do. You can learn

    INFO

    The results of queries can be sorted, paginated and filtered peer-side all at once.

    Conventions

    Expand to learn about the conventions used in the descriptions below
    1. In the Details section of each query, we use gets, returns, searches with the following precise meanings:

      NotationMeaning
      getsThe query already has the data readily available and the data is trivial. Use these queries at will.
      returns or findsThe query has the data readily available, just as with gets, but the data is not trivial. You can still use these queries, but be mindful of the performance impact.
      searchesFor this query, the data must be actively collected and neither the return type nor the collection process is cheap. Use with great care.
    2. The queries are provided with just one data type as input, and parameterised by the type of the output.

    3. For the FindZByXAndY queries, their descriptions have a Parameters and a Returns section. The parameters can either be single or multiple types, while the output is almost always either one type, or a Vec<Type> kind of construction:

      NotationMeaning
      Parameters: (X, Y)In Rust source code, you need to construct the query as let query = FindZByXAndY::new(x: X, y: Y);, where x and y are variables of type X and Y respectively. In the reference below we provide you with information about each type.
      Returns: Vec<Z>The return value is a collection of more than one element of type Z. Depending on the SDK implementation this can be a type native to the language (e.g. JavaScript) or a thin wrapper around the Rust Vec structure.

    Role

    An optional feature. By default, it is present on all Iroha 2 deployments when they're compiled in the private blockchain configuration.

    You can learn more about roles in a dedicated section.

    FindAllRoles

    • Returns: Vec<Roles>

    • Details: Returns all roles registered as global (as opposed to domain-scoped) in the blockchain.

    FindAllRoleIds

    • Returns: Vec<Roles>

    • Details: Returns IDs of all the roles registered as global (as opposed to domain-scoped) in the blockchain.

      Note that it does not return its values, which contain permission tokens, only IDs.

    FindRoleByRoleId

    • Parameters: RoleId

    • Returns: Vec<Roles>

    • Details: Returns the role that has the provided role ID.

      For example, given the name of the role admin, it will return all of the admin-level permission tokens.

    FindRolesByAccountId

    • Parameters: AccountId

    • Returns: Vec<RoleId>

    • Details: Returns all of the role IDs that are attached to the given account.

      Note that unlike FindAllRoles, it does not return the roles themselves.

    Permission

    A semi-optional feature. You have permissions in both public and private blockchains but the use cases are different:

    • In a public blockchain, most accounts have the same common-sense permissions.
    • In a private blockchain, most accounts are assumed not to be able to do anything outside of their own account or domain unless explicitly granted said permission.

    We talk about permissions in more detail in a dedicated chapter.

    FindAllPermissionTokenDefinitions

    • Returns: Vec<PermissionTokenDefinition>

    • Details: Finds all registered permission token definitions.

    FindPermissionTokensByAccountId

    • Parameters: AccountId

    • Returns: Vec<PermissionToken>

    • Details: Returns all of the permission tokens granted to the specified account.

    Account

    Most queries in Iroha pertain to accounts. At the moment this is the most diverse set of queries.

    FindAllAccounts

    • Returns: Vec<Account>

    • Details: Finds all accounts registered globally in the blockchain.

    FindAccountById

    • Parameters: AccountId

    • Returns: Account

    • Details: Returns the full account information corresponding to the given AccountId.

    FindAccountKeyValueByIdAndKey

    • Parameters: (AccountId, Name)

    • Returns: Value

    • Details: Returns the value keyed by the provided Name for the given account.

      This is done by querying the metadata attached to the given account.

    FindAccountsByName

    • Parameters: Name

    • Returns: Vec<Account>

    • Details: Returns all of the accounts that have the given Name.

      This is particularly useful if you remember the name of the account, but do not, for example, recall the domain name in which it was registered.

    FindAccountsByDomainId

    • Parameters: DomainId

    • Returns: Vec<Account>

    • Details: Returns all accounts that belong to a specific domain.

      Note that this returns the full accounts and not the AccountId collection.

    FindAccountsWithAsset

    • Parameters: AccountId

    • Returns: Vec<Account>

    • Details: Returns all accounts that have the given asset.

    Asset

    Assets include simple numbers, but also a special type of key-to-value map that is used as a secure data storage for privileged information.

    FindAllAssets

    • Returns: Vec<Asset>

    • Details: Returns all known assets by value.

      INFO

      You should note that this is not the same as AssetDefinition. If you have one asset called e.g. tea#wonderland that belongs to every account on the blockchain, you will receive the aggregated value across all accounts, but not the information such as the type of the asset.

    FindAllAssetDefinitions

    • Returns: Vec<AssetDefinition>

    • Details: Returns all known asset definitions by value.

      TIP

      To reduce the load on the network, we store the definition of an asset separate from its instances. So if you want to know if an asset is mintable or what type is stored in it, you need to query the asset definition, rather than the asset itself.

    FindAssetById

    • Parameters: AssetId

    • Returns: Asset

    • Details: Returns the aggregated data about the asset usage across the network.

    FindAssetsByName

    • Parameters: Name

    • Returns: Vec<Asset>

    • Details: Searches the network for all assets that match the given name.

    FindAssetsByAccountId

    • Parameters: AccountId

    • Returns: Vec<Asset>

    • Details: Returns all of the assets that belong to a given account.

    FindAssetsByAssetDefinitionId

    • Parameters: AssetDefinitionId

    • Returns: Vec<Asset>

    • Details: Searches for all of the assets that have the given definition ID.

    FindAssetsByDomainId

    • Parameters: DomainId

    • Returns: Vec<Asset>

    • Details: Returns all assets that are registered in the given domain.

    FindAssetsByDomainIdAndAssetDefinitionId

    • Parameters: (DomainId, AssetDefinitionId)

    • Returns: Vec<Asset>

    • Details: Searches the domain for assets that have the given definition ID.

    FindAssetQuantityById

    • Parameters: AssetId

    • Returns: NumericValue

    • Details: Returns the asset quantity.

      Note that this query assumes that the asset given by the identifier is of type AssetValue::Quantity.

      WARNING

      This query can fail.

    FindAssetKeyValueByIdAndKey

    • Parameters: (AssetId, Name)

    • Returns: Value

    • Details: Gets the value keyed by the given name in the metadata of the asset corresponding to the given identifier.

    FindAssetDefinitionKeyValueByIdAndKey

    • Parameters: (AssetDefinitionId, Name)

    • Returns: Value

    • Details: Gets the value keyed by the given name in the metadata of the asset definition corresponding to the given identifier.

    FindTotalAssetQuantityByAssetDefinitionId

    • Parameters: AssetDefinitionId

    • Returns: NumericValue

    • Details: Finds the total asset quantity for the given asset definition. For the Store asset value, finds the sum of asset quantities through all accounts that hold the specified asset.

    Block

    FindAllBlocks

    • Returns: Vec<VersionedCommittedBlock>
    • Details: Returns all blocks in the blockchain.

    FindAllBlockHeaders

    • Returns: Vec<BlockHeader>
    • Details: Returns all block headers for blocks in the blockchain.

    FindBlockHeaderByHash

    • Parameters: Hash
    • Returns: BlockHeader
    • Details: Gets the block header that matches the hash that was provided.

    Domain

    The domain is the basic unit of organisation in an Iroha blockchain. Accounts and assets must be registered inside a domain, triggers are usually scoped by domain, and most queries have the domain as a possible input.

    FindAllDomains

    • Returns: Vec<Domain>

    • Details: Returns all of the known registered domains.

      WARNING

      This query returns the full contents of the world state view as of execution. This query should be used sparingly and for debugging purposes only.

    FindDomainById

    • Parameters: DomainId

    • Returns: Domain

    • Details: Gets the domain corresponding to the given identifier.

    FindDomainKeyValueByIdAndKey

    • Parameters: (DomainId, Name)

    • Returns: Value

    • Details: Returns the value keyed by the given name in the domain corresponding to the given identifier.

    Peer

    A peer is the basic unit of storage and validation. In common parlance we may conflate the node and the peer binary running on the node, but in this case we specifically mean the peer binary as a server with its specific configuration.

    FindAllPeers

    • Returns: Vec<Peer>

    • Details: Returns all known peers identified by their key and accompanied by the address of the API endpoint of each.

    FindAllParameters

    • Returns: Vec<Parameter>

      rust
      pub enum Parameter {
      +    /// Maximum amount of Faulty Peers in the system.
      +    MaximumFaultyPeersAmount(u32),
      +    /// Maximum time for a leader to create a block.
      +    BlockTime(u128),
      +    /// Maximum time for a proxy tail to send commit message.
      +    CommitTime(u128),
      +    /// Time to wait for a transaction Receipt.
      +    TransactionReceiptTime(u128),
      +}
    • Details: Returns the parameters used by all peers in the network.

      This is useful for debugging if any of the peers are incorrectly configured and causing view changes.

    Transaction

    It is often necessary to query the state of specific transactions, especially for use in blockchain explorers and for user-facing applications.

    FindTransactionsByAccountId

    • Parameters: AccountId

    • Returns: Vec<TransactionValue>

      rust
      pub enum TransactionValue {
      +    /// Committed transaction
      +    Transaction(Box<VersionedSignedTransaction>),
      +    /// Rejected transaction with reason of rejection
      +    RejectedTransaction(Box<VersionedRejectedTransaction>),
      +}
    • Details: Returns the full set of transactions that an account has submitted throughout the existence of the blockchain.

    FindTransactionByHash

    • Parameters: Hash

    • Returns: TransactionValue

    • Details: Returns the transaction by hash.

    Trigger

    Iroha is an event-driven architecture. Every modification of the world state emits a corresponding event that can be captured by appropriate event listeners called filters.

    INFO

    Note that Iroha shut downs all listeners on panic.

    FindAllActiveTriggerIds

    • Returns: Vec<TriggerId>

    • Details: Finds all currently active triggers, that is, triggers that have not expired at the time of the query.

    FindTriggerById

    • Parameters: TriggerId

    • Returns: Trigger

    • Details: Finds the trigger with the given ID.

    FindTriggerKeyValueByIdAndKey

    • Parameters: (TriggerId, Name)

    • Returns: Trigger

    • Details: Finds the value corresponding to the key in the metadata of the trigger with the given ID.

    FindTriggersByDomainId

    • Parameters: DomainId

    • Returns: Vec<Trigger>

    • Details: Finds all domain triggers for the given domain ID.

    + + + + \ No newline at end of file diff --git a/reference/torii-endpoints.html b/reference/torii-endpoints.html new file mode 100644 index 00000000..81e1b593 --- /dev/null +++ b/reference/torii-endpoints.html @@ -0,0 +1,123 @@ + + + + + + Torii Endpoints | Hyperledger Iroha 2 Tutorial + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Torii Endpoints

    About Parity SCALE Codec

    Messages for certain TORII operations are encoded with the Parity SCALE Codec (SCALE) commonly used with the Parity Substrate blockchain framework, and other blockchains utilizing it.

    For more information on SCALE, see the Substrate Documentation: Type encoding (SCALE) article and its official GitHub repository.

    Torii (Japanese: 鳥居 — Shinto shrine gateway) is the Iroha 2 module in charge of handling HTTP and WebSocket requests. It is the main API for interacting with Iroha 2. Such interactions include sending transactions, making queries, listening for blocks stream, etc.

    API Version

    INFO

    This operation requires the specific Iroha node being requested to be compiled with the telemetry feature enabled.

    • Protocol: HTTP
    • Method: GET
    • Encoding: JSON
    • Endpoint: /api_version

    Requests

    A GET request to the endpoint.

    Responses

    CodeResponseDescription
    200OKReturns the current version of the API used by the requested Iroha 2 node as a JSON string.

    Example:

    json
    "1"

    INFO

    The API version is retrieved from and is the same as the version of the genesis block, which means that at least a minimal subnet of four peers must be running, and the genesis block must already be submitted at the time of the request.

    Blocks Stream

    • Protocols: HTTP upgraded to WebSocket
    • Encoding: SCALE
    • Endpoint: /block/stream

    Handshake

    Since the /block/stream endpoint handles continuous two-way data exchange, a WebSocket handshake between the client and server must first be performed to initiate communication with this endpoint.

    Data Exchange

    After establishing a WebSocket connection, the client must send a BlockSubscriptionRequest request with the starting block number provided (i.e., the height value). Then, upon sending the confirmation and BlockMessage messages, the server starts streaming all of the blocks, beginning with the block specified with height up to the most recent one, and then continues to stream new blocks as they are added to the blockchain.

    Configuration / Retrieve

    • Protocol: HTTP
    • Method: GET
    • Encoding: JSON
    • Endpoint: /configuration

    Requests

    A GET request to the endpoint.

    Responses

    CodeResponseDescription
    200OKReturns a subset of configuration parameters serialized into JSON format.

    Example:

    json
    {
    +  "logger": {
    +    "level": "TRACE"
    +  }
    +}

    INFO

    The subset of configuration parameters returned by this operation is equal to the one accepted by the Configuration / Update operation, i.e., it only contains the logger.level parameter as of now.

    Configuration / Update

    • Protocol: HTTP
    • Method: POST
    • Encoding: JSON
    • Endpoint: /configuration

    Requests

    This endpoint expects a subset of configuration parameters serialized into JSON format. Currently, it only supports dynamic updating of the logger.level parameter.

    INFO

    The list of all accepted values is currently unavailable and will be a part of the configuration reference that is still WIP.

    Until then, to get assistance with the acceptable values and their definitions, consult Receive Support for ways to contact us.

    The progress on the configuration reference can be tracked in the following GitHub issue:
    iroha-2-docs > Issue #392: Tracking issue for Configuration Reference as per RFC.

    Example:

    json
    {
    +  "logger": {
    +    "level": "DEBUG"
    +  }
    +}

    Responses

    CodeResponseDescription
    202AcceptedThe request to update the configuration is accepted and is due to be processed.

    Guarantees

    A successful configuration update does not guarantee that the configuration is indeed updated. While a follow-up Configuration / Retrieve request will return updated values, the actual update is performed asynchronously.

    Events

    • Protocols: HTTP upgraded to WebSocket
    • Encoding: SCALE
    • Endpoint: /events

    Transaction Events

    The status of a transaction event can be one of the following:

    • Validating — The transaction has been successfully submitted and is currently being validated by peers.
    • Committed — The transaction has been successfully validated and is committed to the blockchain.
    • Rejected — The transaction has been rejected by at least one peer and is not committed to the blockchain.

    All transactions are designated with the Validating status upon creation, which later proceeds to either Committed or Rejected. However, due to the distributed nature of the network, some peers might receive events out of order (e.g., Committed before Validating).

    Some peers in the network may be offline for the validation round. If a client connects to them while they are offline, the peers might not respond with the Validating status. But when the offline peers come back online they will automatically synchronize the blocks. These peers are then guaranteed to respond with either Committed or Rejected status, depending on the information found in the block.

    Handshake

    Since the /events endpoint handles continuous two-way data exchange, a WebSocket handshake between the client and server must first be performed to initiate communication with this endpoint.

    Data Exchange

    After establishing a WebSocket connection, the client must send an EventSubscriptionRequest request, after which the server sends an EventMessage response.

    Health

    • Protocol: HTTP
    • Method: GET
    • Encoding: JSON
    • Endpoint: /health

    Requests

    A GET request to the endpoint.

    Responses

    CodeResponseDescription
    200Health StatusReturns the current status of the peer submitting the request.

    Example:

    json
    "Healthy"

    Metrics

    INFO

    This operation requires the Iroha 2 network to be established with the telemetry feature enabled.

    • Protocol: HTTP
    • Method: GET
    • Encoding: JSON
    • Endpoint: /metrics

    Responses

    CodeResponseDescription
    200MetricsReturns a report on 8 out of 10 Prometheus metrics.

    Example:

    Example 200 Metrics response
    bash
    # HELP accounts User accounts registered at this time
    +# TYPE accounts gauge
    +accounts{domain="genesis"} 1
    +accounts{domain="wonderland"} 1
    +# HELP block_height Current block height
    +# TYPE block_height counter
    +block_height 1
    +# HELP connected_peers Total number of currently connected peers
    +# TYPE connected_peers gauge
    +connected_peers 0
    +# HELP domains Total number of domains
    +# TYPE domains gauge
    +domains 2
    +# HELP tx_amount average amount involved in a transaction on this peer
    +# TYPE tx_amount histogram
    +tx_amount_bucket{le="0.005"} 0
    +tx_amount_bucket{le="0.01"} 0
    +tx_amount_bucket{le="0.025"} 0
    +tx_amount_bucket{le="0.05"} 0
    +tx_amount_bucket{le="0.1"} 0
    +tx_amount_bucket{le="0.25"} 0
    +tx_amount_bucket{le="0.5"} 0
    +tx_amount_bucket{le="1"} 0
    +tx_amount_bucket{le="2.5"} 0
    +tx_amount_bucket{le="5"} 0
    +tx_amount_bucket{le="10"} 0
    +tx_amount_bucket{le="+Inf"} 2
    +tx_amount_sum 26
    +tx_amount_count 2
    +# HELP txs Transactions committed
    +# TYPE txs counter
    +txs{type="accepted"} 1
    +txs{type="rejected"} 0
    +txs{type="total"} 1
    +# HELP uptime_since_genesis_ms Network up-time, from creation of the genesis block
    +# TYPE uptime_since_genesis_ms gauge
    +uptime_since_genesis_ms 54572974
    +# HELP view_changes Number of view_changes in the current round
    +# TYPE view_changes gauge
    +view_changes 0

    INFO

    To learn more about metrics, see Metrics.

    Pending Transactions

    • Protocol: HTTP
    • Method: GET
    • Encoding: SCALE
    • Endpoint: /pending_transactions

    Requests

    A GET request to the endpoint.

    Responses

    CodeResponseDescription
    200OKReturns a list of pending transactions as SignedTransaction objects encoded with SCALE; must be decoded by the client.

    Query

    • Protocol: HTTP
    • Method: POST
    • Encoding: SCALE
    • Endpoint: /query

    Requests

    This endpoint expects requests with two shapes:

    Start a query:

    OR

    Get the next batch of a previously started query:

    • Parameters:
      • cursor - specifies a cursor previously returned as part of query response

    Request

    Responses

    CodeResponseBodyDescription
    200SuccessBatchedResponse<QueryOutputBox>Successful query request
    400Conversion ErrorQueryExecutionFail::Conversion(String)Invalid asset query for the actual asset type
    400Cursor ErrorQueryExecutionFail::UnknownCursorAn invalid cursor was provided in the batch request
    400FetchSizeTooBig ErrorQueryExecutionFail::FetchSizeTooBigFetch size specified in the query request is too large
    400InvalidSingularParameters ErrorQueryExecutionFail::InvalidSingularParametersSpecified query parameters are not applicable to the (singular) query type
    401Signature ErrorQueryExecutionFail::Signature(String)The signature on the query is incorrect
    403Permission ErrorQueryExecutionFail::Permission(String)The user does not have permission to execute this query
    404Find ErrorQueryExecutionFail::Find(FindError)The queried object was not found

    INFO

    The 200 Success response returns results that are ordered by id, which use Rust's PartialOrd and Ord traits.

    Account Not Found 404

    Whether each prerequisite object was found and FindError:

    DomainAccountFindError
    N-FindError::Domain(DomainId)
    YNFindError::Account(AccountId)

    Asset Not Found 404

    Whether each prerequisite object was found and FindError:

    DomainAccountAsset DefinitionAssetFindError
    N---FindError::Domain(DomainId)
    YN--FindError::Account(AccountId)
    Y-N-FindError::AssetDefinition(AssetDefinitionId)
    YYYNFindError::Asset(AssetId)

    Schema

    INFO

    This operation requires the Iroha 2 network to be established with the schema feature enabled.

    • Protocol: HTTP
    • Method: GET
    • Encoding: JSON
    • Endpoint: /schema

    Requests

    A GET request to the endpoint.

    Responses

    CodeResponseDescription
    200OKReturns the Rust data structures and types of the entire Data Model Schema as JSON objects.

    Status

    INFO

    This operation requires the Iroha 2 network to be established with the telemetry feature enabled.

    • Protocol: HTTP
    • Method: GET
    • Encoding: JSON or SCALE
    • Endpoint: /status

    Requests

    A GET request to the endpoint.

    This endpoint also accepts the following:

    • Header: Specifies the encoding of the retrieved data.
      Can be set to one of the following:
      • Accept: application/x-parity-scale — the retrieved data is encoded with SCALE.
      • Accept: application/json — the retrieved data is encoded with JSON.

    If no header is specified in the request, the Accept: application/json header is used by default.

    Responses

    CodeResponseDescription
    200Iroha StatusReturns the Iroha network status report encoded as specified in the header of the request.

    The response body has the following structure:

    rust
    struct Status {
    +    /// Number of connected peers, except for the reporting peer itself
    +    peers: u64,
    +    /// Number of committed blocks
    +    blocks: u64,
    +    /// Number of accepted transactions
    +    txs_accepted: u64,
    +    /// Number of rejected transactions
    +    txs_rejected: u64,
    +    /// Uptime since genesis block creation
    +    uptime: Uptime,
    +    /// Number of view changes in the current round
    +    view_changes: u64,
    +    /// Number of the transactions in the queue
    +    queue_size: u64,
    +}
    +
    +struct Uptime {
    +    secs: u64,
    +    nanos: u32
    +}
    Examples

    The following examples represent the same data:

    json
    {
    +  "peers": 4,
    +  "blocks": 5,
    +  "txs_accepted": 31,
    +  "txs_rejected": 3,
    +  "uptime": {
    +    "secs": 5,
    +    "nanos": 937000000
    +  },
    +  "view_changes": 2,
    +  "queue_size": 18
    +}
    10 14 7C 0C 14 40 7C D9 37 08 48

    JSON Precision Lost

    Almost all fields in the Status structure are 64-bit integers, and they are encoded in JSON as-is. Since native JSON's number type according to the specification effectively is f64, the precision might be lost on deserialization, for example, in JavaScript's JSON.parse.

    For more details, see the related GitHub issue.

    Compact Form in SCALE

    Fields with u64 type are serialized in the Compact form.

    Sub-routing

    It is also possible to retrieve the data of a specific struct group or variable within it by adding their path to the endpoint address. The sub-routed values are only returned in the JSON format.

    Examples:

    json
    {
    +  "peers": 4,
    +  "blocks": 5,
    +  "txs_accepted": 31,
    +  "txs_rejected": 3,
    +  "uptime": {
    +    "secs": 5,
    +    "nanos": 937000000
    +  },
    +  "view_changes": 2,
    +  "queue_size": 18
    +}
    json
    4
    json
    {
    +  "secs": 5,
    +  "nanos": 937000000
    +}
    json
    5

    Transaction

    • Protocol: HTTP
    • Method: POST
    • Encoding: SCALE
    • Endpoint: /transaction

    Requests

    This endpoint expects the following data:

    Responses

    CodeResponseDescription
    200Transaction AcceptedTransaction has been accepted, but is not yet guaranteed to have passed consensus.
    400Transaction Rejected (Malformed)Transaction is rejected due to being malformed.
    401Transaction Rejected (Improperly signed)Transaction is rejected due to being improperly signed.
    + + + + \ No newline at end of file