404
That's a Four-Oh-Four.Take me home.
diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index b9563ec1..00000000 --- a/.eslintignore +++ /dev/null @@ -1,3 +0,0 @@ -node_modules -public - diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 0e055065..00000000 --- a/.eslintrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "hexo" -} diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 18a6fd41..00000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2017-2018 nuls.io - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md index 89b8a347..a85e543d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ + # NULS Official Developer Website The website for NULS Developer. You can see the generated files at [nuls-io/nuls-io.github.io](https://github.com/nuls-io/nuls-io.github.io) repository. @@ -28,11 +29,3 @@ $ yarn run build Waiting for you -## License - -Source released under the [MIT license](https://opensource.org/licenses/MIT) - -Power by [HEXO](https://hexo.io) - -Documentation released under the [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) - diff --git a/_config.yml b/_config.yml deleted file mode 100644 index e73f5821..00000000 --- a/_config.yml +++ /dev/null @@ -1,46 +0,0 @@ -title: NULS -subtitle: "NULS is a global blockchain open-source project which is a highly customizable modular blockchain infrastructure." -description: "NULS developer site. Power by HEXO." -author: NULS -language: en -timezone: UTC - -url: https://nuls-io.github.io -root: / -permalink: news/:year/:month/:day/:title/ -archive_dir: news -code_dir: downloads/code -new_post_name: :year-:month-:day-:title.md # File name of new posts -post_asset_folder: true -per_page: 0 -skip_render: README.md - -theme: nuls -deploy: - type: git - repo: git@github.com:nuls-io/nuls-io.github.io.git - branch: master - -highlight: - enable: true - line_number: false - -marked: - gfm: true - pedantic: false - sanitize: false - tables: true - breaks: true - smartLists: true - smartypants: true - modifyAnchors: '' - autolink: true - -twitter: nulsservice -reddit: r/nulsservice/ -telegram: Nulsio -steemit: nuls -github: nuls-io/nuls -facebook: nulscommunity/ -slack: t/nuls/shared_invite/enQtMjQ4MTM4ODAyNTI4LWJjNGMwYTE0YjRlYmFlZGUwM2JhOGE4MDIwZmE4MzA2MDg1YzUyMmVkN2RhZjkyNWMzZjY5ZDU5ZmViMjZjNGQ -gitter: nuls_io diff --git a/docs/.vuepress/components/NavBar.vue b/docs/.vuepress/components/NavBar.vue new file mode 100644 index 00000000..8a042ebb --- /dev/null +++ b/docs/.vuepress/components/NavBar.vue @@ -0,0 +1,107 @@ + + + + + + + \ No newline at end of file diff --git a/docs/.vuepress/components/NavBars.vue b/docs/.vuepress/components/NavBars.vue new file mode 100644 index 00000000..5d418656 --- /dev/null +++ b/docs/.vuepress/components/NavBars.vue @@ -0,0 +1,107 @@ + + + + + + + \ No newline at end of file diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js new file mode 100644 index 00000000..411f615b --- /dev/null +++ b/docs/.vuepress/config.js @@ -0,0 +1,272 @@ +module.exports = { + base : '/', + markdown: { + lineNumbers: false // 代码块显示行号 + }, + locales: { + // 键名是该语言所属的子路径 + // 作为特例,默认语言可以使用 '/' 作为其路径。 + '/': { + title:"NULS", + lang: 'en-US', + description: 'NULS' + }, + '/zh/': { + title:"NULS", + lang: 'zh-CN', + description: 'NULS' + } + }, + head:[ + ['link', { rel: 'icon', href: "/icon.png" }] + ], + themeConfig : { + repo: 'nuls-io/devsite/tree/dev', + editLinks: true, + docsDir: 'docs', + docsBranch: 'dev', + sidebarDepth: 2, + lastUpdated: 'Last Updated', + nav:[ + {text:"Guide",link:"/learn/"}, + {text:"NULS1.0",link:"/NULS1.0/"}, + {text:"NULS2.0",link:"/NULS2.0/"} + ], + locales: { + '/': { + selectText: 'Languages', + label: 'English', + editLinkText: 'Edit this page on GitHub', + sidebar: { + '/learn/': [ + { + title: 'Overview', + children: [ + 'introduction', + 'howToContribute', + ] + }, + { + title: 'Users Guide', + children: [ + 'NULSTransaction', + 'toolsGuide' + ] + }, + { + title: 'NIPs', + children: [ + 'NIPIntroduction', + 'NIP-1', + 'NIP-2', + 'NIP-3', + 'NIP-4', + ] + }, + { + title: 'NULS Portal', + children: [ + 'NULSNav' + ] + }, + ], + '/NULS1.0/':[ + { + title: 'Launch NULS', + children: [ + 'sourceCodeStartNULS', + 'connectMainnet' + ] + }, + { + title: 'Underlying', + children: [ + 'buildPrivateChain', + ] + }, + { + title: 'Smart Contracts', + children: [ + 'startSmartContract', + 'developerManual', + 'GUIForSmartContract', + 'ideaPlugin', + 'NRC-20TokenStandard', + 'smartContractFee', + 'randomImplementations', + 'randomRPC' + ] + }, + { + title: 'Developer Tools', + children: [ + 'sdk', + 'clientCLI' + ] + }, + ], + '/NULS2.0/': [ + { + title: 'Introduction', + collapsable:false, + children: [ + 'NULS2.0Introduction' + ] + }, + { + title: 'Tutorial', + collapsable:false, + children: [ + 'quickStart', + 'developeModule', + 'encryptedMessageDesign', + 'chainBoxGuide', + 'linuxTutorial', + 'nodeGuide' + ] + }, + { + title: 'Smart Contract', + collapsable:false, + children: [ + 'smartContractManual', + 'mavenPackage', + 'NRC-20TokenStandard', + 'NRC-721', + 'smartContractFee', + ] + }, + ] + }, + }, + '/zh/': { + selectText: '选择语言', + // 该语言在下拉菜单中的标签 + label: '简体中文', + // 编辑链接文字 + editLinkText: '在 GitHub 上编辑此页', + // Service Worker 的配置 + nav:[ + {text:"了解NULS",link:"/zh/learn/"}, + {text:"NULS1.0",link:"/zh/NULS1.0/"}, + {text:"NULS2.0",link:"/zh/NULS2.0/"} + ], + sidebar: { + '/zh/learn/': [ + { + title: '总览', + children: [ + 'introduction', + 'howToContribute', + ] + }, + { + title: '用户操作指南', + children: [ + 'clientWalletGuide', + 'lightWalletGuide', + 'NULSTransaction', + 'NULSExplorerGuide', + ] + }, + { + title: 'NIPs', + children: [ + 'NIPIntroduction', + 'NIP-1', + 'NIP-2', + 'NIP-3', + 'NIP-4', + ] + }, + { + title: 'NULS 导航', + children: [ + 'NULSNav', + ] + }, + ], + '/zh/NULS1.0/':[ + { + title: '启动NULS', + children: [ + 'sourceCodeStartNULS', + 'connectMainnet' + ] + }, + { + title: '底层', + children: [ + 'buildPrivateChain' + ] + }, + { + title: '智能合约', + children: [ + 'startSmartContract', + 'developerManual', + 'GUIForSmartContract', + 'ideaPlugin', + 'NRC-20TokenStandard', + 'smartContractFee', + 'randomImplementations', + 'randomRPC', + 'guessTheSize', + + ] + }, + { + title: '开发者工具', + children: [ + 'sdk', + 'clientCLI' + ] + }, + ], + '/zh/NULS2.0/': [ + { + title: '介绍', + collapsable:false, + children: [ + 'NULS2.0Introduction' + ] + }, + { + title: '教程', + collapsable:false, + children: [ + 'quickStart', + 'developeModule', + 'encryptedMessageDesign', + 'chainBoxGuide', + 'linuxTutorial', + 'nodeGuide', + 'multiSignAccount' + ] + }, + { + title: '智能合约', + collapsable:false, + children: [ + 'smartContractManual', + 'mavenPackage', + 'NRC-20TokenStandard', + 'NRC-721', + 'offlineAssembly', + 'assetsOff', + 'vm-sdk', + 'consensusTransaction', + 'excuteResult', + 'triggerPayable', + 'smartContractFee', + ] + }, + ] + }, + } + }, + } +} + + + diff --git a/docs/.vuepress/dist/404.html b/docs/.vuepress/dist/404.html new file mode 100644 index 00000000..f3869297 --- /dev/null +++ b/docs/.vuepress/dist/404.html @@ -0,0 +1,17 @@ + + +
+ + +1 Start wallet, click [contract] and then click [deploy contract] tab page

2 Insert Hex code of contract in textbox
3 Insert contract construction function parameter, and note the required item and value type. If not, it will fail the table verification.

4 Click [advanced option] to alter default value of GasLimit and GasPrice. Other additional information can be inserted too. Such filed must be required. (Optional step)

5 After filling out, click [test contract]. Wallet will conduct a trial deployment for this contract to verify contract legality.

6 After passing this test, click [deploy contract]. In case of password, insert password, and then click [confirm]. If no password, click [confirm]. Then, the system will go to [my contracts] page on which the confirmation progress of deployed contract can be reviewed.
Review the confirmation progress of deployed contract.

7 After confirmation completion
Click [to call] on the right of table to go to [call contract] page
Click contract address to access to contract overview page
1 Start wallet, click [contract] and click [review contract] tab page

2 Insert legal contract address in box, and click [access], showing a panel below it

3 Have two cases after selecting a method
If read-only method, click [call], get the deployment results after network requests met

If readable method (to be linked), click advanced option to alter default value of GasLimit and GasPrice. After clicking [call], generate a transaction, which will consume nuls. Therefore, in case of account password, insert your password. After transaction confirmation, feedback the results.
View smart contract fee details
Transaction on calling contract under confirmation

Transaction on calling contract confirmed

4 If calling linking method, click TxID in panel, to review the details of this transaction to call contract

Details of this transaction to call contract

1 List of my contracts displays the created and collected contracts

Click contract address to access to contract overview page

Click [to call] to access to the [call contract] page

Click [cancel collection] to remove this contract from the list of [my contracts]
3 [Transaction records] display the transactions in this contract. Click TxID to review the details about this transaction.

4 [Contract details] display all methods of this contract, corresponding parameters and returned value type.

5 If the contract is created by current account, click [delete] on the top right of contract overview to delete this contract. After that, contract details are also available, but the method of contract cannot be called.

After releasing Token via smart contract or transferring in different kinds of Token from other accounts, the account have multiple assets.
1 Access to wallet, to review all kinds of assets under this account address.

2 Click [transfer] to access to transfer interface of this kind of asset, insert payee address and transfer amount, to finish transfer of such asset.

3 Click [transaction records] to access to transaction records page of this kind of asset

4 Click [pull-down list] on [transaction records] page to switch among transaction records of different kinds of assets.

5 Click TxID to review the details of this transaction.
Hex coding of NRC-20 Token
504b03041400080808009184264d000000000000000000000000090004004d4554412d494e462ffeca00000300504b0708000000000200000000000000504b03041400080808009184264d000000000000000000000000140000004d4554412d494e462f4d414e49464553542e4d46f34dcccb4c4b2d2ed10d4b2d2acecccfb35230d433e0e5722e4a4d2c494dd175aa040958e819c41b9a982868f8172526e7a42a38e71715e417259600d56bf272f1720100504b07089e7c76534400000045000000504b03040a00000800002f6e264d0000000000000000000000001300000074657374636f6e74726163742f6e726332302f504b03041400080808002f6e264d0000000000000000000000002400000074657374636f6e74726163742f6e726332302f53696d706c65546f6b656e2e636c617373b558fb7313d7153e2bad2d595ec0186cfc005b0697d87a581868420ca5186a1a27d850db3885b44dd6d2da5e90568a766542489b579b479b3469d2e6d990b4494b9226e1116c43689374a6d3ccf49fe83fc274fa9dbbabd54a48f63499fee0bb77efbde79cefbcbebbf2bffef3d9e744b49bfede40113acbc3c33c9ce3e1911045e9a70dd4423f0bd0a3210af04b841ee3e1715e7e2284e1491e7e1ea25fd0538db4919e0ed033216aa25f85e8397a9e577e1da01702f4620852bfe1e1251e5ee6eddff2ec77017a25449d2c10a1d778789d873758ed9b3cfc3e486ff1ca797e799b67ef04e90ffcfc6390de653def05e84f01fa73802e04e87d896443cd6812351f39a52ea889b46acc2526adbc6ecced95a8de3c9b99c9a6250aa6b4a49e51d3a644d2a8448d56d652d393855c2e7d56a2565b34a35af38983fadca86169735a1ee2c11915fa921aa4d6d9670a969e4e8ca9396c364cea73866a15f2303e52bebbef889e4d1885b49948660d2baf26ad84993a9d184ea5f29a69eead6e6e3f7406d4743a7b464b49647d0d8ddfd03c03d8d8d75f2d8ef2a16c4ae320e886365ec8cc68f92975262da29e4daae96935aff3bbb3285bf33a42163e6269a6e54230f2c99d3b12937a268783d9d39a01bded1305c3d233dab46eea101d360ce4c5d2b306c4b757f74275cf24a675ed0c94f8fbfa91d2b622f25bd358bf4f37746bbf44fbfb6e75aed64aa59ad1fe6989d6b0225d4d0f67b2002ed1d672fcc7d43c6ad1d2f2658e44567564427bb0a0e7b5145795a8002e3a89a6fa5649e48abb35c351973d63687989ba569647359a39cd48f15145880c178bb36e414d17346e9cb2ec9fcd152b60cda4a5264fa314c5bbcd08d002238639abe50fe7b319898e7f23f7aa7bd77f12e5372bd4fbac2cc2e974f0d159896e5fc55ecd80051c252084a20712ddb11afa9af8026a2e97cf2e405d936e24f39a6a6ac36245055185d4544a4b4ddbf16d026b55ecaf330b33c2987b28984d17a72cec26e9ff125ef44050b58f0c96a63b3db85cfb21532bbdac2b0a95b6b172b018d7af19cc690ea67dc483c0d55a979cd792a7c1327db5e51335f66a4bd48be21f2c4ee07b74451d5e6a61797fc69c9368f87fb25b5d5368325bc827b5c33ab75c93875907f8b84203945068070f83b453a15db45ba111fa40a10f69b744eb4b77c65daa398f6655e8db74bb4277f2f0173efc117dacd0277431409714ba4c5714fa94ae8299abf0faf8c4a19d3b7aa79cf61859d0981ed754bc2ba30668e4505a354dcd642ca0864585966859a16b741d0265f718aea36ad150689e34850c4a2b749a87cfe886423a692b212b76501159d9bb4229d67837dda350961087bfd2df14fa9c2e4ad4396a9885d9593da9e35cd8e9dc54d8e230f3e10585bea08b0a9d2074767c6a5e0b8baa08670aa6159ed1c273e85f5c08616b5e35c2d97c184cafa6211ede31c0e280d25566c1a19a7076d6b631c0ee7d89532bdfa5c87fa9448ece9cd292d0bca56a4f1d725e7065d68a96b8535160f2c99189a378991a19c798cb9ee15e1aadc993c14c216de9e2936aa056cbd5926dab8a758c5ba5de746ea130aef855ae2c7fae00c7f678ef793b1a7b6f5de9bf7549a28eaa068ea3224131b296d1a1bebb065b895ab27b7c4ec3b9ed556054351ac8db1f00b0d07792e51b92d94c4ecd23b72bb0173e7afc603fc4bdc87cb891fb4e56e30aeac1f773947c14a338d5533353037e0834333b882708024f1f738478820808b42ce67bf077a7e77d081fe6c830edc57c1f56127893f0ac8b5c25e99238f21d8cf562710bedc7a8d807e8bb7400cf6167f7209e12205453e4ab54b46d55458374a88a22ff47158afa5755b48bbe5745915c8928b1aaa2113aec28fa374ed4e1a94596a1ec0ad52f921cb9418113cb145ca486d23414892e9214892d922fd2222f923f12bf428d2df212294bb486a5ae52c3355acb80aed33a3fdd7b839a4e48ceca32adbf46cd975da003d4887127c94859236da2566a4329eca2ed487314491e445a8791d60924398524ef17bf0e0550c7219e0d8838f08ccbc52766dfc739bf980d0afd7761de2ee3d8a8f0fcd611e40a018ec51750c12612401c8a5ea70d3efa92368ec7bfa2000273291e73965a86e476f92b0a6291671c7e5978d585dfa604ac6b81b119285b11eead48fe6dc85b0c212f799170bd48d0111a73d2368e990fd23d7414fefb21bb868e4142a61f3809b5f7f6606f022b6bc977935a033479935a0234559664f67b8dafc2d7e334ede4fd11c090f1ec8d4491a2f832b546a21837456218db3875519e71d6e452a1b60af0f7500340af03d81640de0a40ec58c4d6e73ad64bf73a8ef5d20f85633c3b26d2c3e036f8aba603f795938e2721c299ec8dfe9302f20592fdd7a89dabac989a96b1989d9ab118e7c0ef81781cd19aa60e40e882f1add0c910c3b63e0f443bf61d14a2fb00cc27a2da48fee001e926b5550b69407291fe887eec0453874dd6dc1d412c631cc568cc892216785e11c76611abfb29480f20892ac868c603b0db05d82d222789d93101b06a5a7fe22279c041d211710c77dca0ce2288cde520d68a937348e63cba4ff700e8700174889a94c46c0500f7bb00e6d002aca2a708604b11805858a2ae1a3832c061c0cdac07478f8ba3c7c5d1031f6be2505d1c578183633c120186eea2edf1587c89c2e769bd5840e52040174829626d5d01abdfd3e126a26c017701d5b6802a7a0897d7c3e8f3739e461871b18fb8d84790e6dda2c3efa0a46804aeb706eee25e145bb09a533efe04c49c9d7ac221eb30ea0be886e448bbccdec57988c6da6578d703974a3c6b77c3a328b4c760f571da001ddde8ac1213855d9c619a7570869146bb61c34ec3065121770b26f2f147ae83e711074f97074fbc79eb326d2ba2e92d436397fd53d0f634ada76750f6cf7a9074b948ba5c245d2e922e1749ab8b447791fc033bac63c88e8597bf6db26e772eb221596cb63b7754bb1c8bdb3346e965f1e7a0ef79feb721b5d30b609017c1cf2fe1267ad98378c8453ce4221e72110f398837e2563b053e2fb1b8bdb2072b9cff20816c12607148e16783e3d139ec72b410ca25fad67824d6bc7d996e2bbad7108d23e23d25e8de74bf02c67a1557c76b08f8eb80fe86a72cb7b990b7a1e5c69c2f18bbb5eb9190fb04641fff887180980e906e07483cd6dcc7192e82e8ad046167f92da83b8f9a7b1bf17cc703c04b6e990a72ab47ac8b00f073c70170126f1ccf4db807d673d3a285df2cdd0897dde60c8963ef220aef0983adb6986b7093302389a0d791aff98024ec3ce8d8c939f74d6724ca4166dee0b2ae6ecb76f202f4bc0fbb1f801e3ff41057a76bb393f2c226cf4cf78a81f556c7bae558d71ceb6d55bc8c5da3fe4a373f863b9f784cb6b926db1c37795610df45150e2fb825e6135e6caee170bcccacedf16528ba02089fc29fab9eb46e76cd6f763ddeec78cc3306e22ff7fd8ca89887e89742b98f9ac0a2cf820d3bf17c951afe0b504b0708b86173e8da09000014180000504b03041400080808002f6e264d0000000000000000000000001e00000074657374636f6e74726163742f6e726332302f4e524332302e636c617373a5525d4f1341143d03b5cb16aa28a8e0b78490d6079710a30f3c5522491322a6451e789b6e2f657076b6cecc96f0d77cf007f8a38c776ba954ba69a29becceceb967ceb977eefdf1f3db77006fb011e05980e7015e08541bfdbe4d07527f1890f1024b4d63c8ee69e91cb9002f997164a571a764478c92910909acd6ea07e77220232d4d2f6a7bab4c6f5760bd9519af123a564e7534358c49bdf42a354e60eb40a591c9b48be2d4782b631fb9ee97488e39d1b1a20b1629bbcba4936a81852ec52a919a0fcfd7ea4d8145cf54ddcefa7d7d29b076954322fd59f45ef59ac6538f2c4b841dc989c574782af0b636ddb8d1ed5a726eb7506463b2984fd272e99eec4455af6656d5a2af99b2d465c5053fba4c817733b29a9e54fd847b7425b26fd344e0f32ca17fb409e47034b8d7a1d43abdc8af53e0e8bfdc0aafbad24e331bd3bed2ec51f9d8dadbd97e9d53b9c99e9c1f8b191bef6c47c3b8c0f29f013cec9c53ccd3b955c4defc6bd08b8913f35e16109843fe8425ee1f42de577857e67511606c690a56c5ed1bd81d2cdfc0eee21eab5fc3b0c26f909bae0e09f7f180ff73b03af71b1c871e626d145a99bf1e1a13d68bcf3ec2e329be9334263c197e9fe216af79a2b94f89cbcd0f05087f01504b070846c6797bcf01000052040000504b03041400080808002f6e264d0000000000000000000000002c00000074657374636f6e74726163742f6e726332302f4e5243323024417070726f76616c4576656e742e636c6173738d565b6f1b4514fec6bbde75b69bbb49d224b4e985e2d8491d42b8e6d2242681809394a435b4406163af926d9ddd74771d90a0129540ea033c801020242e2f252f790089ba0824c45390f82ffc03049c99ddb88963273cf8cc99b367e67cdf7c6746fef39f5f7e0330826b1ae2b8d0000593dc4c7133cd631915331a66f1bc8617b899c51cf7e654bca8e1182ec4f0121fb3dcccc7b010c322772f72f3b28a2515cb0c51e76ddb74194e642d276d978a5e3aefd8be6be4fdb457b8919e2a145cd3f34619546fc3b40b3c35ba69144b264347f6bab169a4d70d7f2d3d6dadced9beb96aba94aa8c59b6e54f305c4e1cbeeb115f6b6edf9f6390334e810034672ddb5c28adaf98ee2563a54891b6ac93378a39c3b5f83c0ccafe9ae531344e6d6cb80e619fd9346d9f419fb38979a668789e499f1359dff4fc0a10dbcd0f0fa5179632c34367f72d247ea7974ab66fad9b39cbb3a8c245c335d64ddf74a76cdbf10ddf726cda2f599b9c51c9492f99374b966b1668c7d8aae92f0642f425fa8f9222e655b24f1d71c2fcb434da7c79573ccddb33e1657381985d54b68e9cbc5c98753c515f1485e8184562fe50985434ecd5f4e2ca7533ef8ff65f65600e17e8c02721904182342efb46fec6bcb12174a3e6a6d26b86b716882d25fae7a808b12a152999d124e63bcbbe6bd9ab0cf15df862e7204a3b6bcb4ec9cd9bb316ef034da8799ea7e9e8c1251d1de8d4d1c5cd7174ebb88c9c8a5718cefdbf4e50f1aa8e213ca6e28a8ea7f03443673584e9925514271ddfb7f25d71e9c6755cc56bdcbc4ee006fac20b364ec406fac41d13196fe818c518434bf5c93174d7d43eec6f3ab05c20b1e87186f67d67248274445df5c832f41ed65ac4a9562b9044c60627c230983828c94195c2231aadcadfed9b43f27b1399fa9f718a9ec938a81b2121c295a6c734c2c51623e94da346df7bd04bf3876956a451a6319ebc0f964cdd432439700f5272f01ee41fc5aa13643b10257b93325d34c043137cb4a38493144d06ebd1873380f0785d263c5e39223c5e5bc259f2db25faf80839fbed393c4a96434ad3c89747933f21f24305832282ef889a7a9010d6a4770cfde1e209cae61515c1e501034d44dfa335b7c40e1d415605b512a2a637ac2610a91ac8fb3581a46a0391aa817c406b3eac03a42b043280c11a40e46a20776a02392f161d00225703f988d67c5c0708d78c17a6eb1eeef517e54834de4ea6be4754de4eeda02959463445bfbb884adba9dfa1cc73dd76a8a36818a05f19ea5768dea2db2ee294c5cf3348902826ed4d907613e41db4f281627219b12d3473ef0fa8f21664699b404882463701053e818a4fe9e43e23989f13e52ff026be14b4fa02c0155ab7318cc7059d02fdcf3843849e100daaab4dec6ff4aa7852619d0a8b6b939c3abd7021f59fc3639c09d8352605b3060e66ace564cf5ac08987a530fcd66e5c0ee244430be23d0fe0b789dbf335dda66fa879be4506dfed51632684dd4ea09fc1b30485831d84d23ac9fea55b1e21b804937c847e84b1dcfe292da2a73464718db6e58d32f22b8e5db90fbdadb14c0a0a2acd6d2d812f71bf35f0097373cbad32daca68af6ebcbb7b1a6f24041ac1b8b013381d3e350a9ea367a9e13f504b0708a7368aa198040000da090000504b03041400080808002f6e264d0000000000000000000000002c00000074657374636f6e74726163742f6e726332302f4e52433230245472616e736665724576656e742e636c6173738d56dd531b5514ffddec6637a40be14ba0806dfa610d49208868ab7c13a14503b44063a15abb245bd836ece2ee8617c787fe1bbe2b2f3cd419491d9d717cc219ff17ff03473df7ee924248c0879c7beed973eef99df33bf74efefce797df008ce249149d986a8282692e66b898e5b6ac8ab928e671378a7b5ccc63816b0b2a3e8de212a622f88caf392e1623588a6099abf7b978a06245c52a83fcccb17718aee44c3b63954b6ea6605b9ea317bc8c5b7c919929161dc375c718429ecd10ded34b6583a12bf75cdfd3333bbab79d9935b7162ccfd8321cf252c64dcbf426191e26ce3ff082af758f1fc813dcac5d2400b19c69194be59d4dc359d3374b6469cfd905bd94d71d93ef03a3ec6d9b2e43f39aa35bee33c399db332c8f415bb02cc3c99674d735e87322e719ae570562398591e1ccd24a7664f8e6a940aaeffa4ad9f2cc1d236fba2665b8af3bfa8ee119ce8c65d99eee99b645e725eb17a7577d322bc6d765d3318a74a2ba6578f382827862e0221254f7d8f9da05fde5bd0ad3d16b9c35d75f23b4cffb04f650ae061446dcaad7e5446322142a412f51b56f054e25dddaca2c6f3e370aded8c00603b33929673e09527422a179d5d30b2f16f55dc1158d32a5ded6dd6d9f602931b04049a89672899c196d229ebdea39a6b5c5d0790c5f9cec5be9e4e8aa5d760ac6bcc9b98f0a0687b89b863eac69e842b7861e2e2ea357c343e4557cce70ebffb1afe2918661bca7625dc36ddc61e8ae85305b364b45c361e83815f90dbf62131a36f0988b2f889174dcb327a8a4745cdc28f1f14b0d63186768aded19436f5dae8369a656e57d72c54453f653dd11466a4e4fa33219facf1b25ea76bd212072f4dd5dc32a320c26ce9271969fa0396335fec713738e7f7f22dbf833aed173d8099a434808718ee9d10c719ac54a4cd31aa5ef7de8a7fddbb42bd12ad3da997c0d964c1d22944c1f424a0e1e42fe51445d21d98530c934790ea209436841061d340057c99af4e311c70d40683c2f131acf1c121acf2de126e9318904c33b27e42dbc4b92c3c9d0ca43c3c99f107a55cdaf08e3fb229fe63b04f9e8c5c240103c49de3c9b22ea78833e2aacb729e68e38a1cbf7aa225602c4f45ad50522d50219ab0b24551f88540b648a62a61b00e90980a4a9d16781c8b540b275810c89a03340e45a207729e65e03209c2f9e982e7970d65fe4c3a97b994cfd80b07c903a424bb282708a7edf232c1da47e87b2c8793ba269a2254dbf0ad4ef10db47342dece4c5fbe93b4864934e3a48c70ef211daf84236b982c83e625cfb03aabc0f593a20109228a397800239a858a4ce2d13cc0754f20abec2aa282bee03ae96f512233444bc9c22fd97b841057d208653535bd8dfe857f1a1c2ba15d6199de6a5d3bb1694fe73d0c639bfbae6a4a8ac8983196fbddab7edd7c4cd52607e7a6c977d3b9511f5ed7d6fe0b78b9bf3886ed23a0dcf06b1f9f8041b7301ec0e02fd113e26281cec2094b669f62fddf010c12598a423d0438ce54f6f29889ed1a08a27742c1f94d15f7169fd35b4f6e60a31284a89b5b7fabac4f5365f27ccb1d66f2b68afa0a376f09e9e18bcd100680813424ee27af0cc28f8849ea4a6ff00504b0708d092051588040000be090000504b010214001400080808009184264d0000000002000000000000000900040000000000000000000000000000004d4554412d494e462ffeca0000504b010214001400080808009184264d9e7c7653440000004500000014000000000000000000000000003d0000004d4554412d494e462f4d414e49464553542e4d46504b01020a000a00000800002f6e264d0000000000000000000000001300000000000000000000000000c300000074657374636f6e74726163742f6e726332302f504b010214001400080808002f6e264db86173e8da090000141800002400000000000000000000000000f400000074657374636f6e74726163742f6e726332302f53696d706c65546f6b656e2e636c617373504b010214001400080808002f6e264d46c6797bcf010000520400001e00000000000000000000000000200b000074657374636f6e74726163742f6e726332302f4e524332302e636c617373504b010214001400080808002f6e264da7368aa198040000da0900002c000000000000000000000000003b0d000074657374636f6e74726163742f6e726332302f4e5243323024417070726f76616c4576656e742e636c617373504b010214001400080808002f6e264dd092051588040000be0900002c000000000000000000000000002d12000074657374636f6e74726163742f6e726332302f4e52433230245472616e736665724576656e742e636c617373504b05060000000007000700100200000f1700000000
+
+
++ ← + + Development Manual + + IDEA Plugin + + → +
A standard interface for tokens.
The following standard allows for the implementation of a standard API for tokens within smart contracts. +This standard provides basic functionality to transfer tokens, as well as allow tokens to be approved so they can be spent by another on-chain third party.
A standard interface allows any tokens on Nuls to be re-used by other applications: from wallets to decentralized exchanges.
NOTE: Callers MUST handle false from return boolean. Callers MUST NOT assume that false is never returned!
Returns the name of the token - e.g. "MyToken".
@View
+public String name();
+Returns the symbol of the token. E.g. "MT".
@View
+public String symbol();
+Returns the number of decimals the token uses - e.g. 8, means to divide the token amount by 100000000 to get its user representation.
@View
+public int decimals();
+Returns the total token supply.
@View
+public BigInteger totalSupply();
+Returns the account balance of another account with address owner.
@View
+public BigInteger balanceOf(@Required Address owner);
+Transfers value amount of tokens to address to, and MUST fire the TransferEvent event.
+The function SHOULD revert if the from account balance does not have enough tokens to spend.
A token contract which creates new tokens SHOULD trigger a Transfer event with the from address set to null when tokens are created.
Note Transfers of 0 values MUST be treated as normal transfers and fire the TransferEvent event.
public boolean transfer(@Required Address to, @Required BigInteger value);
+Transfers value amount of tokens from address from to address to, and MUST fire the TransferEvent event.
The transferFrom method is used for a withdraw workflow, allowing contracts to transfer tokens on your behalf.
+This can be used for example to allow a contract to transfer tokens on your behalf and/or to charge fees in sub-currencies.
+The function SHOULD revert unless the from account has deliberately authorized the sender of the message via some mechanism, such as calling approve(@Required Address spender, @Required BigInteger value).
Note Transfers of 0 values MUST be treated as normal transfers and fire the TransferEvent event.
public boolean transferFrom(@Required Address from, @Required Address to, @Required BigInteger value);
+Allows spender to withdraw from your account multiple times, up to the value amount. If this function is called again it overwrites the current allowance with value.
public boolean approve(@Required Address spender, @Required BigInteger value);
+Returns the amount which spender is still allowed to withdraw from owner.
@View
+public BigInteger allowance(@Required Address owner, @Required Address spender);
+MUST trigger when tokens are transferred, including zero value transfers.
A token contract which creates new tokens SHOULD trigger a Transfer event with the from address set to null when tokens are created.
public TransferEvent(Address from, @Required Address to, @Required BigInteger value)
+MUST trigger on any successful call to approve(@Required Address spender, @Required BigInteger value).
public ApprovalEvent(@Required Address owner, @Required Address spender, @Required BigInteger value)
++ ← + + IDEA Plugin + + Service charge + + → +
This tutorial guides you to build a private chain based on NULS source code, to make is easier for users to learn about the operation, development or experiment of the NULS Blockchain. By building a chain to fully understand the operation of each node and data interaction, we can better grasp the overall operating mechanism of the NULS Blockchain, which is conducive to further research. We assume that readers have the skills to set up and debug a Java development environment.
Since blockchain is a decentralized network composed of multiple nodes, we will take a private chain with three nodes as an example. Although we recommend using a Linux server to run the NULS main-net consensus node, in this tutorial, we choose macOS system that can set up a Java development environment to run and debug nodes.
First, clone the NULS source code using IntelliJ IDEA and open the project. Make sure JDK is the jdk1.8 version and Maven is configured correctly.

We also need to set up a seed node to maintain the operation of the blockchain, i.e., to package and forge blocks. In addition, we need to prepare a block-forging address (including private key, to import into the seed node), which can be prepared in advance.
In this tutorial, the initial block-forging address we prepare is:
+Nse4zpZHsUuU7h5ymv28pcGbwHju3joV
PS: You may find that the first few letters of the address we prepare differs from those of the test-net address in the figure, which is for the sake of distinguishing the test-net address from the main-net address, so as to avoid confusion that may result in adverse consequences. Specifically, we set the test-net address to start with "TT" and the main-net address to start with "Ns". This tutorial uses the NULS main-branch code, so the address starts with "Ns". If you prefer to custom the starting letters of the private-chain account address, you can try to modify the chain.id parameter in the nuls.ini file. The parameters of the same chain must be in consistence.
[network]
+Bootstrap=io.nuls.network.netty.module.impl.NettyNetworkModuleBootstrap
+Network.server.port=8003
+Network.magic=20190101
+Network.max.in=100
+Network.max.out=10
+Network.seed.ip=192.168.1.1:8003
+
+[consensus]
+Bootstrap=io.nuls.consensus.poc.module.impl.PocConsensusModuleBootstrap
+Partake.packing=true
+Min.upgrade.delay=1000
+Seed.nodes=Nse4zpZHsUuU7h5ymv28pcGbwHju3joV
+work.seed.ip to the ip and port of the seed node.seed.nodes to the block-forging address.network.magic of all nodes in the private chain is a must.<appender-ref ref="STDOUT"/> in logback.xml.io.nuls.client.Bootstrap.sysStart(Bootstrap.java:156):bestHeight:0 , txCount : 1 io.nuls.client.Bootstrap.sysStart(Bootstrap.java:174):height:0,count:2, hash :xxxxxxx,192.168.1.2:8003,192.168.1.2:8003
+
+Nse4zpZHsUuU7h5ymv28pcGbwHju3joV via wallet interface of the seed node A. After a while, you can see the latest height displayed in the console increasing, which indicates that the network is producing new blocks. At the same time, the height of the node B, C will also increase and the height of the three nodes will remain the same. At this point, the setup of the private chain network is completed.This tutorial mainly introduces the easiest way to build a private chain for the development and debugging of NULS, without modification on the source code of NULS. If you want to dig deeper into NULS, you can refer to the relevant documentation of NULS to modify and debug the source code. Maybe you will find more secrets!
+ ← + + Connect Test-net + + RPC-TOOL design document + + → +
The User Manual (hereinafter referred to as Manual) is for the full-node wallet of NULS (Linux). Before reading this Manual, please know about the basic operation and usage of Linux system. The Manual includes operations for creating account, importing account, transferring, building nodes, agency and others with NULS wallet. It is recommended to build stable NULS nodes with Linux system server.
| Version | Date updated | Contents |
|---|---|---|
| V1.0.0 | 2018-07-12 | All functions of official version |
Server for creating NULS nodes shall be with configurations not lower than the following
| CPU | Memory | Hard Disk | Broadband |
|---|---|---|---|
| Quad-core 3.0GHz | 16G | 128G Hard Disk | 20M Uplink |
Recommendation
| CPU | Memory | Hard Disk | Broadband |
|---|---|---|---|
| 8-core 3.0GHz | 32G | 256G Hard Disk | 100M Uplink |
Linux system
It is recommended to use core of version 2.6.32 or higher.
NULS official website for downloading the latest full-node wallet:http://nuls.io/wallet
GitHub:https://github.com/nuls-io/nuls-wallet-release
Enter wallet download on NULS website,and select Linux download. MEGA and Baidu Cloud Disk are available and optional for users.
The following is for downloading wallet (v1.0.0) in Linux system:
$ wget https://media.githubusercontent.com/media/nuls-io/nuls-wallet-release/master/NULS-Wallet-linux64-1.0.0.tar.gz
+Note: the downloading link for the subsequent versions is subject to change.
Extract downloaded files in Linux system
$ tar -zxf NULS-Wallet-linux64-1.0.0.tar.gz
+Enter bin catalogue and run startup script to start full-node wallet
$ cd bin
+$ ./start.sh
+Upon confirming the wallet is started, start the command line of wallet to run it.
Enter bin catalogue to execute the following commands:
$ ./cmd.sh
+Display NULS naming prompt nuls>>>, and then directly input NULS wallet operation command to run it.
The following gives an example of account creating:
nuls>>> create
+Please enter the password (password is between 8 and 20 inclusive of numbers and letters), If you do not want to set a password, return directly.
+Enter your password:*********
+Please confirm new password:*********
+[ "Nse9EtaRwgVgN42pxURgZjUR33LUx1j1" ]
+nuls>>>
+Command create is to create a single account, insert password, confirm the inserted password, and receive the account address if the account is created successfully.
All commands for output and printing
| Parameter | Description |
|---|---|
| -a | Formatting printing command, optional |
Return message help
getaccount <address> --get account information
+Return message help -a
getaccount <address> --get account information
+ OPTIONS:
+ <address> the account address - Required
+Example
nuls>>> help
+nuls>>> help -a
+Create account and return to account addresses collection
| Parameter | Description |
|---|---|
| [number] | Quantity of accounts created, optional |
Upon creating account, receive prompt of password inserting; if the account is not to have a password, ignore it and directly enter;
Return accounts collection
[ "NsdwsD8n3GrW9Sx43eLZ3xv8C858ovE2", "Nse6iqzBZsBtL5c46xaHhAhAqVDv3zQQ" ]
+Example, to create 2 accounts without password
nuls>>> create 2
+Please enter the password (password is between 8 and 20 inclusive of numbers and letters), If you do not want to set a password, return directly.
+Enter your password:
+[ "NsdwsD8n3GrW9Sx43eLZ3xv8C858ovE2", "Nse6iqzBZsBtL5c46xaHhAhAqVDv3zQQ" ]
+For backup of account, generate a backup file, titled as account address, with .keystore file extension as and file as account
| Parameter | Description |
|---|---|
| <address> | Account address, required |
| [path] | The target folder of backup files, defaults to be the current folder, optional |
Note: insert current password when backup the encrypted account, and use such password when importing the backup files to generate account. It is permitted but not recommended to backup an unencrypted account, because it is not safe.
Return message
The path to the backup file is /nuls/bin/NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy.keystore
+Example: backup of an account with password
nuls>>> backup NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy
+Please enter the password.
+Enter your password:**********
+The path to the backup file is /nuls/bin/NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy.keystore
+Remove local account according to account address; if the account is encrypted, insert password.
| Parameter | Description |
|---|---|
| <address> | Account address, required |
Return message
Success
+Example
nuls>>> remove NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy
+Please enter the password.
+Enter your password:**********
+Success
+Set password for the unencrypted accounts based on account address. No password setting for the encrypted accounts.
| Parameter | Description |
|---|---|
| <address> | Account address, required |
Return message
Success
+Example
nuls>>> setpwd Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT
+Please enter the new password(8-20 characters, the combination of letters and numbers).
+Enter your new password:**********
+Please confirm new password:**********
+Success
+Change password of the encrypted accounts based on account address. No password changing for the unencrypted accounts. Require original password when replacing it with a new one.
| Parameter | Description |
|---|---|
| <address> | Account address, required |
Return message
Success
+Example
nuls>>> resetpwd Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT
+Enter your old password:**********
+Please enter the new password(8-20 characters, the combination of letters and numbers).
+Enter your new password:**********
+Please confirm new password:**********
+Success
+Set a nickname for account. If the account is used to create nodes, the nickname will be displayed as node source.
| Parameter | Description |
|---|---|
| <address> | Account address, required |
| <alias> | Nickname, required |
Return message, transaction hash
"0020f94f36aefd59f9cca9bff3c018fc287dc6c0bcd7fbeb047133cadb5747e7d98d"
+Example
nuls>>> setalias Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT nuls_alias
+"0020f94f36aefd59f9cca9bff3c018fc287dc6c0bcd7fbeb047133cadb5747e7d98d"
+Imported account keystore files, and create a local account. Receive failure to import if there is an existing local account.
| Parameter | Description |
|---|---|
| <path> | Address of keystore files to be imported, required |
Note: when importing keystore files to create an account, if they are encrypted, the password for backup of keystore files is required.
Return message, imported account address
"NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy"
+Example
nuls>>> importkeystore /home/charlie/bin/NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy.keystore
+Please enter the password (password is between 8 and 20 inclusive of numbers and letters), If you do not want to set a password, return directly.
+Enter your password:**********
+"NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy"
+Import account’s private key and create a local account. Receive failure to import if there is an existing local account.
| Parameter | Description |
|---|---|
| <privatekey> | Account’s private key, required |
注意:Note: when importing such private key, set a new password. If the account does not need to be encrypted, users do not need to insert a new password.
Return message, imported account address
"NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy"
+Example
nuls>>> import 00a166d10c2cc4cd8f76449ff699ab3eee44fe4f82b4bb866f7bba02751a6fd655
+Please enter the password (password is between 8 and 20 inclusive of numbers and letters), If you do not want to set a password, return directly.
+Enter your password:**********
+Please confirm new password:**********
+"NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy"
+Import account’s private key and create a local account. Receive failure to realize overwritten import if there is an existing local account.
| Parameter | Description |
|---|---|
| <privatekey> | Account’s private key, required |
Note: when importing account’s private key, set a new password. If the account does not need to be encrypted, users do not need to insert a new password.
Overwritten import: if the account exists locally, the password before importing will be replaced with a new password after performing overwritten import; if the account is not encrypted after this import, the account will be unencrypted account (even though the account is encrypted before such import).
Return message, imported account address
"NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy"
+Example
nuls>>> import 00a166d10c2cc4cd8f76449ff699ab3eee44fe4f82b4bb866f7bba02751a6fd655
+Please enter the password (password is between 8 and 20 inclusive of numbers and letters), If you do not want to set a password, return directly.
+Enter your password:**********
+Please confirm new password:**********
+"NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy"
+Inquire account information based on account address
| Parameter | Description |
|---|---|
| <address> | Account address, required |
Return message
{
+ "address" : "NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy",//Account address
+ "alias" : null,//Nickname
+ "pubKey" : "03f364bae9bb632a9b957522f150cb501dbc950e3700cff7a3679ed8820c486875",//Public key
+ "priKey" : "",//Private key (unavailable if the account is encrypted)
+ "encryptedPriKey" : "712149fad00350cdfee4d20850a9e5c1e9d7e9c1562dabc593cbc9b5ac57e99f1549748ff2421b3f6830f34bff7c69d8",//Private key after encryption (unavailable if the account is encrypted)
+ "extend" : null,
+ "createTime" : "2018-07-13 11:39:14",//Creation time
+ "encrypted" : true//Encrypted or not (set password or not)
+}
+Example
nuls>>> getaccount NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy
+{
+ "address" : "NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy",
+ "alias" : null,
+ "pubKey" : "03f364bae9bb632a9b957522f150cb501dbc950e3700cff7a3679ed8820c486875",
+ "priKey" : "",
+ "encryptedPriKey" : "712149fad00350cdfee4d20850a9e5c1e9d7e9c1562dabc593cbc9b5ac57e99f1549748ff2421b3f6830f34bff7c69d8",
+ "extend" : null,
+ "createTime" : "2018-07-13 11:39:14",
+ "encrypted" : true
+}
+Inquire list of accounts as per paging parameter, and output all accounts in reverse sequence of creation time
| Parameter | Description |
|---|---|
| <pageNumber> | Page, to get the data on which page, required |
| <pageSize> | Number of data displayed on each page, required |
Return message, output accounts collection
[ {
+ "address" : "NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy",//Account address
+ "alias" : null,//Nickname
+ "pubKey" : "03f364bae9bb632a9b957522f150cb501dbc950e3700cff7a3679ed8820c486875",// Public key
+ "priKey" : "",//Private key (unavailable if the account is encrypted)
+ "encryptedPriKey" : "712149fad00350cdfee4d20850a9e5c1e9d7e9c1562dabc593cbc9b5ac57e99f1549748ff2421b3f6830f34bff7c69d8",// Private key after encryption (unavailable if the account is encrypted)
+ "extend" : null,
+ "createTime" : "2018-07-13 11:39:14",//Creation time
+ "encrypted" : true//Encrypted or not (set password or not)
+}, {
+ "address" : "NsdwsD8n3GrW9Sx43eLZ3xv8C858ovE2",
+ "alias" : null,
+ "pubKey" : "035f063012385032d19082a302ba774af4e02abe32e43120d3bfe82ec72dcdeafa",
+ "priKey" : "3ba27d6a53fb52f52443d8d895155ca113c632fd8a1bd6e7846933d1fb378ecb",
+ "encryptedPriKey" : "",
+ "extend" : null,
+ "createTime" : "2018-07-13 11:02:23",
+ "encrypted" : false
+} ]
+Example: to get list of accounts, showing page 1, 2 items per page
nuls>>> getaccounts 1 2
+[ {
+ "address" : "NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy",
+ "alias" : null,
+ "pubKey" : "03f364bae9bb632a9b957522f150cb501dbc950e3700cff7a3679ed8820c486875",
+ "priKey" : "",
+ "encryptedPriKey" : "712149fad00350cdfee4d20850a9e5c1e9d7e9c1562dabc593cbc9b5ac57e99f1549748ff2421b3f6830f34bff7c69d8",
+ "extend" : null,
+ "createTime" : "2018-07-13 11:39:14",
+ "encrypted" : true
+}, {
+ "address" : "NsdwsD8n3GrW9Sx43eLZ3xv8C858ovE2",
+ "alias" : null,
+ "pubKey" : "035f063012385032d19082a302ba774af4e02abe32e43120d3bfe82ec72dcdeafa",
+ "priKey" : "3ba27d6a53fb52f52443d8d895155ca113c632fd8a1bd6e7846933d1fb378ecb",
+ "encryptedPriKey" : "",
+ "extend" : null,
+ "createTime" : "2018-07-13 11:02:23",
+ "encrypted" : false
+} ]
+Inquire account’s private key based on account address; if the account is encrypted, insert password.
| Parameter | Description |
|---|---|
| <address> | Account address, required |
Return message, imported account address
"00a166d10c2cc4cd8f76449ff699ab3eee44fe4f82b4bb866f7bba02751a6fd655"
+Example
nuls>>> getprikey NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy
+Please enter the password.
+Enter your password:**********
+"00a166d10c2cc4cd8f76449ff699ab3eee44fe4f82b4bb866f7bba02751a6fd655"
+Inquire account balance based on account address
| Parameter | Description |
|---|---|
| <address> | Account address, required |
Return message, imported account address
{
+ "balance" : "9999998.99",//Balance
+ "locked" : "0",//Locked balance
+ "usable" : "9999998.99"//Available balance
+}
+Example
nuls>>> getbalance Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT
+{
+ "balance" : "9999998.99",
+ "locked" : "0",
+ "usable" : "9999998.99"
+}
+Transfer NULS into another account address based on account address. If such account has password, insert password; if it has no password, transfer out directly.
| Parameter | Description |
|---|---|
| <address> | transferring address, required |
| <toAddress> | receiving address, required |
| <amount> | transferred amount, round to 8 decimals in total (in NULS), required |
| [remark] | Remarks, required |
Return message, transfer transaction hash
"00200bef73ad728c48146c8a5eb0d76fe7325b85803c61d8357c16dba09ea33b3596"
+Example
nuls>>> transfer Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT NsdtmV5XkgSdpBXi65ueTsrv2W5beV2T 100 Transfer
+Please enter the password.
+Enter your password:**********
+"00200bef73ad728c48146c8a5eb0d76fe7325b85803c61d8357c16dba09ea33b3596"
+Inquire transaction details as per transaction hash
| Parameter | Description |
|---|---|
| <hash> | Transaction hash, required |
Return message, transaction details
{
+ "hash" : "00200bef73ad728c48146c8a5eb0d76fe7325b85803c61d8357c16dba09ea33b3596",//Transaction hash
+ "type" : "transfer",//Transaction type (transfer transaction as an example)
+ "time" : "2018-07-16 11:21:46",//Transaction time
+ "blockHeight" : 26269,//Block height of package transaction
+ "fee" : "0.001",//Transaction service charge
+ "value" : "100",//(Transfer) transaction amount
+ "remark" : "Transfer",//remarks
+ "scriptSig" : "2103f68aeb83f3a4fdf9b49259a6e8eae97cf73c7a0a1c52da8a1f9c09312a6d3c530046304402202932ea77976a603b832861c64f868a34e9ad59b728d3a8eeba27269f05b4267c0220217a6e1b97fb3f65e6711434e17e399f43e168f3699edb2aba8618bdd3f410e1",//Signature
+ "status" : "confirm",//Status of transaction confirmation (confirmed or unconfirmed)
+ "confirmCount" : 46,//Times of confirmation
+ "size" : 254,//Size of transaction
+ "inputs" : [ {//Input of transaction
+ "fromHash" : "002006a5b7eb1d32ed6d7d54e24e219b112d4fdb8530db5506ee953b6f65a0fdb55e",
+ "fromIndex" : 1,
+ "address" : "Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT",
+ "value" : "9979998.98",
+ "lockTime" : 0
+ } ],
+ "outputs" : [ {//Output of transaction
+ "txHash" : "00200bef73ad728c48146c8a5eb0d76fe7325b85803c61d8357c16dba09ea33b3596",
+ "index" : 0,
+ "address" : "NsdtmV5XkgSdpBXi65ueTsrv2W5beV2T"// Target address of transaction output (means to transfer 100 to the target address)
+ "value" : "100",
+ "lockTime" : 0,
+ "status" : "usable"
+ }, {
+ "txHash" : "00200bef73ad728c48146c8a5eb0d76fe7325b85803c61d8357c16dba09ea33b3596",//Transaction hash
+ "index" : 1,
+ "address" : "Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT",//Target address of transaction output (means to give users changes)
+ "value" : "9979898.979",
+ "lockTime" : 0,
+ "status" : "usable"
+ } ]
+}
+Example, to inquire transfer transaction
nuls>>> gettx 00200bef73ad728c48146c8a5eb0d76fe7325b85803c61d8357c16dba09ea33b3596
+{
+ "hash" : "00200bef73ad728c48146c8a5eb0d76fe7325b85803c61d8357c16dba09ea33b3596",
+ "type" : "transfer",
+ "time" : "2018-07-16 11:21:46",
+ "blockHeight" : 26269,
+ "fee" : "0.001",
+ "value" : "100",
+ "remark" : "Transfer",
+ "scriptSig" : "2103f68aeb83f3a4fdf9b49259a6e8eae97cf73c7a0a1c52da8a1f9c09312a6d3c530046304402202932ea77976a603b832861c64f868a34e9ad59b728d3a8eeba27269f05b4267c0220217a6e1b97fb3f65e6711434e17e399f43e168f3699edb2aba8618bdd3f410e1",
+ "status" : "confirm",
+ "confirmCount" : 46,
+ "size" : 254,
+ "inputs" : [ {
+ "fromHash" : "002006a5b7eb1d32ed6d7d54e24e219b112d4fdb8530db5506ee953b6f65a0fdb55e",
+ "fromIndex" : 1,
+ "address" : "Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT",
+ "value" : "9979998.98",
+ "lockTime" : 0
+ } ],
+ "outputs" : [ {
+ "txHash" : "00200bef73ad728c48146c8a5eb0d76fe7325b85803c61d8357c16dba09ea33b3596",
+ "index" : 0,
+ "address" : "NsdtmV5XkgSdpBXi65ueTsrv2W5beV2T",
+ "value" : "100",
+ "lockTime" : 0,
+ "status" : "usable"
+ }, {
+ "txHash" : "00200bef73ad728c48146c8a5eb0d76fe7325b85803c61d8357c16dba09ea33b3596",
+ "index" : 1,
+ "address" : "Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT",
+ "value" : "9979898.979",
+ "lockTime" : 0,
+ "status" : "usable"
+ } ]
+}
+Inquire list of transactions in this account based on account address
| Parameter | Description |
|---|---|
| <address> | Account address, required |
| <pageNumber> | Page, to get the data on which page, required |
| <pageSize> | Number of data displayed on each page, required |
Return message, transaction details
[ {
+ "txHash" : "0020153f76bec3433676a96ef343d7e432b7de16b3175a9c5f4579338f604989996e",//Transaction hash
+ "blockHeight" : 26473,//Block height of transaction
+ "time" : "2018-07-16 11:55:43",//Transaction time
+ "txType" : "transfer",//Transaction type
+ "status" : 1,//Status of confirmation
+ "info" : "+100"//Message
+},{
+ "txHash" : "00200bef73ad728c48146c8a5eb0d76fe7325b85803c61d8357c16dba09ea33b3596",
+ "blockHeight" : 26269,
+ "time" : "2018-07-16 11:21:46",
+ "txType" : "transfer",
+ "status" : 1,
+ "info" : "+100"
+} ]
+Example
nuls>>> gettxlist NsdtmV5XkgSdpBXi65ueTsrv2W5beV2T 1 10
+[ {
+ "txHash" : "0020153f76bec3433676a96ef343d7e432b7de16b3175a9c5f4579338f604989996e",
+ "blockHeight" : 26473,
+ "time" : "2018-07-16 11:55:43",
+ "txType" : "transfer",
+ "status" : 1,
+ "info" : "+100"
+}, {
+ "txHash" : "00200bef73ad728c48146c8a5eb0d76fe7325b85803c61d8357c16dba09ea33b3596",
+ "blockHeight" : 26269,
+ "time" : "2018-07-16 11:21:46",
+ "txType" : "transfer",
+ "status" : 1,
+ "info" : "+100"
+} ]
+Create node based on account address. Need an account package address when creating node (package address shall have no password), and deposit of 2 at least.
| Parameter | Description |
|---|---|
| <agentAddress> | Account address of nodes created, required |
| <packingAddress> | Node account package address, required (note: the account shall have no password, otherwise the node cannot package) |
| <commissionRate> | Agent commission proportion, with a range of 10~100, required |
| <deposit> | Node creating deposit of 2 at least, required |
Return message, agent hash of return node
"002006a5b7eb1d32ed6d7d54e24e219b112d4fdb8530db5506ee953b6f65a0fdb55e"
+Example: to create a node, commission proportion of 10%, and deposit of 20000 NULS
nuls>>> createagent Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT NsdvAnqc8oEiNiGgcp6pEusfiRFZi4vt 10 20000
+Please enter the password.
+Enter your password:**********
+"002006a5b7eb1d32ed6d7d54e24e219b112d4fdb8530db5506ee953b6f65a0fdb55e"
+Include consensus of 2000NULS at least based on account address and node agent hash
| Parameter | Description |
|---|---|
| <address> | Account address, required |
| <agentHash> | Node agent hash, required |
| <deposit> | Include consensus deposit, not less than 2000NULS, required |
Return message, transaction hash for including consensus; to exit the consensus, require such hash.
"0020d349b7ad322ff958e3abfa799d9ac76341afa6e1fb4d3857353a5adc74ba3fd0"
+Example
nuls>>> deposit NsdtmV5XkgSdpBXi65ueTsrv2W5beV2T 002006a5b7eb1d32ed6d7d54e24e219b112d4fdb8530db5506ee953b6f65a0fdb55e 5000
+"0020d349b7ad322ff958e3abfa799d9ac76341afa6e1fb4d3857353a5adc74ba3fd0"
+Exit the consensus (agency) based on account address and transaction hash for including consensus. When an account agents several nodes, each agent transaction is independent, so users shall exit the corresponding agent rather than all agents as per the transaction hash of an agent.
| Parameter | Description |
|---|---|
| <address> | Account address, required |
| <txHash> | Transaction hash upon agency, required |
Return message, transaction hash upon exiting the consensus
"00201d70ac37b53d41c0e813ad245fc42e1d3a5d174d9148fbbbaed3c18d4d67bdbf"
+Example
nuls>>> withdraw NsdtmV5XkgSdpBXi65ueTsrv2W5beV2T 0020d349b7ad322ff958e3abfa799d9ac76341afa6e1fb4d3857353a5adc74ba3fd0
+"00201d70ac37b53d41c0e813ad245fc42e1d3a5d174d9148fbbbaed3c18d4d67bdbf"
+Stop node, all NULS agented to node will be returned, and the deposit in account of node creator will be locked for 72 hours.
| Parameter | Description |
|---|---|
| <address> | Account address, required |
Return message, transaction hash of stop node
"0020f15eecd7c85be76521ed6af4d58a3810f7df58e536481cff4a96af6d4fddec5f"
+Example
nuls>>> stopagent Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT
+Please enter the password.
+Enter your password:**********
+"0020f15eecd7c85be76521ed6af4d58a3810f7df58e536481cff4a96af6d4fddec5f"
+Get node details as per agent hash of node
| Parameter | Description |
|---|---|
| <agentHash> | Node agent hash, required |
Return message
{
+ "agentHash" : "0020d349117a35c3b9c1e64f442d7750aae941162018f9d8d4c1db57565235024de6",
+ "agentAddress" : "Nsdy5AZmMkYQzQvfuEgVzwdmndnMYNmh",//Account address for creating node
+ "packingAddress" : "NsdwvEJuPC3hA5ws7VQGwXN77vqsM1PA",//Node package (block) address
+ "rewardAddress" : "Nsdy5AZmMkYQzQvfuEgVzwdmndnMYNmh",//Bonus address (default to be address for creating node)
+ "deposit" : "20000",//Deposit for creating node
+ "commissionRate" : 60.0,//Agent commission proportion
+ "agentName" : null,//Node name (source)
+ "agentId" : "35024DE6",//Node ID
+ "time" : "2018-07-16 16:33:38",//Time for creating node
+ "blockHeight" : 28141,// Block height of node creating transaction
+ "delHeight" : -1,
+ "status" : "consensus",// Status
+ "creditVal" : 0.05,//Credit value
+ "totalDeposit" : "208000",//Current total agency amount of node
+ "txHash" : "0020d349117a35c3b9c1e64f442d7750aae941162018f9d8d4c1db57565235024de6",
+ "memberCount" : 5//Quantity of participants
+}
+Example
nuls>>> getagent 0020d349117a35c3b9c1e64f442d7750aae941162018f9d8d4c1db57565235024de6
+{
+ "agentHash" : "0020d349117a35c3b9c1e64f442d7750aae941162018f9d8d4c1db57565235024de6",
+ "agentAddress" : "Nsdy5AZmMkYQzQvfuEgVzwdmndnMYNmh",
+ "packingAddress" : "NsdwvEJuPC3hA5ws7VQGwXN77vqsM1PA",
+ "rewardAddress" : "Nsdy5AZmMkYQzQvfuEgVzwdmndnMYNmh",
+ "deposit" : "20000",
+ "commissionRate" : 60.0,
+ "agentName" : null,
+ "agentId" : "35024DE6",
+ "time" : "2018-07-16 16:33:38",
+ "blockHeight" : 28141,
+ "delHeight" : -1,
+ "status" : "consensus",
+ "creditVal" : 0.05,
+ "totalDeposit" : "208000",
+ "txHash" : "0020d349117a35c3b9c1e64f442d7750aae941162018f9d8d4c1db57565235024de6",
+ "memberCount" : 5
+}
+As per list of consensus nodes
| Parameter | Description |
|---|---|
| <pageNumber> | Page, to get the data on which page, required |
| <pageSize> | Number of data displayed on each page, required |
Return message
[{
+ "agentHash" : "0020d349117a35c3b9c1e64f442d7750aae941162018f9d8d4c1db57565235024de6",
+ "agentAddress" : "Nsdy5AZmMkYQzQvfuEgVzwdmndnMYNmh",//Account address for creating node
+ "packingAddress" : "NsdwvEJuPC3hA5ws7VQGwXN77vqsM1PA",//Node package (block) address
+ "rewardAddress" : "Nsdy5AZmMkYQzQvfuEgVzwdmndnMYNmh",//Bonus address (default to be address for creating node)
+ "deposit" : "20000",//Deposit for creating node
+ "commissionRate" : 60.0,//Agent commission proportion
+ "agentName" : null,//Node name (source)
+ "agentId" : "35024DE6",//Node ID
+ "time" : "2018-07-16 16:33:38",//Time for creating node
+ "blockHeight" : 28141,//Block height of node creating transaction
+ "delHeight" : -1,
+ "status" : "consensus",//Status
+ "creditVal" : 0.05,//Credit value
+ "totalDeposit" : "208000",//Current total agent amount of node
+ "txHash" : "0020d349117a35c3b9c1e64f442d7750aae941162018f9d8d4c1db57565235024de6",
+ "memberCount" : 5//Quantity of participants
+}]
+Example
nuls>>> getagents 1 2
+[ {
+ "agentHash" : "0020d349117a35c3b9c1e64f442d7750aae941162018f9d8d4c1db57565235024de6",
+ "agentAddress" : "Nsdy5AZmMkYQzQvfuEgVzwdmndnMYNmh",
+ "packingAddress" : "NsdwvEJuPC3hA5ws7VQGwXN77vqsM1PA",
+ "rewardAddress" : "Nsdy5AZmMkYQzQvfuEgVzwdmndnMYNmh",
+ "deposit" : "20000",
+ "commissionRate" : 60.0,
+ "agentName" : null,
+ "agentId" : "35024DE6",
+ "time" : "2018-07-16 16:33:38",
+ "blockHeight" : 28141,
+ "delHeight" : -1,
+ "status" : "consensus",
+ "creditVal" : 0.18,
+ "totalDeposit" : "208000",
+ "txHash" : "0020d349117a35c3b9c1e64f442d7750aae941162018f9d8d4c1db57565235024de6",
+ "memberCount" : 5
+}, {
+ "agentHash" : "00202ef1977c1eea6fde8d1bf8d75b6f5650d62933e5fccc2d8d08023dea5ce291d8",
+ "agentAddress" : "NsdtEdrY4QWGa8VUGW83hXbZsbKhbrTN",
+ "packingAddress" : "NsdwhLzjCLJp9V7zULU9KBerqkW971K7",
+ "rewardAddress" : "NsdtEdrY4QWGa8VUGW83hXbZsbKhbrTN",
+ "deposit" : "20000",
+ "commissionRate" : 10.0,
+ "agentName" : null,
+ "agentId" : "5CE291D8",
+ "time" : "2018-07-16 16:31:12",
+ "blockHeight" : 28126,
+ "delHeight" : -1,
+ "status" : "consensus",
+ "creditVal" : -0.16,
+ "totalDeposit" : "208000",
+ "txHash" : "00202ef1977c1eea6fde8d1bf8d75b6f5650d62933e5fccc2d8d08023dea5ce291d8",
+ "memberCount" : 5
+} ]
+Inquire total information of network consensuses
Return message
{
+ "agentCount" : 6,//Quantity of nodes
+ "totalDeposit" : "1758000",//Total quantity of agents
+ "rewardOfDay" : "0",//Bonus
+ "consensusAccountNumber" : 6,//Quantity of consensus accounts
+ "packingAgentCount" : 6//Quantity of package addresses
+}
+Example
nuls>>> getconsensus
+{
+ "agentCount" : 6,
+ "totalDeposit" : "1758000",
+ "rewardOfDay" : "0",
+ "consensusAccountNumber" : 6,
+ "packingAgentCount" : 6
+}
+Get the general of all agents (consensuses) information of the account based on account address
| Parameter | Description |
|---|---|
| <address> | Account address, required |
Return message
{
+ "agentCount" : 1,//Quantity of nodes created
+ "totalDeposit" : "1600000",// Quantity of total agents
+ "joinAgentCount" : 6,//Quantity of nodes in agency
+ "usableBalance" : "8048998.869",//Available balance
+ "reward" : "219.65910271",//Total bonuses gained
+ "rewardOfDay" : "219.65910271",//Bonuses gained a day
+ "agentHash" : "00202794351e662e53f16fe04dd9217731463c3b24a6ee6cf80c9ba2d3e5e09eb7fd"//Node hash
+}
+Example
nuls>>> getdepositedinfo Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT
+{
+ "agentCount" : 1,
+ "totalDeposit" : "1600000",
+ "joinAgentCount" : 6,
+ "usableBalance" : "8048998.869",
+ "reward" : "219.65910271",
+ "rewardOfDay" : "219.65910271",
+ "agentHash" : "00202794351e662e53f16fe04dd9217731463c3b24a6ee6cf80c9ba2d3e5e09eb7fd"
+}
+Get list of agent information of the account as per address (return consensus information list), and review the list of agency information of the account under a node when following the agent hash.
| Parameter | Description |
|---|---|
| <address> | Account address, required |
| <pageNumber> | Page, to get the data on which page, required |
| <pageSize> | Number of data displayed on each page, required |
| [agentHash] | Node hash, optional |
Return message
[{
+ "deposit" : "2000",//Agency amount
+ "agentHash" : "0020d349117a35c3b9c1e64f442d7750aae941162018f9d8d4c1db57565235024de6",
+ "address" : "Nse6UxwHXNEDsySTnZr4hNfGwFZwkDto",//Address of agent
+ "time" : "2018-07-16 16:38:25",//Time
+ "txHash" : "0020c93d039b57361a141470b3630c3cf6fa304b1acaeabb7a26a772f434d24de221",//Agency transaction hash
+ "blockHeight" : 28148,//Block height of transaction
+ "delHeight" : -1,
+ "status" : "consensus",//Node status
+ "agentName" : "35024DE6",//Node name
+ "agentAddress" : "Nsdy5AZmMkYQzQvfuEgVzwdmndnMYNmh"//Node address
+}]
+Example
nuls>>> getdepositeds Nse6UxwHXNEDsySTnZr4hNfGwFZwkDto 1 2
+[ {
+ "deposit" : "2000",
+ "agentHash" : "0020d349117a35c3b9c1e64f442d7750aae941162018f9d8d4c1db57565235024de6",
+ "address" : "Nse6UxwHXNEDsySTnZr4hNfGwFZwkDto",
+ "time" : "2018-07-16 16:38:25",
+ "txHash" : "0020c93d039b57361a141470b3630c3cf6fa304b1acaeabb7a26a772f434d24de221",
+ "blockHeight" : 28148,
+ "delHeight" : -1,
+ "status" : "consensus",
+ "agentName" : "35024DE6",
+ "agentAddress" : "Nsdy5AZmMkYQzQvfuEgVzwdmndnMYNmh"
+}, {
+ "deposit" : "2000",
+ "agentHash" : "00202794351e662e53f16fe04dd9217731463c3b24a6ee6cf80c9ba2d3e5e09eb7fd",
+ "address" : "Nse6UxwHXNEDsySTnZr4hNfGwFZwkDto",
+ "time" : "2018-07-16 16:38:43",
+ "txHash" : "00205278ce2eeaf9da7acc13ce81293a01a3f44a1de09e4e0b3ec078884a65700234",
+ "blockHeight" : 28149,
+ "delHeight" : -1,
+ "status" : "consensus",
+ "agentName" : "E09EB7FD",
+ "agentAddress" : "Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT"
+} ]
+Inquire list of agency nodes asper address (return list of node information)
| Parameter | Description |
|---|---|
| <address> | Account address, required |
| <pageNumber> | Page, to get the data on which page, required |
| <pageSize> | Number of data displayed on each page, required |
Return message
[ {
+ "agentHash" : "0020617f9be18306fcdf95917fad80f4d15c51426667825ad5a6968ec0ee0198acaf",//Node hash
+ "agentAddress" : "Nse6UxwHXNEDsySTnZr4hNfGwFZwkDto",//Account address for creating node
+ "packingAddress" : "Nse77VDHtiQ6WnkEhgCA7TbfNkoH9iyr",//Node package (block) address
+ "rewardAddress" : "Nse6UxwHXNEDsySTnZr4hNfGwFZwkDto",//Bonus address (default to be address for creating node)
+ "deposit" : "20000",//Deposit for creating node
+ "commissionRate" : 40.0,//Agent commission proportion
+ "agentName" : null,//Node name (source)
+ "agentId" : "0198ACAF",// Node ID
+ "time" : "2018-07-16 16:32:52",//Time for creating node
+ "blockHeight" : 28136,//Block height of node creating transaction
+ "delHeight" : -1,
+ "status" : "consensus",//Status
+ "creditVal" : -0.91,//Credit value
+ "totalDeposit" : "204000",//Current total agent amount of node
+ "txHash" : "0020617f9be18306fcdf95917fad80f4d15c51426667825ad5a6968ec0ee0198acaf",
+ "memberCount" : 3// Quantity of participants
+}]
+Example, to get page 1, display 2 items per page
nuls>>> getdepositedagents Nse6UxwHXNEDsySTnZr4hNfGwFZwkDto 1 2
+[ {
+ "agentHash" : "0020617f9be18306fcdf95917fad80f4d15c51426667825ad5a6968ec0ee0198acaf",
+ "agentAddress" : "Nse6UxwHXNEDsySTnZr4hNfGwFZwkDto",
+ "packingAddress" : "Nse77VDHtiQ6WnkEhgCA7TbfNkoH9iyr",
+ "rewardAddress" : "Nse6UxwHXNEDsySTnZr4hNfGwFZwkDto",
+ "deposit" : "20000",
+ "commissionRate" : 40.0,
+ "agentName" : null,
+ "agentId" : "0198ACAF",
+ "time" : "2018-07-16 16:32:52",
+ "blockHeight" : 28136,
+ "delHeight" : -1,
+ "status" : "consensus",
+ "creditVal" : -0.91,
+ "totalDeposit" : "204000",
+ "txHash" : "0020617f9be18306fcdf95917fad80f4d15c51426667825ad5a6968ec0ee0198acaf",
+ "memberCount" : 3
+}, {
+ "agentHash" : "0020d349117a35c3b9c1e64f442d7750aae941162018f9d8d4c1db57565235024de6",
+ "agentAddress" : "Nsdy5AZmMkYQzQvfuEgVzwdmndnMYNmh",
+ "packingAddress" : "NsdwvEJuPC3hA5ws7VQGwXN77vqsM1PA",
+ "rewardAddress" : "Nsdy5AZmMkYQzQvfuEgVzwdmndnMYNmh",
+ "deposit" : "20000",
+ "commissionRate" : 60.0,
+ "agentName" : null,
+ "agentId" : "35024DE6",
+ "time" : "2018-07-16 16:33:38",
+ "blockHeight" : 28141,
+ "delHeight" : -1,
+ "status" : "consensus",
+ "creditVal" : 0.91,
+ "totalDeposit" : "208000",
+ "txHash" : "0020d349117a35c3b9c1e64f442d7750aae941162018f9d8d4c1db57565235024de6",
+ "memberCount" : 5
+} ]
+Get the latest block head information
Return message
{
+ "hash" : "00206c4ae1d90fdfd875ee3bf84e72615db8bc628f015db089f8a6304ed46a47db5e",//Block hash
+ "preHash" : "00207ec8c85a6844899806f55cd9223efa091b548e5cc093ee7833f1c0208254957d",//Former block hash
+ "merkleHash" : "002019aff9431c5b409df7af48a64a50e4e9a0af24cc309d6eefa84deada2a438877",//Merkle hash
+ "time" : "2018-07-17 10:25:40",//Block generation time
+ "height" : 33950,//Block height
+ "txCount" : 1,//Quantity of block package transactions
+ "packingAddress" : "NsdyF8gBxAfxCyiNbLzsENUvbJZ27mWw",//Package address
+ "roundIndex" : 668413,//Rounds of consensuses
+ "consensusMemberCount" : 1,//Quantity of participants in consensus
+ "roundStartTime" : "2018-07-17 10:25:30",//Start time of current round
+ "packingIndexOfRound" : 1,//Rank of package and block in current round
+ "reward" : "0",//Consensus bonus
+ "fee" : "0",//Package service charge of block
+ "confirmCount" : 0,//Times of confirmation
+ "size" : 204,//Size of block
+ "scriptSig" : "210381e44e0c2fffadc94603a41514f3e5b1c5fd53166be73eb8f49ce8c297059e5600473045022100ece231eec6765c3d3cd7a4b74ef227eea05c3511e04ea46bc1b518a51a624e48022022208161b3064f261233bfa0c00308bf5b56421401ba7dd02232bac5077935b9"// Signature
+}
+Example
nuls>>> getbestblockheader
+{
+ "hash" : "00206c4ae1d90fdfd875ee3bf84e72615db8bc628f015db089f8a6304ed46a47db5e",
+ "preHash" : "00207ec8c85a6844899806f55cd9223efa091b548e5cc093ee7833f1c0208254957d",
+ "merkleHash" : "002019aff9431c5b409df7af48a64a50e4e9a0af24cc309d6eefa84deada2a438877",
+ "time" : "2018-07-17 10:25:40",
+ "height" : 33950,
+ "txCount" : 1,
+ "packingAddress" : "NsdyF8gBxAfxCyiNbLzsENUvbJZ27mWw",
+ "roundIndex" : 668413,
+ "consensusMemberCount" : 1,
+ "roundStartTime" : "2018-07-17 10:25:30",
+ "packingIndexOfRound" : 1,
+ "reward" : "0",
+ "fee" : "0",
+ "confirmCount" : 0,
+ "size" : 204,
+ "scriptSig" : "210381e44e0c2fffadc94603a41514f3e5b1c5fd53166be73eb8f49ce8c297059e5600473045022100ece231eec6765c3d3cd7a4b74ef227eea05c3511e04ea46bc1b518a51a624e48022022208161b3064f261233bfa0c00308bf5b56421401ba7dd02232bac5077935b9"
+}
+Inquire block head information as per block height or block hash. Do and only choose one parameter as inquiry condition.
| Parameter | Description |
|---|---|
| <hash> | Block hash |
| <height> | Height of block |
Return message
{
+ "hash" : "0020c40f471756c88e7487fcc0d428545232120071b58f35e450891237d7b41eb817",//Block hash
+ "preHash" : "0020fb1fd03cda7e2b6585256f4da85bdac7d8fc8bafa0740b8eb0ed577f3020b954",//Former block hash
+ "merkleHash" : "0020474c5a353f235e8e8514328e1e98d6b653d4a5445473d160691e39121cd8b158",//Merkle hash
+ "time" : "2018-07-16 16:29:30",//Block generation time
+ "height" : 28115,//Block height
+ "txCount" : 2,//Quantity of block package transactions
+ "packingAddress" : "NsdyF8gBxAfxCyiNbLzsENUvbJZ27mWw",//Package address
+ "roundIndex" : 662578,//Rounds of consensuses
+ "consensusMemberCount" : 1,//Quantity of participants in consensus
+ "roundStartTime" : "2018-07-16 16:29:20",//Start time of current round
+ "packingIndexOfRound" : 1,//Rank of package and block in current round
+ "reward" : "0.001",//Consensus bonus
+ "fee" : "0.001",//Package service charge of block
+ "confirmCount" : 6174,//Times of confirmation
+ "size" : 507,//Size of block
+ "txList" : [ {//Transaction collection
+ "hash" : "0020648f1d25237ba3614237a52c2121e51608f3822ac57a0e67d6a53e84c867e841",//Transaction hash
+ "type" : "coinbase",//Transaction type
+ "time" : "2018-07-16 16:29:30",//Transaction time
+ "blockHeight" : 28115,//Block height of transaction
+ "fee" : "0",//Transaction service charge
+ "value" : null,
+ "remark" : null,
+ "scriptSig" : null,
+ "status" : "confirm",
+ "confirmCount" : 6174,
+ "size" : 54,
+ "inputs" : [ ],//Transaction input
+ "outputs" : [ //Transaction output
+ {
+ "address" : "NsdyF8gBxAfxCyiNbLzsENUvbJZ27mWw",
+ "value" : 100000,
+ "lockTime" : 29115
+ }
+ ]
+ }],
+ "scriptSig" : "210381e44e0c2fffadc94603a41514f3e5b1c5fd53166be73eb8f49ce8c297059e5600473045022100d25b815fa30376247692fad856d3984acf45c9b49edd3d222e3afdab3169520c02200565a486e33358301848bf3d704c187ff8b2d1e859c93b704f713abb984584bf"//Signature
+}
+Example: to get block as per height
nuls>>> getblock 28115
+{
+ "hash" : "0020c40f471756c88e7487fcc0d428545232120071b58f35e450891237d7b41eb817",
+ "preHash" : "0020fb1fd03cda7e2b6585256f4da85bdac7d8fc8bafa0740b8eb0ed577f3020b954",
+ "merkleHash" : "0020474c5a353f235e8e8514328e1e98d6b653d4a5445473d160691e39121cd8b158",
+ "time" : "2018-07-16 16:29:30",
+ "height" : 28115,
+ "txCount" : 2,
+ "packingAddress" : "NsdyF8gBxAfxCyiNbLzsENUvbJZ27mWw",
+ "roundIndex" : 662578,
+ "consensusMemberCount" : 1,
+ "roundStartTime" : "2018-07-16 16:29:20",
+ "packingIndexOfRound" : 1,
+ "reward" : "0.001",
+ "fee" : "0.001",
+ "confirmCount" : 6174,
+ "size" : 507,
+ "txList" : [ {
+ "hash" : "0020648f1d25237ba3614237a52c2121e51608f3822ac57a0e67d6a53e84c867e841",
+ "type" : "coinbase",
+ "time" : "2018-07-16 16:29:30",
+ "blockHeight" : 28115,
+ "fee" : "0",
+ "value" : null,
+ "remark" : null,
+ "scriptSig" : null,
+ "status" : "confirm",
+ "confirmCount" : 6174,
+ "size" : 54,
+ "inputs" : [ ],
+ "outputs" : [ {
+ "address" : "NsdyF8gBxAfxCyiNbLzsENUvbJZ27mWw",
+ "value" : 100000,
+ "lockTime" : 29115
+ } ]
+ }, {
+ "hash" : "0020217945b6804801e0860913d24bf1ca500f9b77518a2be190c1afe63334b3ee2b",
+ "type" : "transfer",
+ "time" : "2018-07-16 16:29:27",
+ "blockHeight" : 28115,
+ "fee" : "0.001",
+ "value" : null,
+ "remark" : null,
+ "scriptSig" : "2103f68aeb83f3a4fdf9b49259a6e8eae97cf73c7a0a1c52da8a1f9c09312a6d3c53004730450221008a78bd954ea2f0f5be72217f0858faaf408b2e70f8d4d5aebc9ead9eb6e3aa22022015305c46eab978b08fbc23608c064306ea150be6552bb51cc83badef68217663",
+ "status" : "confirm",
+ "confirmCount" : 6174,
+ "size" : 249,
+ "inputs" : [ {
+ "fromHash" : "0020f98434eb71e62bfda9a2708689c2f44b58f5b22299490f5956c35d54f2d48459",
+ "fromIndex" : 1,
+ "address" : "Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT",
+ "value" : 972899896100000
+ } ],
+ "outputs" : [ {
+ "address" : "NsdxeBuwQBStXHQ6mcaHyDpnTKijD5ne",
+ "value" : 3000000000000,
+ "lockTime" : 0
+ }, {
+ "address" : "Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT",
+ "value" : 969899896000000,
+ "lockTime" : 0
+ } ]
+ } ],
+ "scriptSig" : "210381e44e0c2fffadc94603a41514f3e5b1c5fd53166be73eb8f49ce8c297059e5600473045022100d25b815fa30376247692fad856d3984acf45c9b49edd3d222e3afdab3169520c02200565a486e33358301848bf3d704c187ff8b2d1e859c93b704f713abb984584bf"
+}
+Inquire block head information as per block height or block hash. Do and only choose one parameter as inquiry condition.
| Parameter | Description |
|---|---|
| <hash> | Block hash |
| <height> | Block height |
Return message
{
+ "hash" : "0020c40f471756c88e7487fcc0d428545232120071b58f35e450891237d7b41eb817",//Block hash
+ "preHash" : "0020fb1fd03cda7e2b6585256f4da85bdac7d8fc8bafa0740b8eb0ed577f3020b954",//Former block hash
+ "merkleHash" : "0020474c5a353f235e8e8514328e1e98d6b653d4a5445473d160691e39121cd8b158",//Merkle hash
+ "time" : "2018-07-16 16:29:30",//Block generation time
+ "height" : 28115,//Block height
+ "txCount" : 2,//Quantity of block package transactions
+ "packingAddress" : "NsdyF8gBxAfxCyiNbLzsENUvbJZ27mWw",//Package address
+ "roundIndex" : 662578,//Rounds of consensuses
+ "consensusMemberCount" : 1,//Quantity of participants in consensus
+ "roundStartTime" : "2018-07-16 16:29:20",//Start time of current round
+ "packingIndexOfRound" : 1,//Rank of package and block in current round
+ "reward" : "0.001",//Consensus bonus
+ "fee" : "0.001",//Package service charge of block
+ "confirmCount" : 6174,//Times of confirmation
+ "size" : 507,//Size of block
+ "scriptSig" : "210381e44e0c2fffadc94603a41514f3e5b1c5fd53166be73eb8f49ce8c297059e5600473045022100d25b815fa30376247692fad856d3984acf45c9b49edd3d222e3afdab3169520c02200565a486e33358301848bf3d704c187ff8b2d1e859c93b704f713abb984584bf"//Signature
+}
+Example: to get block as per height
nuls>>> getblockheader 28115
+{
+ "hash" : "0020c40f471756c88e7487fcc0d428545232120071b58f35e450891237d7b41eb817",
+ "preHash" : "0020fb1fd03cda7e2b6585256f4da85bdac7d8fc8bafa0740b8eb0ed577f3020b954",
+ "merkleHash" : "0020474c5a353f235e8e8514328e1e98d6b653d4a5445473d160691e39121cd8b158",
+ "time" : "2018-07-16 16:29:30",
+ "height" : 28115,
+ "txCount" : 2,
+ "packingAddress" : "NsdyF8gBxAfxCyiNbLzsENUvbJZ27mWw",
+ "roundIndex" : 662578,
+ "consensusMemberCount" : 1,
+ "roundStartTime" : "2018-07-16 16:29:20",
+ "packingIndexOfRound" : 1,
+ "reward" : "0.001",
+ "fee" : "0.001",
+ "confirmCount" : 6280,
+ "size" : 204,
+ "scriptSig" : "210381e44e0c2fffadc94603a41514f3e5b1c5fd53166be73eb8f49ce8c297059e5600473045022100d25b815fa30376247692fad856d3984acf45c9b49edd3d222e3afdab3169520c02200565a486e33358301848bf3d704c187ff8b2d1e859c93b704f713abb984584bf"
+}
+Inquire network basic information
Return message
{
+ "localBestHeight" : 35317,//Height of local latest block
+ "netBestHeight" : 35317,//Height of latest block online
+ "timeOffset" : "0ms",//Offset of network time
+ "inCount" : 0,//Quantity of passive connecting nodes
+ "outCount" : 1//Quantity of active connecting nodes
+}
+Example
nuls>>> getnetinfo
+{
+ "localBestHeight" : 35317,
+ "netBestHeight" : 35317,
+ "timeOffset" : "0ms",
+ "inCount" : 0,
+ "outCount" : 1
+}
+Inquire network node IP
Return message
[ "192.168.1.223" ]
+Example: get block as per height
nuls>>> getnetnodes
+[ "192.168.1.223" ]
+Inquire current version number
Return message
[ "192.168.1.223" ]
+Example
nuls>>> version
+{
+ "myVersion" : "1.0.0",
+ "newestVersion" : "0.9.11",
+ "upgradable" : false,
+ "infromation" : " Address format modification, node finding logic optimizing, block downloading logic optimizing, property and stability optimizing"
+}
+Inquire current version number
Example
nuls>>> version 1.0.0
+Exiting from wallet command line program does not mean exiting from wallet node started.
Example
nuls>>> exit
++ ← + + SDK +
The NULS main-net wallet is available in Windows, Linux and Mac versions, and is constantly updated. You can download for your operating system of choice.
Option 1: downloading from the official website (https://nuls.io/newWallet)

Option 2: downloading from github (https://github.com/nuls-io/nuls/releases)

Note: The version marked [Main-net] is the main-net wallet.
After the wallet is downloaded, unzip it according to specific operating systems.
For Windows users, the wallet is unzipped as shown below: the data folder and the logs folder are generated after the first run of the wallet.

Double-click NULS-Wallet.exe to launch and run the wallet. The browser will automatically open the wallet interface by default, as shown below:

When the interface is opened for the first time, the page will prompt that currently the block is being synchronized, as shown below:

The appearance of block synchronization means the successful connection to the NULS main-net. Once the synchronization is completed, the wallet can be used normally. To save time, users who do not want to resynchronize data from the first block can also download the latest block data package corresponding to each version on github, as shown below:

For Linux users, the wallet is unzipped as shown below: the data folder and the logs folder are generated after the first run of the wallet.
Run the command sh bin/start.sh to launch the wallet. Then run the command sh bin/cmd.sh to enter the NULS wallet command line interface (CLI). Run the command getnetinfo on the CLI to check the current network status. When the localBestHeight increases, it indicates that the main-net has been successfully connected, as shown below:
Users can also track the nuls.log in the logs folder to check the latest status of the wallet.
For MAC users, steps are almost the same as the Windows users, so let’s skip it.
The NULS test-net wallet is available in Windows, Linux and Mac versions, and is constantly updated. You can download for your operating system of choice.
Download: downloading from github (https://github.com/nuls-io/nuls/releases)
!
Note: The version marked [Testnet] is the test-net wallet.
After the wallet is downloaded, unzip it according to specific operating systems.
For Windows users, the wallet is unzipped as shown below: the data folder and the logs folder are generated after the first run of the wallet.

Double-click NULS-Wallet.exe to launch and run the wallet. The browser will automatically open the wallet interface by default, as shown below:

When the interface is opened for the first time, the page will prompt that currently the block is being synchronized, as shown below:

The appearance of block synchronization means the successful connection to the NULS test-net. Once the synchronization is completed, the wallet can be used normally. To save time, users who do not want to resynchronize data from the first block can also download the latest block data package corresponding to each version on github, as shown below:

For Linux users, the wallet is unzipped as shown below: the data folder and the logs folder are generated after the first run of the wallet.
Run the command sh bin/start.sh to launch the wallet. Then run the command sh bin/cmd.sh to enter the NULS wallet command line interface (CLI). Run the command getnetinfo on the CLI to check the current network status. When the localBestHeight increases, it indicates that the test-net has been successfully connected, as shown below:
Users can also track the nuls.log in the logs folder to check the latest status of the wallet.
For MAC users, steps are almost the same as the Windows users, so let’s skip it.
+ ← + + Connect Main-net + + Build Chain + + → +
NULS smart contract is developed with Java, and it operates in NULS virtual machine. Not all Java features are applicable to contract development and the relevant restrictions are specified in section 3.
NULS smart contract adopts IntelliJ IDEA as development tool
NULS smart contract plug-ins provide the following main functions:
NULS smart contract syntax is a subset of Java syntax, with some restrictions
Main classes of contracts must implement contract interfaces. A smart contract can have a class implementing contract interface only; and other classes and interfaces provide functions for such contract.
Java key words are listed as follows and those not applicable for NULS smart contract will be marked
Access control
Key words and instantiated object of definition class, interface, abstract class, implementation interface and derivative class
Key words of package
Key words of data type
Conditional loops (process control)
Error processing
Modification method, class, property and variables
other
The following syntax is the same with Java and simply listed here under, with specific details referred to the relevant documents of Java
NULS smart contract can be developed with the following class
@View type, Make sure to optimize the contract code as much as possible.a simple contract
Main classes of contract must implement contract interface, and other classes and interfaces provide functions for this contract
+package contracts.examples;
+
+import io.nuls.contract.sdk.Contract;
+import io.nuls.contract.sdk.annotation.Payable;
+import io.nuls.contract.sdk.annotation.Required;
+import io.nuls.contract.sdk.annotation.View;
+
+public class SimpleStorage implements Contract {
+
+ private String storedData;
+
+ @View
+ public String getStoredData() {
+ return storedData;
+ }
+
+ @Payable
+ public void setStoredData(@Required String storedData) {
+ this.storedData = storedData;
+ }
+
+}
+In one contract project, it requires to introduce a jar package “contract-sdk.jar” which provides the class to get block and transaction details +The project has several classes and interfaces
When compiling, packaging and deploying the prepared contract onto the NULS chain, the virtual machine will implement the construction method of this contract to initialize it, and save the contract status onto the chain. The contract status is the member variables of contract class
After the contract is deployed, all public methods of contract class can be called so as to read or modify the contract status
Explanatory comments
@View labels the method of @View. After it is called, the contract status will remain and it can be researched by such means
@Payable labels the method of @Payable. Only when it is called, the amount can be transferred in
@Required labels the parameter of @Required. When it is called, there must be transfer-in value
Go to download NULS source code on github, and get some contract examples
Contract SDK provides several classes to be convenient for contract development:
public class Address {
+
+ private final String address;
+
+ public Address(String address) {
+ valid(address);
+ this.address = address;
+ }
+
+ /**
+ * Get the balance of the address (only the balance of contract address)
+ *
+ * @return
+ */
+ public native BigInteger balance();
+
+ /**
+ * Transfer amount to the address from contract
+ *
+ * @param value transfer amount (in Na)
+ */
+ public native void transfer(BigInteger value);
+
+ /**
+ * Contract method to call the address
+ *
+ * @param Method name
+ * @param Method signature
+ * @param Parameters
+ * @param value Incidental currency (in Na)
+ */
+ public native void call(String methodName, String methodDesc, String[][] args, BigInteger value);
+
+ /**
+ * Call the contract method of this address with a return value(String)
+ *
+ * @param Method name
+ * @param Method signature
+ * @param Parameters
+ * @param value Incidental currency (in Na)
+ * @return return value after calling the contract
+ */
+ public native String callWithReturnValue(String methodName, String methodDesc, String[][] args, BigInteger value);
+
+ /**
+ * Verify the address
+ *
+ * @param address
+ * @see io.nuls.kernel.utils.AddressTool#validAddress(String)
+ */
+ private native void valid(String address);
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Address address1 = (Address) o;
+ return address != null ? address.equals(address1.address) : address1.address == null;
+ }
+
+ @Override
+ public int hashCode() {
+ return address != null ? address.hashCode() : 0;
+ }
+
+ @Override
+ public String toString() {
+ return address;
+ }
+
+}
+public class Block {
+
+ /**
+ * Given block’s head
+ *
+ * @param blockNumber
+ * @return
+ */
+ public static native BlockHeader getBlockHeader(long blockNumber);
+
+ /**
+ * Current block’s head
+ *
+ * @return
+ */
+ public static native BlockHeader currentBlockHeader();
+
+ /**
+ * Newest block’s head
+ *
+ * @return
+ */
+ public static native BlockHeader newestBlockHeader();
+
+ /**
+ * Given block’s hash
+ *
+ * @param blockNumber
+ * @return
+ */
+ public static String blockhash(long blockNumber) {
+ return getBlockHeader(blockNumber).getHash();
+ }
+
+ /**
+ *
+ * CCurrent block’s miner address
+ *
+ * @return
+ */
+ public static Address coinbase() {
+ return currentBlockHeader().getPackingAddress();
+ }
+
+ /**
+ *
+ * Current block’s No.
+ *
+ * @return
+ */
+ public static long number() {
+ return currentBlockHeader().getHeight();
+ }
+
+ /**
+ *
+ * Current block’s time stamp
+ *
+ * @return
+ */
+ public static long timestamp() {
+ return currentBlockHeader().getTime();
+ }
+
+}
+public class BlockHeader {
+
+ private String hash;
+ private long time;
+ private long height;
+ private long txCount;
+ private Address packingAddress;
+ private String stateRoot;
+
+ public String getHash() {
+ return hash;
+ }
+
+ public long getTime() {
+ return time;
+ }
+
+ public long getHeight() {
+ return height;
+ }
+
+ public long getTxCount() {
+ return txCount;
+ }
+
+ public Address getPackingAddress() {
+ return packingAddress;
+ }
+
+ public String getStateRoot() {
+ return stateRoot;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ BlockHeader that = (BlockHeader) o;
+
+ if (time != that.time) return false;
+ if (height != that.height) return false;
+ if (txCount != that.txCount) return false;
+ if (hash != null ? !hash.equals(that.hash) : that.hash != null) return false;
+ if (packingAddress != null ? !packingAddress.equals(that.packingAddress) : that.packingAddress != null)
+ return false;
+ return stateRoot != null ? stateRoot.equals(that.stateRoot) : that.stateRoot == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = hash != null ? hash.hashCode() : 0;
+ result = 31 * result + (int) (time ^ (time >>> 32));
+ result = 31 * result + (int) (height ^ (height >>> 32));
+ result = 31 * result + (int) (txCount ^ (txCount >>> 32));
+ result = 31 * result + (packingAddress != null ? packingAddress.hashCode() : 0);
+ result = 31 * result + (stateRoot != null ? stateRoot.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "BlockHeader{" +
+ "hash='" + hash + '\'' +
+ ", time=" + time +
+ ", height=" + height +
+ ", txCount=" + txCount +
+ ", packingAddress=" + packingAddress +
+ ", stateRoot='" + stateRoot + '\'' +
+ '}';
+ }
+
+}
+/**
+ * Contract interface, implemented by contract class
+ */
+public interface Contract {
+
+ /**
+ * Directly transfer to the contract, this method will be called, no action is done by default. If the contract address is to accept direct transfer, you can override this method and mark the `@Payable` annotation.
+ */
+ default void _payable() {
+ }
+
+}
+/**
+* Event interface, implemented by event class
+*/
+public interface Event {
+}
+public class Msg {
+
+ /**
+ * Remaining gas
+ *
+ * @return
+ */
+ public static native long gasleft();
+
+ /**
+ * sender of the contract
+ *
+ * @return
+ */
+ public static native Address sender();
+
+ /**
+ * The number of Nuls transferred by the contract sender to the contract address, the unit is Na, 1Nuls = 1 billion Na
+ *
+ * @return
+ */
+ public static native BigInteger value();
+
+ /**
+ * Gas price
+ *
+ * @return
+ */
+ public static native long gasprice();
+
+ /**
+ * Contract address
+ *
+ * @return
+ */
+ public static native Address address();
+
+}
+public class Utils {
+
+ private Utils() {
+ }
+
+ /**
+ * Check conditions; if conditions are not met, it will roll back.
+ *
+ * @param expression
+ */
+ public static void require(boolean expression) {
+ if (!expression) {
+ revert();
+ }
+ }
+
+ /**
+ * Check conditions; if conditions are not met, it will roll back
+ *
+ * @param expression
+ * @param errorMessage
+ */
+ public static void require(boolean expression, String errorMessage) {
+ if (!expression) {
+ revert(errorMessage);
+ }
+ }
+
+ /**
+ * Terminate implementation and restore status
+ */
+ public static void revert() {
+ revert(null);
+ }
+
+ /**
+ * Terminate implementation and restore status
+ *
+ * @param errorMessage
+ */
+ public static native void revert(String errorMessage);
+
+ /**
+ * Send events
+ *
+ * @param event
+ */
+ public static native void emit(Event event);
+
+ /**
+ * @param seed a private seed
+ * @return pseudo random number (0 ~ 1)
+ */
+ public static float pseudoRandom(long seed) {
+ int hash1 = Block.currentBlockHeader().getPackingAddress().toString().substring(2).hashCode();
+ int hash2 = Msg.address().toString().substring(2).hashCode();
+ int hash3 = Msg.sender() != null ? Msg.sender().toString().substring(2).hashCode() : 0;
+ int hash4 = Long.valueOf(Block.timestamp()).toString().hashCode();
+
+ long hash = seed ^ hash1 ^ hash2 ^ hash3 ^ hash4;
+
+ seed = (hash * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
+ return ((int) (seed >>> 24) / (float) (1 << 24));
+ }
+
+ /**
+ * @return pseudo random number (0 ~ 1)
+ */
+ public static float pseudoRandom() {
+ return pseudoRandom(0x5DEECE66DL);
+ }
+
+ /**
+ *
+ * Please note that this is the SHA-3 FIPS 202 standard, not Keccak-256.
+ *
+ * @param src source string (hex encoding string)
+ * @return sha3-256 hash (hex encoding string)
+ */
+ public static native String sha3(String hexString);
+
+ /**
+ *
+ * Please note that this is the SHA-3 FIPS 202 standard, not Keccak-256.
+ *
+ * @param bytes source byte array
+ * @return sha3-256 hash (hex encoding string)
+ */
+ public static native String sha3(byte[] bytes);
+
+ /**
+ * [Testnet]verify signature data(ECDSA)
+ *
+ * @param data(hex encoding string)
+ * @param signature(hex encoding string)
+ * @param pubkey(hex encoding string)
+ * @return verify result
+ */
+ public static native boolean verifySignatureData(String data, String signature, String pubkey);
+
+ /**
+ * [Testnet]Generate a random seed with a specific algorithm based on the cutoff block height and the number of original seeds
+ *
+ * @param endHeight the cutoff block height
+ * @param seedCount the number of original seeds
+ * @param algorithm Hash algorithm identifier
+ * @return After the original seed byte array is merged, the hash algorithm is used to get a 32-bit hash byte array, which is then converted into BigInteger(new BigInteger(byte[] bytes)).
+ */
+ public static native BigInteger getRandomSeed(long endHeight, int seedCount, String algorithm);
+
+ /**
+ * [Testnet]Generate a random seed using the `SHA3-256`hash algorithm based on the cutoff block height and the number of original seeds.
+ *
+ * @param endHeight the cutoff block height
+ * @param seedCount the number of original seeds
+ * @return After the original seed byte array is merged, the `SHA3-256` hash algorithm is used to get the 32-bit hash byte array, which is then converted into BigInteger(new BigInteger(byte[] bytes)).
+ */
+ public static BigInteger getRandomSeed(long endHeight, int seedCount) {
+ return getRandomSeed(endHeight, seedCount, "SHA3");
+ }
+
+ /**
+ * [Testnet]Generate a random seed with a specific algorithm based on the block height range
+ *
+ * @param startHeight the starting block height
+ * @param endHeight the cutoff block height
+ * @param algorithm Hash algorithm identifier
+ * @return After the original seed byte array is merged, the hash algorithm is used to get a 32-bit hash byte array, which is then converted into BigInteger(new BigInteger(byte[] bytes)).
+ */
+ public static native BigInteger getRandomSeed(long startHeight, long endHeight, String algorithm);
+
+ /**
+ * [Testnet]Generate a random seed with the `SHA3-256` hash algorithm based on the block height range
+ *
+ * @param startHeight the starting block height
+ * @param endHeight the cutoff block height
+ * @return After the original seed byte array is merged, the `SHA3-256` hash algorithm is used to get the 32-bit hash byte array, which is then converted into BigInteger(new BigInteger(byte[] bytes)).
+ */
+ public static BigInteger getRandomSeed(long startHeight, long endHeight){
+ return getRandomSeed(startHeight, endHeight, "SHA3");
+ }
+
+ /**
+ * [Testnet]Get a collection of raw seeds based on the cutoff block height and the number of original seeds
+ *
+ * @param endHeight the cutoff block height
+ * @param seedCount the number of original seeds
+ * @return returns a collection of original seeds, the element is a BigInteger (new BigInteger(byte[] bytes)))
+ */
+ public static native List<BigInteger> getRandomSeedList(long endHeight, int seedCount);
+
+ /**
+ * [Testnet]Get a collection of raw seeds based on the block height range
+ *
+ * @param startHeight the starting block height
+ * @param endHeight the cutoff block height
+ * @return returns a collection of original seeds, the element is a BigInteger (new BigInteger(byte[] bytes)))
+ */
+ public static native List<BigInteger> getRandomSeedList(long startHeight, long endHeight);
+
+}
+@Payable labels the method of @Payable. Only when it is called, the amount can be transferred in
@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Payable {
+}
+@Required labels the parameter of @Required. When it is called, there must be transfer-in value.
@Target({ElementType.PARAMETER})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Required {
+}
+@Viewlabels the method of @View. After it is called, the contract status will remain and it can be researched by such means
@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface View {
+}
+See parameter structure and simple examples hereafter. See details of other interfaces at [Swagger UI] (http://127.0.0.1:8001/docs#/)
The default port of test network’s “Swagger UI” is 8001, and that of official network is 6001
/api/contract/create| Parameter | Type | Description |
|---|---|---|
| sender* | string | transaction creator |
| password* | string | password of transaction creator |
| gasLimit* | long | max. gas consumption |
| price* | long | unit price of implementation contract |
| contractCode* | string | smart contract code (byte code’s Hex coded string) |
| remark | string | remark |
| args | string[][] | Parameter list |
{
+ "sender": "Nsdz8mKKFMehRDVRZFyXNuuenugUYM7M",
+ "gasLimit": 4687,
+ "price": 20,
+ "password": "xxx",
+ "contractCode": "504b03041400080808003b5aed4c000000000000000000000000090004004d4554412d494e462ffeca00000300504b0708000000000200000000000000504b03041400080808003b5aed4c000000000000000000000000140000004d4554412d494e462f4d414e49464553542e4d46f34dcccb4c4b2d2ed10d4b2d2acecccfb35230d433e0e5722e4a4d2c494dd175aa040958e819c41b9a982868f8172526e7a42a38e71715e417259600d56bf272f1720100504b07089e7c76534400000045000000504b03040a00000800007559ed4c0000000000000000000000000d00000074657374636f6e74726163742f504b03041400080808008359ed4c0000000000000000000000001f00000074657374636f6e74726163742f54657374436f6e74726163742e636c6173737d535d53d350103d9796a684604b2cdf20c5cf365a421110f986225a2cf040c5d1b7b40d25d0264c9232e39bbfc2f147f8a03352189df107f8a31cf7b635744a310f7befeedd73f6dcdd9bdf7f7efc023083bd2e746052801ac4948824a6453cc58c8859cc75827f9f3f7de4de331e9f0fe2b9883e2c04b1c8714bdc2c0b581111c60237ab41acf1754ec0ba800d06bfa99575063973ac9d696a49338beabe6b1b66719121e07c28e7ac12434fca321d5733dd03ad54a1ec6041cf1b65ade430b0b48f44c80c425177776b5c9158bc1d9b3f6515e83494314c7db752cee97656cb956ab5adbc563ad06c83fb8da0df3d32887e24e3ea8e9bb74cd7d6f2ae9a2527d57088b28b6aee373476d37ed393e58bc5d3a429a791863c574c10d339d46dbad592611aee4a2de78041dcb72a765edf3278d5dee60293fc12120630c83074a30c868e6c56404ac2265e08d89210c34b01af24a4312e611baf25c491a1baeb6f93b3f36f2428784cd23947d63ad14d094318943082518681d6be6d548c5241b725ec609740d144b4cec210be4addcb1deb5cc89861a966a5e4a89e50a770a25e091d6c7bbee314a9535aa160eb0e752e4ad36b9bb75ecfa0b68ffeef9ccafc9b7f59738fd40da398365dbda8db848cb48bf3e958f5eb929033fec4f60ea9e5b1ed1b798662ed4ff84003dae9a96e161812b1ebcff0facb6c74781113f4aff481a11f3edad1d4f9bbe6b3a1d830ed3b282ef33179fe1802b4bf8371b2518aa8b4325a3b95ef605f6b29136403b5a082bb64a57a02eee13ead0c0f3c70a201f6c9be56e86413d4e7411fe2512b342c7f69814eb785c6bcaa330da878097f159d55045a8bcf3531881e43dc6358265e7e16228608844b745521cadd573422adc002512c3651853c2afa1d1a5456832aa95c4052e49e733045f69de3961296cf11fa89f0bb0bf42aefa9bb55c8f26d32554428eb9b576c9854032bf05367456a51989ad48f554c61ada978d22bfea4864cfc05504b070818c1191cd20200006f050000504b010214001400080808003b5aed4c0000000002000000000000000900040000000000000000000000000000004d4554412d494e462ffeca0000504b010214001400080808003b5aed4c9e7c7653440000004500000014000000000000000000000000003d0000004d4554412d494e462f4d414e49464553542e4d46504b01020a000a00000800007559ed4c0000000000000000000000000d00000000000000000000000000c300000074657374636f6e74726163742f504b010214001400080808008359ed4c18c1191cd20200006f0500001f00000000000000000000000000ee00000074657374636f6e74726163742f54657374436f6e74726163742e636c617373504b05060000000004000400050100000d0400000000",
+ "remark": "asd",
+ "args": []
+}
+/api/contract/imputedgas/create| Parameter | Type | Description |
|---|---|---|
| sender* | string | transaction creator |
| password* | string | password of transaction creator |
| price* | long | unit price of implementation contract |
| contractCode* | string | smart contract code (byte code’s Hex coded string) |
| args | string[][] | Parameter list |
{
+ "sender": "Nsdz8mKKFMehRDVRZFyXNuuenugUYM7M",
+ "price": 20,
+ "password": "xxx",
+ "contractCode": "504b03041400080808003b5aed4c000000000000000000000000090004004d4554412d494e462ffeca00000300504b0708000000000200000000000000504b03041400080808003b5aed4c000000000000000000000000140000004d4554412d494e462f4d414e49464553542e4d46f34dcccb4c4b2d2ed10d4b2d2acecccfb35230d433e0e5722e4a4d2c494dd175aa040958e819c41b9a982868f8172526e7a42a38e71715e417259600d56bf272f1720100504b07089e7c76534400000045000000504b03040a00000800007559ed4c0000000000000000000000000d00000074657374636f6e74726163742f504b03041400080808008359ed4c0000000000000000000000001f00000074657374636f6e74726163742f54657374436f6e74726163742e636c6173737d535d53d350103d9796a684604b2cdf20c5cf365a421110f986225a2cf040c5d1b7b40d25d0264c9232e39bbfc2f147f8a03352189df107f8a31cf7b635744a310f7befeedd73f6dcdd9bdf7f7efc023083bd2e746052801ac4948824a6453cc58c8859cc75827f9f3f7de4de331e9f0fe2b9883e2c04b1c8714bdc2c0b581111c60237ab41acf1754ec0ba800d06bfa99575063973ac9d696a49338beabe6b1b66719121e07c28e7ac12434fca321d5733dd03ad54a1ec6041cf1b65ade430b0b48f44c80c425177776b5c9158bc1d9b3f6515e83494314c7db752cee97656cb956ab5adbc563ad06c83fb8da0df3d32887e24e3ea8e9bb74cd7d6f2ae9a2527d57088b28b6aee373476d37ed393e58bc5d3a429a791863c574c10d339d46dbad592611aee4a2de78041dcb72a765edf3278d5dee60293fc12120630c83074a30c868e6c56404ac2265e08d89210c34b01af24a4312e611baf25c491a1baeb6f93b3f36f2428784cd23947d63ad14d094318943082518681d6be6d548c5241b725ec609740d144b4cec210be4addcb1deb5cc89861a966a5e4a89e50a770a25e091d6c7bbee314a9535aa160eb0e752e4ad36b9bb75ecfa0b68ffeef9ccafc9b7f59738fd40da398365dbda8db848cb48bf3e958f5eb929033fec4f60ea9e5b1ed1b798662ed4ff84003dae9a96e161812b1ebcff0facb6c74781113f4aff481a11f3edad1d4f9bbe6b3a1d830ed3b282ef33179fe1802b4bf8371b2518aa8b4325a3b95ef605f6b29136403b5a082bb64a57a02eee13ead0c0f3c70a201f6c9be56e86413d4e7411fe2512b342c7f69814eb785c6bcaa330da878097f159d55045a8bcf3531881e43dc6358265e7e16228608844b745521cadd573422adc002512c3651853c2afa1d1a5456832aa95c4052e49e733045f69de3961296cf11fa89f0bb0bf42aefa9bb55c8f26d32554428eb9b576c9854032bf05367456a51989ad48f554c61ada978d22bfea4864cfc05504b070818c1191cd20200006f050000504b010214001400080808003b5aed4c0000000002000000000000000900040000000000000000000000000000004d4554412d494e462ffeca0000504b010214001400080808003b5aed4c9e7c7653440000004500000014000000000000000000000000003d0000004d4554412d494e462f4d414e49464553542e4d46504b01020a000a00000800007559ed4c0000000000000000000000000d00000000000000000000000000c300000074657374636f6e74726163742f504b010214001400080808008359ed4c18c1191cd20200006f0500001f00000000000000000000000000ee00000074657374636f6e74726163742f54657374436f6e74726163742e636c617373504b05060000000004000400050100000d0400000000",
+ "args": []
+}
+/api/contract/call| Parameter | Type | Description |
|---|---|---|
| sender* | string | transaction creator |
| password* | string | password of transaction creator |
| contractAddress* | string | address of smart contract |
| gasLimit* | long | max. gas consumption |
| price* | long | unit price of implementation contract |
| value | long | amount transferred by transaction creator to contract address (Na - 100000000Na=1NULS) |
| methodName* | string | method name |
| methodDesc | string | method signature which may be not transferred if the method name is not repeated |
| remark | string | remark |
| args | string[][] | Parameter list |
{
+ "sender": "Nsdz8mKKFMehRDVRZFyXNuuenugUYM7M",
+ "password": "",
+ "contractAddress": "NseBvPEzerLi3p5Me8Rbm7SeHThVGv1U",
+ "gasLimit": 8000,
+ "price": 20,
+ "value": 0,
+ "methodName": "balance",
+ "methodDesc": "",
+ "remark": "qwe"
+ "args": []
+}
+Swagger UI)/api/contract/imputedgas/callSwagger UI)/api/contract/imputedpriceSwagger UI)/api/contract/deleteSwagger UI)/api/contract/viewSwagger UI)/api/contract/result/{hash}Swagger UI)/api/contract/info/{address}Swagger UI)/api/contract/{address}Swagger UI)/api/contract/balance/{address}Swagger UI)/api/contract/tx/{hash}Swagger UI)/api/contract/tx/list/{address}Swagger UI)/api/contract/limit/{address}/{limit}Swagger UI)/api/contract/amount/{address}/{amount}Swagger UI)/api/contract/transfersegments are as followsFull code:
https://github.com/nuls-io/nuls-vote
package io.nuls.vote.contract;
+
+import io.nuls.contract.sdk.Address;
+import io.nuls.contract.sdk.Contract;
+import io.nuls.contract.sdk.Utils;
+import io.nuls.contract.sdk.annotation.Payable;
+import io.nuls.contract.sdk.annotation.View;
+import io.nuls.vote.contract.func.BaseVote;
+import io.nuls.vote.contract.func.VoteInterface;
+import io.nuls.vote.contract.model.VoteConfig;
+import io.nuls.vote.contract.model.VoteEntity;
+
+import java.math.BigInteger;
+import java.util.List;
+import java.util.Map;
+
+public class VoteContract implements Contract {
+
+ private VoteInterface baseVote;
+
+ public VoteContract(long minRecognizance) {
+ baseVote = new BaseVote(BigInteger.valueOf(minRecognizance));
+ }
+
+ @Payable
+ public VoteEntity create(String title, String desc, String[] items, long startTime, long endTime, boolean isMultipleSelect, int maxSelectCount, boolean voteCanModify) {
+ VoteEntity voteEntity = baseVote.create(title, desc, items);
+
+ VoteConfig config = new VoteConfig(startTime, endTime, isMultipleSelect, maxSelectCount, voteCanModify);
+ boolean success = baseVote.init(voteEntity.getId(), config);
+
+ Utils.require(success);
+
+ return voteEntity;
+ }
+
+ public boolean vote(long voteId, long[] itemIds) {
+ return baseVote.vote(voteId, itemIds);
+ }
+
+ public boolean redemption(long voteId) {
+ return baseVote.redemption(voteId);
+ }
+
+ @View
+ public boolean canVote(long voteId) {
+ return baseVote.canVote(voteId);
+ }
+
+ @View
+ public VoteEntity queryVote(long voteId) {
+ return baseVote.queryVote(voteId);
+ }
+
+ @View
+ public Map<Address, List<Long>> queryVoteResult(long voteId) {
+ return baseVote.queryVoteResult(voteId);
+ }
+
+ @View
+ public boolean queryAddressHasVote(long voteId, Address address) {
+ return baseVote.queryAddressHasVote(voteId, address);
+ }
+}
+
+If the methods of smart contract include the parameter of array type, please use the following method to transfer parameters
Refer to the
createmethod in the aforesaid voting contract code
{
+ "sender": "NsdtydTVWskMc7GkZzbsq2FoChqKFwMf",
+ "password": "",
+ "contractAddress": "NseLt14NacjTDhXaTXUdrk6VF7aEwtW4",
+ "gasLimit": 200000,
+ "price": 1,
+ "value": 10000000000,
+ "methodName": "create",
+ "methodDesc": "",
+ "remark": "",
+ "args": [
+ "Test voting 1",
+ "Voting contract 1",
+ [
+ "Option 1",
+ "Option 2",
+ "Option 3"
+ ],
+ 1536044066056, 1536184066056, false, 300, false
+ ]
+}
+segmentsFull code:
https://github.com/nuls-io/nuls-nrc20
package io.nuls.contract.token;
+
+import io.nuls.contract.sdk.Address;
+import io.nuls.contract.sdk.Contract;
+import io.nuls.contract.sdk.Msg;
+import io.nuls.contract.sdk.annotation.Required;
+import io.nuls.contract.sdk.annotation.View;
+
+import java.math.BigInteger;
+import java.util.HashMap;
+import java.util.Map;
+
+import static io.nuls.contract.sdk.Utils.emit;
+import static io.nuls.contract.sdk.Utils.require;
+
+public class SimpleToken implements Contract, Token {
+
+ private final String name;
+ private final String symbol;
+ private final int decimals;
+ private BigInteger totalSupply = BigInteger.ZERO;
+
+ private Map<Address, BigInteger> balances = new HashMap<Address, BigInteger>();
+ private Map<Address, Map<Address, BigInteger>> allowed = new HashMap<Address, Map<Address, BigInteger>>();
+
+ @Override
+ @View
+ public String name() {
+ return name;
+ }
+
+ @Override
+ @View
+ public String symbol() {
+ return symbol;
+ }
+
+ @Override
+ @View
+ public int decimals() {
+ return decimals;
+ }
+
+ @Override
+ @View
+ public BigInteger totalSupply() {
+ return totalSupply;
+ }
+
+ public SimpleToken(@Required String name, @Required String symbol, @Required BigInteger initialAmount, @Required int decimals) {
+ this.name = name;
+ this.symbol = symbol;
+ this.decimals = decimals;
+ totalSupply = initialAmount.multiply(BigInteger.TEN.pow(decimals));;
+ balances.put(Msg.sender(), totalSupply);
+ emit(new TransferEvent(null, Msg.sender(), totalSupply));
+ }
+
+ @Override
+ @View
+ public BigInteger allowance(@Required Address owner, @Required Address spender) {
+ Map<Address, BigInteger> ownerAllowed = allowed.get(owner);
+ if (ownerAllowed == null) {
+ return BigInteger.ZERO;
+ }
+ BigInteger value = ownerAllowed.get(spender);
+ if (value == null) {
+ value = BigInteger.ZERO;
+ }
+ return value;
+ }
+
+ @Override
+ public boolean transferFrom(@Required Address from, @Required Address to, @Required BigInteger value) {
+ subtractAllowed(from, Msg.sender(), value);
+ subtractBalance(from, value);
+ addBalance(to, value);
+ emit(new TransferEvent(from, to, value));
+ return true;
+ }
+
+ @Override
+ @View
+ public BigInteger balanceOf(@Required Address owner) {
+ require(owner != null);
+ BigInteger balance = balances.get(owner);
+ if (balance == null) {
+ balance = BigInteger.ZERO;
+ }
+ return balance;
+ }
+
+ @Override
+ public boolean transfer(@Required Address to, @Required BigInteger value) {
+ subtractBalance(Msg.sender(), value);
+ addBalance(to, value);
+ emit(new TransferEvent(Msg.sender(), to, value));
+ return true;
+ }
+
+ @Override
+ public boolean approve(@Required Address spender, @Required BigInteger value) {
+ setAllowed(Msg.sender(), spender, value);
+ emit(new ApprovalEvent(Msg.sender(), spender, value));
+ return true;
+ }
+
+ public boolean increaseApproval(@Required Address spender, @Required BigInteger addedValue) {
+ addAllowed(Msg.sender(), spender, addedValue);
+ emit(new ApprovalEvent(Msg.sender(), spender, allowance(Msg.sender(), spender)));
+ return true;
+ }
+
+ public boolean decreaseApproval(@Required Address spender, @Required BigInteger subtractedValue) {
+ check(subtractedValue);
+ BigInteger oldValue = allowance(Msg.sender(), spender);
+ if (subtractedValue.compareTo(oldValue) > 0) {
+ setAllowed(Msg.sender(), spender, BigInteger.ZERO);
+ } else {
+ subtractAllowed(Msg.sender(), spender, subtractedValue);
+ }
+ emit(new ApprovalEvent(Msg.sender(), spender, allowance(Msg.sender(), spender)));
+ return true;
+ }
+
+ private void addAllowed(Address address1, Address address2, BigInteger value) {
+ BigInteger allowance = allowance(address1, address2);
+ check(allowance);
+ check(value);
+ setAllowed(address1, address2, allowance.add(value));
+ }
+
+ private void subtractAllowed(Address address1, Address address2, BigInteger value) {
+ BigInteger allowance = allowance(address1, address2);
+ check(allowance, value, "Insufficient approved token");
+ setAllowed(address1, address2, allowance.subtract(value));
+ }
+
+ private void setAllowed(Address address1, Address address2, BigInteger value) {
+ check(value);
+ Map<Address, BigInteger> address1Allowed = allowed.get(address1);
+ if (address1Allowed == null) {
+ address1Allowed = new HashMap<Address, BigInteger>();
+ allowed.put(address1, address1Allowed);
+ }
+ address1Allowed.put(address2, value);
+ }
+
+ private void addBalance(Address address, BigInteger value) {
+ BigInteger balance = balanceOf(address);
+ check(value, "The value must be greater than or equal to 0.");
+ check(balance);
+ balances.put(address, balance.add(value));
+ }
+
+ private void subtractBalance(Address address, BigInteger value) {
+ BigInteger balance = balanceOf(address);
+ check(balance, value, "Insufficient balance of token.");
+ balances.put(address, balance.subtract(value));
+ }
+
+ private void check(BigInteger value) {
+ require(value != null && value.compareTo(BigInteger.ZERO) >= 0);
+ }
+
+ private void check(BigInteger value1, BigInteger value2) {
+ check(value1);
+ check(value2);
+ require(value1.compareTo(value2) >= 0);
+ }
+
+ private void check(BigInteger value, String msg) {
+ require(value != null && value.compareTo(BigInteger.ZERO) >= 0, msg);
+ }
+
+ private void check(BigInteger value1, BigInteger value2, String msg) {
+ check(value1);
+ check(value2);
+ require(value1.compareTo(value2) >= 0, msg);
+ }
+
+
+
+}
+
+



Input Project name, click finish

Smart contract code compilation refers to [developer document] (http://dev.nuls.io/contract/)

Click NULS plugin on the right, and call NULS plugin interface

Plugin automatically generates a node 127.0.0.1:8001, and developer adds a node to deploy the contract. +Recommendation: Start the local wallet, and add the wallet address as the node address.
Click + on the top left corner of panel, and select Add Node.

Input Node address and clock OK

Click + on the top left corner of panel, and select Add Account. Input Account address and click OK.

Click the second button on the top left corner of plugin to directly package the current Project. Two output forms after packaging: Jar package and Hex code

Click [copy code] to copy the HEX code to the [deploy contract] interface of wallet to deploy contract (optional step).

Click the third button on the plugin panel top or [Next] at the button of current package interface to access contract deploying interface


On Deploy interface, select the node and account for deploying contract from pull-down list. JarFilePath default value is the package route of the previous step.

Parameters following JarFilePath are the parameters of the contract construction function.

Click [advanced] to set gas value and price value. Gas varies from 1 to 10000000. Recommend to set a greater gas value to avoid failing in deploying contract.

Click [Test Deploy] to conduct a trial deployment of contract. In case of a success, it gives prompt of Success.

If success, click [Deploy]. After confirmation of contract creation transaction, it feeds back details of transaction, indicating a success of contract deployment.

Review the deployed contract on the top of panel

Click the deployed contract to review all method of this contract

NULS is a blockchain infrastructure for customizable services, driven by our global open-source community.
The NULS document library is a collection of all NULS documents. Here you can learn about technical manuals of NULS, NULS community, user manuals and other aspects.
References:
[Solidity Pitfalls: Random Number Generation for Ethereum] +(https://www.sitepoint.com/solidity-pitfalls-random-number-generation-for-ethereum/)
[Predicting Random Numbers in Ethereum Smart Contracts] +(https://blog.positive.com/predicting-random-numbers-in-ethereum-smart-contracts-e5358c6b8620)
Linear Congruential Generator (LCG): algorithm to generate pseudorandom numbersThe NULS smart contract SDK provides a way to create random numbers. It takes the current block's miner address, contract address, contract invoker address, and current block’s timestamp as random factors, and uses the algorithm linear congruential generator (LCG) to generate pseudorandom numbers
Invoking like this:
io.nuls.contract.sdk.Utils.pseudoRandom();
+/**
+ * add a random factor
+ */
+io.nuls.contract.sdk.Utils.pseudoRandom(long seed);
+--
BlockHash of the future blockTaking lottery as an example, it needs to invoke contract transactions twice - close the lottery and pick the winner.
Once the lottery is closed, record the current block height H1 and generate a number N. Pick the winner when the height of the future block reaches H1+N。
When picking the winner, add up the recorded block height H1 and block number in interval (0~80] (to be determined) to the block height H2, and take the BlockHash of the block H2 as a random seed.
ETH cannot use this way for the following reasons:
+
--
In the case of lottery, we need more arbitrary data for picking our winner. When we determine the winner, we can use the addresses of the players that have entered our lottery smart contract as random factors to generate random numbers.
--
Also take the lottery as an example.
The contract sets aside awards for the random number.
Each user generates own secret random number N.
Users can hash their N and address to generate the hash value of their secret random numbers: String hash = sha3(N + Msg.sender()).
Note: step 2 and 3 should be performed locally, for instance, the user submits N to the lottery application, which performs the hash operation.
Users submit their hash to the smart contract.
Submission is open until the number of blocks reaches a certain value, or until enough participants join.
Once the submission is closed, it’s time to pick the winner.
Each user submits their random number N to the smart contract.
The contract verifies sha3 (N + Msg.sender()) to match the original submission.
If the user fails to submit a valid N in time, his deposit will be forfeited.
Perform XOR operation on all-verified N to get random numbers.
These numbers are used to determine the winners --> (N % numUsers).
+ ← + + Service charge + + Wallet adds a random seed + + → +
The random seed you get is a big number, and notice, it could be a negative number
URL:/random/seeds/height
Method:GET
Prams:
| parameter | type | Required | remark |
|---|---|---|---|
| startHeight | Long | True | Initial height of interval |
| endHeight | Long | True | Interval cutoff height, cannot exceed startHeight+1000 |
Returns:
| field | type | Remark |
|---|---|---|
| success | boolean | Successful or not |
| data | array | The seed array |
Example:
Request:
curl -X GET "http://127.0.0.1:8001/api/random/seeds/height?startHeight=500&endHeight=510" -H "accept: application/json"
+Response:
{
+ "success": true,
+ "data": [
+ "8486473738212806059384942122915964966516544811115122625378589706648696927875",
+ "5763677830362183770819418466587054532227472729077319516033962399030101482330",
+ "-21576822359476915572374120992682286995340746526938743512234391635989859550499",
+ "21657748356022199241379814087980601843534504184851063250908405386419429001546",
+ "-31320197741848993348465901825403870475226356831977749494101003161293910010564",
+ "16054257794265746474880657765642725318937086559191102027715411501558318980478",
+ "39222628335763902261547055653161137231901517785016195993008289217415793052023",
+ "28759812140738813907858073405869390691919557824743093132519210315994120629868",
+ "26779511442264535228335930919961858598639368721086477781863239801135250744386",
+ "-23481782415506504277094909296039579696138464413290902597168011374639343982630"
+ ]
+}
+URL:/random/seeds/count
Method:GET
Prams:
| parameter | type | Required | remark |
|---|---|---|---|
| height | Long | True | Gets the maximum height of the seed list |
| count | Long | True | Random seed count, no more than 128 |
Returns:
| field | type | Remark |
|---|---|---|
| success | boolean | Successful or not |
| data | array | The seed array |
Example:
Request:
curl -X GET "http://127.0.0.1:8001/api/random/seeds/count?height=500&count=10" -H "accept: application/json"
+Response:
{
+ "success": true,
+ "data": [
+ "8486473738212806059384942122915964966516544811115122625378589706648696927875",
+ "5763677830362183770819418466587054532227472729077319516033962399030101482330",
+ "-21576822359476915572374120992682286995340746526938743512234391635989859550499",
+ "21657748356022199241379814087980601843534504184851063250908405386419429001546",
+ "-31320197741848993348465901825403870475226356831977749494101003161293910010564",
+ "16054257794265746474880657765642725318937086559191102027715411501558318980478",
+ "39222628335763902261547055653161137231901517785016195993008289217415793052023",
+ "28759812140738813907858073405869390691919557824743093132519210315994120629868",
+ "26779511442264535228335930919961858598639368721086477781863239801135250744386",
+ "-23481782415506504277094909296039579696138464413290902597168011374639343982630"
+ ]
+}
+URL:/random/seed/height
Method:GET
Prams:
| parameter | type | Required | remark |
|---|---|---|---|
| startHeight | Long | True | Initial height of interval |
| endHeight | Long | True | Interval cut-off height,endHeight-startHeight<=1000 |
| algorithm | String | false | The default is sha3 algorithm, supporting sha3, KECCAK, merkle algorithm |
Returns:
| field | type | Remark |
|---|---|---|
| success | boolean | Successful or not |
| data | Object | The result object |
| seed | String | Calculate the random seed result |
| algorithm | String | Computational algorithm |
| count | int | Number of original random seeds |
Example:
Request:
curl -X GET "http://192.168.1.123:8001/api/random/seed/height?startHeight=600&endHeight=610&algorithm=sha3" -H "accept: application/json"
+Response:
{
+ "success": true,
+ "data": {
+ "seed": "49349273589710891971526183625401126395677304794754035539210022261211357904457",
+ "algorithm": "sha3",
+ "count": 10
+ }
+}
+URL:/random/seed/count
Method:GET
Prams:
| parameter | type | Required | remark |
|---|---|---|---|
| height | Long | True | Gets the maximum height of the seed list |
| count | Long | True | Random seed count, no more than 128 |
| algorithm | String | false | The default is sha3 algorithm, supporting sha3, KECCAK, merkle algorithm |
Returns:
| field | type | Remark |
|---|---|---|
| success | boolean | Successful or not |
| data | Object | The result object |
| seed | String | Calculate the random seed result |
| algorithm | String | Computational algorithm |
| count | int | Number of original random seeds |
Example:
Request:
curl -X GET "http://192.168.1.123:8001/api/random/seed/count?height=600&count=10&algorithm=merkle" -H "accept: application/json"
+Response:
{
+ "success": true,
+ "data": {
+ "seed": "49349273589710891971526183625401126395677304794754035539210022261211357904457",
+ "algorithm": "merkle",
+ "count": 10
+ }
+}
+Similar to the above RPC interface, the smart contract SDK supports the same method to obtain the random number seed provided by the underlying blockchain, such as the following code.
+Take one of these methods as an exampleUtils.getRandomSeed(long endHeight, int seedCount, String algorithm) Shows how to generate random Numbers using random number seeds.
/**
+ * [Testnet]According to the cutoff height and the number of original seeds, a specific algorithm is used to generate a random seed
+ *
+ * @param endHeight End height
+ * @param seedCount Number of original seeds
+ * @param algorithm Hash algorithm identification
+ * @return After the original seed byte array is merged, the 32-bit hash byte array is obtained using the hash algorithm and converted to BigInteger(new BigInteger(byte[] bytes))
+ */
+public static native BigInteger getRandomSeed(long endHeight, int seedCount, String algorithm);
+
+/**
+ * [Testnet]According to the height and the original seed number, use the ` SHA3-256 ` hash algorithm to generate a random seed
+ *
+ * @param endHeight End height
+ * @param seedCount Number of original seeds
+ * @return After the original seed byte array is merged, the 32-bit hash byte array is obtained using the hash algorithm and converted to BigInteger(new BigInteger(byte[] bytes))
+ */
+public static BigInteger getRandomSeed(long endHeight, int seedCount) {
+ return getRandomSeed(endHeight, seedCount, "SHA3");
+}
+
+/**
+ * [Testnet]According to the height range, a specific algorithm is used to generate a random seed
+ *
+ * @param startHeight Start height
+ * @param endHeight Number of original seeds
+ * @param algorithm Hash algorithm identification
+ * @return After the original seed byte array is merged, the 32-bit hash byte array is obtained using the hash algorithm and converted to BigInteger(new BigInteger(byte[] bytes))
+ */
+public static native BigInteger getRandomSeed(long startHeight, long endHeight, String algorithm);
+
+/**
+ * [Testnet]According to height, use ` SHA3-256 ` hash algorithm to generate a random seed
+ *
+ * @param startHeight Start height
+ * @param endHeight End height
+ * @return After the original seed byte array is merged, the 32-bit hash byte array is obtained using the hash algorithm and converted to BigInteger(new BigInteger(byte[] bytes))
+ */
+public static BigInteger getRandomSeed(long startHeight, long endHeight){
+ return getRandomSeed(startHeight, endHeight, "SHA3");
+}
+
+/**
+ * [Testnet]According to the cutoff height and the number of original seeds, the collection of original seeds was obtained
+ *
+ * @param endHeight End height
+ * @param seedCount Number of original seeds
+ * @return Returns a collection of original seeds, whose elements are BigInteger converted from byte arrays(new BigInteger(byte[] bytes))
+ */
+public static native List<BigInteger> getRandomSeedList(long endHeight, int seedCount);
+
+/**
+ * [Testnet]Get the set of original seeds according to the height range
+ *
+ * @param startHeight Start height
+ * @param endHeight End height
+ * @return Returns a collection of original seeds, whose elements are BigInteger converted from byte arrays(new BigInteger(byte[] bytes))
+ */
+public static native List<BigInteger> getRandomSeedList(long startHeight, long endHeight);
+example shaking at the same time NUtils.getRandomSeed(long endHeight, int seedCount, String algorithm)Refer to the following code
public List<Integer> dice(long endHeight, int count, int range, int times) {
+ BigInteger orginSeed = getRandomSeed(endHeight, count, "sha3");
+ if (orginSeed.equals(BigInteger.ZERO)) {
+ return null;
+ }
+ BigInteger wrapperRange = BigInteger.valueOf((long) range);
+ List<Integer> resultList = new ArrayList<Integer>(times);
+ for (int i = 0; i < times; i++) {
+ if(i == 0) {
+ BigInteger mod = orginSeed.mod(wrapperRange);
+ resultList.add(mod.intValue());
+ } else {
+ BigInteger multiply = orginSeed.multiply(BigInteger.valueOf(i + 1));
+ String s = sha3(multiply.toByteArray());
+ byte[] decode = decode(s);
+ BigInteger bigInteger = new BigInteger(decode);
+ BigInteger mod = bigInteger.mod(wrapperRange);
+ resultList.add(mod.intValue());
+ }
+ }
+ return resultList;
+}
+
+public byte[] decode(String hexString) {
+ byte[] bts = new byte[hexString.length() / 2];
+ for (int i = 0; i < bts.length; i++) {
+ bts[i] = (byte) Integer.parseInt(hexString.substring(2 * i, 2 * i + 2), 16);
+ }
+ return bts;
+}
+Utils.getRandomSeed(long endHeight, int seedCount, String algorithm)Refer to the following code
public List<Integer> diceAnother(long endHeight, int count, int range, int times) {
+ BigInteger orginSeed = getRandomSeed(endHeight, count, "sha3");
+ if (orginSeed.equals(BigInteger.ZERO)) {
+ return null;
+ }
+ BigInteger wrapperRange = BigInteger.valueOf((long) range);
+ List<Integer> resultList = new ArrayList<Integer>(times);
+ BigInteger mod = orginSeed.mod(wrapperRange);
+ resultList.add(mod.intValue());
+ String orginStr = orginSeed.toString();
+ int length = orginStr.length();
+ for (int i = 1; i < times; i++) {
+ int c = orginStr.charAt(length - i);
+ BigInteger multiply = orginSeed.multiply(BigInteger.valueOf(c));
+ String s = sha3(multiply.toByteArray());
+ byte[] decode = decode(s);
+ BigInteger bigInteger = new BigInteger(decode);
+ mod = bigInteger.mod(wrapperRange);
+ resultList.add(mod.intValue());
+ }
+ return resultList;
+}
+
+public byte[] decode(String hexString) {
+ byte[] bts = new byte[hexString.length() / 2];
+ for (int i = 0; i < bts.length; i++) {
+ bts[i] = (byte) Integer.parseInt(hexString.substring(2 * i, 2 * i + 2), 16);
+ }
+ return bts;
+}
++ ← + + Ways of creating random numbers + + SDK + + → +
[TOC]
Data interaction between modules is done through RPC-TOOL
RPC-TOOL is the underlying application, and any module will depend on RPC-TOOL.
Interface description +Kernel will periodically push the status of the current system to each module, which is used for receiving
Request example
{
+ "cmd":"status",
+ "minVersion":1,
+ "params":[
+ {
+ "service":[
+ "a",
+ "b",
+ "c"
+ ],
+ "available":true,
+ "modules":{
+ "moduleABC":{
+ "name":"moduleABC",
+ "status":"READY",
+ "available":false,
+ "addr":"127.0.0.1",
+ "port":19722,
+ "rpcList":[
+ {
+ "cmd":"shutdown",
+ "version":1
+ },
+ {
+ "cmd":"cmd1",
+ "version":1
+ },
+ {
+ "cmd":"conf_reset",
+ "version":1
+ },
+ {
+ "cmd":"terminate",
+ "version":1
+ }
+ ],
+ "dependsModule":[
+ "m2",
+ "m3"
+ ]
+ }
+ }
+ }
+ ]
+}
+Request parameter specification
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | modules_information | true | map | All module information |
modules_information
| parameter | required | type | description |
|---|---|---|---|
| service | true | string[] | The dependent modules |
| available | true | boolean | can start service? |
| modules | true | map<name, module> | All module information |
module
| parameter | required | type | description |
|---|---|---|---|
| name | true | string | name |
| status | true | string | status |
| available | true | boolean | can start service? |
| addr | true | string | ip address/host name |
| port | true | int | port |
| rpcList | true | list | cmd list |
| dependsModule | true | string[] | The dependent modules |
Response example +Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+Success
{
+"version": 1.2,
+ "code":0,
+ "result":{}
+}
+Response field specification +N/A
Interface description +Kernel calls the interface to close the module (waiting for all the processing of the current business to complete)
Request example
{
+ "cmd":"shutdown",
+ "minVersion":1,
+ "params":[]
+}
+Request parameter specification
N/A
Response example +Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+Success
{
+ "version": 1.2,
+ "code":0,
+ "result":{}
+}
+Response field specification +N/A
Interface description +Kernel calls the interface to close the module (immediately terminates).
Request example
{
+ "cmd":"terminate",
+ "minVersion":1,
+ "params":[]
+}
+Request parameter specification
N/A
Response example +Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+Success
{
+ "version": 1.2,
+ "code":0,
+ "result":{}
+}
+Response field specification +N/A
Interface description +Kernel gets module configuration items
Request example
{
+ "cmd":"confGet",
+ "minVersion":1,
+ "params":[]
+}
+Request parameter specification
N/A
Response example +Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+Success
{
+ "version": 1.2,
+ "code":0,
+ "result":{
+ "key1": "value1",
+ "key2": "value2"
+ }
+}
+Response field specification +N/A
Interface description +Kernel sets module configuration items
Request example
{
+ "cmd":"confSet",
+ "minVersion":1,
+ "params":[
+ {
+ "key1":"value1",
+ "key2":"value2"
+ }
+ ]
+}
+Request parameter specification
N/A
Response example +Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+Success
{
+ "version": 1.2,
+ "code":0,
+ "result":{}
+}
+Response field specification +N/A
Interface description +Kernel restore template is configured as initial value.
Request example
{
+ "cmd":"confReset",
+ "minVersion":1,
+ "params":[]
+}
+Request parameter specification
N/A
Response example +Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+Success
{
+ "version": 1.2,
+ "code":0,
+ "result":{}
+}
+Response field specification +N/A
Start server
// Port is not necessary. If no port is specified, the system is allocated randomly
+BaseRpcServer server = new GrizzlyServer(RpcConstant.KERNEL_PORT);
+
+// Scan the package in which the CMD command is located
+server.scanPackage("io.nuls.rpc.mycmd");
+
+// Initialization
+server.init("moduleName", "dependsModule, type is List<String>");
+
+// start
+server.start();
+Custom CMD
// extends BaseCmd
+public class SomeCmd extends BaseCmd
+
+// Custom method to add annotation CmdInfo
+@CmdInfo(cmd = "cmd1", version = 1.0, preCompatible = true)
+public Object methodName(List params) {
+ System.out.println("I'm version 1");
+ return success();
+}
+
+Note: rpc-tool automatically transfers the Object[] transferred from client to List<Object>.
+There must be and only one CMD class to implement the KernelCmd interface.
// Implement interface
+public class SomeCmd extends BaseCmd implements KernelCmd
+
+/**
+ * Receive all module information from kernel
+ */
+public Object status(List params);
+
+/**
+ * Shut down service: after the existing business is completed
+ */
+public Object shutdown(List params);
+
+/**
+ * Shut down service: close immediately, whether or not the business is completed.
+ */
+public Object terminate(List params);
+
+/**
+ * Provide local configuration information
+ */
+public Object confGet(List params);
+
+/**
+ * Update local configuration information
+ */
+public Object confSet(List params);
+
+/**
+ * Reset local configuration information
+ */
+public Object confReset(List params);
+Provide module information to kernel
RpcClient.versionToKernel();
+call rpc
// CMD corresponds to one interface.
+String jsonStr = RpcClient.callSingleRpc("shutdown", params, minVersion);
+
+// CMD corresponds to multiple interfaces.
+String jsonStr = RpcClient.callMultiplyRpc("shutdown", params, minVersion);
+
+note:
+params is instance of Object[]
+Request
{
+ "cmd": "shutdown",
+ "minVersion": 1.0, //根据自己需要传最低版本号
+ "params": [],
+}
+Response(success and failure are the same)
{
+ "code":0,
+ "msg": " This property is only available when failed",
+ "version": "Actually called version",
+ "result": {}
+}
+BaseCmd has a default implementation of the status method, so if you don't have a specific requirement, you just need to do the following:
@Override
+@CmdInfo(cmd = RpcConstant.STATUS, version = 1.0, preCompatible = true)
+public Object status(List params){
+ return super.status(params);
+}
+There are ways to return to success and failure in BaseCmd.
+success:
protected Object success(double version) {
+ return success(version, null);
+}
+
+protected Object success(double version, Object result) {
+ Map<String, Object> map = new HashMap<>(16);
+ map.put("code", 0);
+ map.put("msg", SUCCESS);
+ map.put("version", version);
+ map.put("result", result);
+ return map;
+}
+fail:
protected Object fail(String code, String msg, double version, Object result) {
+ Map<String, Object> map = new HashMap<>(16);
+ map.put("code", code);
+ map.put("msg", msg);
+ map.put("version", version);
+ map.put("result", result);
+ return map;
+}
++ ← + + Build Chain + + Quick Start + + → +
This document is the user guide for the NULS Java SDK. It describes the usage instructions of the basic functional interfaces such as accounts, transactions, and blocks provided by the NULS service.
| Version | Release Date | Release Notes |
|---|---|---|
| v0.9.11.0 | 2018-06-19 | Provide interfaces for docking basic functions of the NULS service |
| v0.9.11.1 | 2018-06-22 | Add interfaces to get the latest block height and hash (3.6, 3.7), and modify 2.1 |
| v0.9.14 | 2018-07-04 | Modify the initialization method of the SDK to init in Quick Start and the usage of SDK, and alter the name of the returned encapsulated object (removing Dto, etc.) |
| v0.9.15 | 2018-07-07 | Add four consensus interfaces (4.1-4.4) |
| v0.9.16 | 2018-07-11 | Add interface 4.5 |
| v1.0.1 | 2018-07-13 | Add error code |
| v1.1.0 | 2018-09-28 | Add multi-account transfer interface |
Import jar files by using build tool
<dependency>
+ <groupId>io.nuls.sdk</groupId>
+ <artifactId>sdk-all</artifactId>
+ <version>1.0.1</version>
+</dependency>
+First introduce SDK namespace
// introduce the namespace of the SDK boot class
+import io.nuls.sdk.SDKBootstrap;
+import io.nuls.sdk.model.Result;
+// introduce the namespace of the SDK calls tool
+import io.nuls.sdk.tool.NulsSDKTool;
+After importing, create a client instance using the following code
127.0.0.1, 8001 //By default
+SDKBootstrap.init();
+// Pass in the NULS service’s IP and Port
+SDKBootstrap.init("192.168.1.88", "8001");
+Result result = NulsSDKTool.createAccount("nuls123456");
+e.g a complete example of creating an account with password
import io.nuls.sdk.SDKBootstrap;
+import io.nuls.sdk.model.Result;
+// introduce the namespace for corresponding modules as required
+import io.nuls.sdk.tool.NulsSDKTool;
+
+public static void main(String[] args) {
+ SDKBootstrap.init();
+ Result result = NulsSDKTool.createAccount("nuls123456");
+}
+--
Interface
Result createAccount(int count, String password);
Instructions
Creates one or more accounts with or without a password depending on the parameters passed in. +The information about the successfully created account will be persisted to the NULS service local database.
Returns a set of successfully created account addresses +
parameter type required or not note count int optional account count to be created (default 1) password String optional set the password of the account with length between 8 and 20, must containing both letters and digitals, the space not allowed
Return
Result object in the following format:{
+ "success": true,
+ "data":{
+ "list": [ // Return a set of the created account addresses
+ "2Cbkwxu34iCjsiHKBjqZDNjoVbLMcJv",
+ "2Cbkwxu34iCjsiHKBjqZDNjoVbLMcJv"
+ ]
+ }
+}
+e.g Sample Code
//create an account without password
+createAccount();
+//create an account with password
+createAccount("nuls123456");
+// create three password-less accounts
+createAccount(3);
+// create three accounts with passwords
+createAccount(3, "nuls123456");
+Interface
Result createOfflineAccount(int count, String password)
Instructions
Directly create an offline account and return it completely, without underlying interaction with NULS and persistence +Creates an encrypted off-line account (Not saved to the database)
Result.data
List<AccountInfo>
| parameter | type | required or not | note |
|---|---|---|---|
| count | int | optional | account count to be created (default 1) |
| password | String | optional | set the password of the account with length between 8 and 20, must containing both letters and digitals, the space not allowed |
Return
Result object in the following format:{
+ "success": true,
+ "data": {
+ "list":[
+ {
+ "address": String, account address
+ "alias": String, account alias
+ "pubKey": String, public key
+ "extend": String, extension
+ "createTime": Long, create time
+ "encrypted": boolean, encrypted or not
+ "priKey": String, private key(not null only if a password-less offline account is created)
+ "encryptedPriKey": String, encrypted private key(not null only if an offline account with password is created)
+ },
+ {
+ "address": "2CiBQg72BCLmLqttRpPfp8ECRCBwbdD",
+ "alias": null,
+ "pubKey": "020159dc5cc74463f346b71c08dd934a823e9e6fe727d8d3c577e7d462e1a364bb",
+ "extend": null,
+ "createTime": 1529314943624,
+ "encrypted": true,
+ "priKey": "",
+ "encryptedPriKey": "5664f746654fb111e967bb3922910b16340f1e60ff1b281c7a333179d7b82d6220bb12d1c058d9cd06099d4f443a4cb0"
+ }
+ ]
+ }
+}
+e.g Sample Code
// create an offline account without password
+createOfflineAccount();
+// create an offline account with password
+createOfflineAccount("nuls123456");
+// create three password-less offline accounts
+createOfflineAccount(3);
+// create three offline accounts with passwords
+createOfflineAccount(3, "nuls123456");
+Interface
Result getAccount(String address)
Instructions
Gets information about the account by account address
Result.data
AccountInfo
| parameter | type | required or not | note |
|---|---|---|---|
| address | String | required | account address |
Return
Result object in the following format:{
+ "success": true,
+ "data": {
+ "address": String, account address
+ "alias": String, account alias
+ "pubKey": String, public key
+ "extend": String, extension
+ "createTime": Long, create time
+ "encrypted": boolean, encrypted or not
+ "priKey": String, private key(not null only if when a password-less offline account is created)
+ "encryptedPriKey": String, encrypted private key(not null only if an offline account with password is created)
+ }
+}
+e.g Sample Code
getAccount("2ChqBTvFXttQsghj8zQpcdv76TQU8G5");
+Interface
Result getAliasFee(String address, String alias)
Instructions
Gets the fee required to set the alias name based on the account address and the alias name to be set (excluding the fixed cost 1NULS of setting the alias name)> +Result.data
double, unit isNULS
Note! The unit of the fee returned by this interface is NULS
| parameter | type | required or not | note |
|---|---|---|---|
| address | String | required | account address |
| alias | String | required | alias name to be set |
Return
Result object in the following format:{
+ "success": true,
+ "data":{
+ "value": 0.01 //( unit: NULS)
+ }
+}
+e.g Sample Code
getAliasFee("2ChqBTvFXttQsghj8zQpcdv76TQU8G5","factory666");
+Interface
Result getAccountList(int pageNumber, int pageSize)
Instructions
Gets a list of accounts based on the paging parameters
Result.data Page
List<AccountInfo>
| parameter | type | required or not | note |
|---|---|---|---|
| pageNumber | int | required | page number, must be greater than 0 |
| pageSize | int | required | record size displayed per page, ranging from 1 to 100 |
Return
Result object in the following format:{
+ "success": true,
+ "data": {
+ "pageNumber": 1,
+ "pageSize": 10,
+ "total": 100,
+ "pages": 10,
+ "list": [
+ {
+
+ "address": String, account address
+ "alias": String, account alias
+ "pubKey": String, public key
+ "extend": String, extension
+ "createTime": Long, create time
+ "encrypted": boolean, encrypted or not
+ "priKey": String, private key(not null only if a password-less offline account is created)
+ "encryptedPriKey": String, encrypted private key(not null only if an offline account with password is created) },
+ {
+ "address": "2Cid96JrTGA2XaNG6zXrRKh18kLUbLP",
+ "alias": null,
+ "pubKey": "033da2433ef4ca111bfeefaadd9fe0f5874f3aac5186109f9de10a9eed6f48f184",
+ "extend": null,
+ "createTime": 1529311250627,
+ "encrypted": true,
+ "priKey": null,
+ "encryptedPriKey": null
+ }
+ ...
+
+ ]
+ }
+}
+e.g Sample Code
getAccountList(1, 10);
+Interface
Result getAddressByAlias(String alias)
Instructions
Gets the account address by the account alias
Result.data
String
| parameter | type | required or not | note |
|---|---|---|---|
| alias | String | required | account alias |
Return
Result object in the following format:{
+ "success": true,
+ "data": {
+ "value": "2ChDcC1nvki521xXhYAUzYXt4RLNULS"
+ }
+}
+e.g Sample Code
getAddressByAlias("factory666");
+Interface
Result getPrikey(String address, String password)
Instructions
Gets the private key of the account by account address and password, and returns the private key string
Result.data
String
| parameter | type | required or not | note |
|---|---|---|---|
| address | String | required | account address |
| password | String | optional | account password, leave it blank if the account is not encrypted |
Return
Result object in the following format:{
+ "success": true,
+ "data": {
+ "value":"1f9d3ad044e0e1201e117b041f3d2ceedacb44688e57969620f3ad7a4d6e9d24"
+ }
+}
+e.g Sample Code
// the way of calling the account with password
+getPrikey("2ChqBTvFXttQsghj8zQpcdv76TQU8G5", "nuls123456");
+//the way of calling the password-less account
+getPrikey("2ChqBTvFXttQsghj8zQpcdv76TQU8G5");
+Interface
Result isAliasUsable(String alias)
Instructions
Verifies that the alias is available (if it is not used) by alias name
Result
| parameter | type | required or not | note |
|---|---|---|---|
| address | String | required | alias name |
Return
Result object in the following format:{ // indicate the alias is available
+ "success": true,
+ "data": {
+ "value":true
+ }
+}
+{ // indicate the alias is not available
+ "success": true,
+ "data":{
+ "value": false
+ }
+}
+{ // indicate an error
+ "success": false,
+ "data":{
+ "code": "ACT005",
+ "msg": "xxxxxx...."
+ }
+}
+e.g Sample Code
isAliasUsable("factory666");
+Interface
Result backupAccount(String address, String path, String password)
Instructions
Backups the account (exporting .Keystore file) based on the account address, password and output address. If the account is encrypted, the exported keystore file is encrypted by the current password. The password of the account needs to be verified when importing.
Result: the generated file address
| parameter | type | required or not | note |
|---|---|---|---|
| address | String | required | account address |
| path | String | required | the folder where the backup file will be stored. When null is passed in, it will be backed up to the current directory of the NULS service. |
| password | String | optional | account password, leave it blank if the account is not encrypted |
Return
Result object in the following format:{
+ "success": true,
+ "data": {
+ "value": "/Users/lichao/Downloads/2ChDcC1nvki521xXhYAUzYXt4RLNULS.accountkeystore"
+ }
+}
+e.g Sample Code
// Backup an password-less account to the current directory
+backupAccount("2ChqBTvFXttQsghj8zQpcdv76TQU8G5", null);
+// Backup an account with password to the /backup directory
+backupAccount("2ChqBTvFXttQsghj8zQpcdv76TQU8G5", "/backup", "nuls123456");
+Interface
Result importAccountByKeystore
Instrucions
Imports the account using the keystore file. If the keystore file is generated by an encrypted account backup, the password of the account at the time of backup needs to be verified.
Result
| parameter | type | required or not | note |
|---|---|---|---|
| path/fileReader | String/FileReader | required | the url of the .keystore file to be imported, or the FileReader object generated by the .keystore file |
| password | String | optional | the password of the account corresponding to the .keystore file, leave it blank if the account is not encrypted when the .keystore is exported |
| overwrite | boolean | required | true: perform overwrite import; false: if the account already exists in the wallet, the import will not be performed and an error prompt will be returned. |
Return
Result object in the following format:{
+ "success": true,
+ "data": {
+ "value":"2ChDcC1nvki521xXhYAUzYXt4RLNULS"
+ }
+}
+e.g Sample Code
//import an account with password
+importAccountByKeystore("/backup/XXXXXX.keystore", "nuls123456", true);
+importAccountByKeystore(fileReader, "nuls123456", true);
+//import a password-less account
+importAccountByKeystore("/backup/XXXXXX.keystore", false);
+importAccountByKeystore(fileReader, false);
+Interface
Result importAccountByPriKey(String privateKey, String password, boolean overwrite)
Instructions
Imports an account by private key
Result
| parameter | type | required or not | note |
|---|---|---|---|
| privateKey | String | required | private key of the account |
| password | String | optional | set the password of the account with length between 8 and 20, must containing both letters and digitals, the space not allowed |
| overwrite | boolean | required | true: perform overwrite import; false: if the account already exists in the wallet, the import will not be performed and an error prompt will be returned. |
Return
Result object in the following format:{
+ "success": true,
+ "data": {
+ "value":"2CiU1CmB6c9jmSLDNBe6PouA7NgNULS"
+ }
+}
+e.g Sample Code
// set a password when importing account
+importAccountByPriKey("1f9d3ad044e0e120......", "nuls123456", true);
+// no password is set when importing account
+importAccountByPriKey("1f9d3ad044e0e120......", true);
+Interface
Result isEncrypted(String address)
Instructions
Verifies the account is encrypted
Result
| parameter | type | required or not | note |
|---|---|---|---|
| address | String | required | account address |
Return
Result object in the following format:{ // indicate encrypted
+ "success": true,
+ "data": {
+ "value":true
+ }
+}
+{
+ "success": true,
+ "data":{
+ "value": false
+ }
+}
+{ //indicate an error
+ "success": false,
+ "data":{
+ "code": "ACT005",
+ "msg": "xxxxxx...."
+ }
+}
+e.g Sample Code
isEncrypted("2ChqBTvFXttQsghj8zQpcdv76TQU8G5");
+Interface
Result removeAccount(String address, String password)
Instructions
Removes an account
Result
| parameter | type | required or not | note |
|---|---|---|---|
| address | String | required | account address |
| password | String | optional | account password, leave it blank if the account is not encrypted |
Return
Result object in the following format:{ //indicate a success
+ "success": true,
+ "data": {
+ "value":true
+ }
+}
+{ // indicate an error
+ "success": false,
+ "data":{
+ "code": "ACT005",
+ "msg": "xxxxxx...."
+ }
+}
+e.g Sample Code
removeAccount("2ChqBTvFXttQsghj8zQpcdv76TQU8G5");
+removeAccount("2ChqBTvFXttQsghj8zQpcdv76TQU8G5", "nuls123456");
+Interface
Result setPassword(String address, String password)
Instructions
Sets a password for an unencrypted account. Encrypted account cannot call this interface.
Result
| parameter | type | required or not | note |
|---|---|---|---|
| address | String | required | account address |
| password | String | required | set the password of the account with length between 8 and 20, must containing both letters and digitals, the space not allowed |
Return
Result object in the following format:{ //indicate a success
+ "success": true,
+ "data": {
+ "value":true
+ }
+}
+{ // indicate an error
+ "success": false,
+ "data":{
+ "code": "ACT005",
+ "msg": "xxxxxx...."
+ }
+}
+e.g Sample Code
setPassword("2ChqBTvFXttQsghj8zQpcdv76TQU8G5", "nuls123456");
+Interface
Result resetPassword(String address, String password, String newPassword)
Instructions
Modifys the password for an encrypted account. Unencrypted account cannot call this interface.
Result
| parameter | type | required or not | note |
|---|---|---|---|
| address | String | required | account address |
| password | String | required | the current password of the account |
| newPassword | String | required | set new password of the account with length between 8 and 20, must containing both letters and digitals, the space not allowed. |
Return
Result object in the following format:{ //indicate a success
+ "success": true,
+ "data": {
+ "value":true
+ }
+}
+{ // indicate an error
+ "success": false,
+ "data":{
+ "code": "ACT005",
+ "msg": "xxxxxx...."
+ }
+}
+e.g Sample Code
resetPassword("2ChqBTvFXttQsghj8zQpcdv76TQU8G5", "nuls123456", "NULS111111");
+Interface
Result setAlias(String address, String alias, String password)
Instructions
Sets alias name for an account
Result: the hash of the transaction for setting the alias +
parameter type required or not note address String required account address alias String required alias name to be set password String password account password, leave it blank if the account is not encrypted
Return
Result object in the following format:{
+ "success": true,
+ "data":{
+ "value":"0020d7a69747778f6f02e2b0171640bc98aa19c53700988b7765c195ae691f3202c6"
+ }
+}
+{
+ "success": false,
+ "data":{
+ "code": "ACT007",
+ "msg": "The account already set an alias"
+ }
+}
+e.g Sample code
setAlias("2ChqBTvFXttQsghj8zQpcdv76TQU8G5", "factory666", "NULS111111");
+setAlias("2ChqBTvFXttQsghj8zQpcdv76TQU8G5", "factory666");
+Interface
Result setPasswordOffline(String address, String priKey, String password)
Instructions
Sets the password of the offline account, independently encrypted in SDK, without interaction with NULS service
Result: the encrypted private key(encryptedPriKey)
| parameter | type | required or not | note |
|---|---|---|---|
| address | String | required | account address |
| priKey | String | required | account’s private key |
| password | String | required | set new password of the account with length between 8 and 20, must containing both letters and digitals, the space not allowed |
Return
Result object in the following format:{
+ "success": true,
+ "data": {
+ "value":"a770c1886f566c973b6eb99543ef03825a89ed16e20d8dbe320aed64a85d5863ca23df43ef16ce0475424a49e192b6f9"
+ }
+}
+e.g Sample Code
setPasswordOffline("2CacFwqMwcJiGNNBwiwV7bCL7bjwNBr","00e4bfd347351ea899b5f0ae2c0a3e7a6951b202eaf72432d1a63a2dc85c59c82a","nuls123456");
+Interface
Result resetPasswordOffline(String address, String encryptedPriKey, String password, String newPassword)
Instructions
Modifies the password of the offline account independently in SDK, without interaction with NULS service
Result: the encrypted private key generated by the new password (encryptedPriKey)
| parameter | type | required or not | note |
|---|---|---|---|
| address | String | required | account address |
| encryptedPriKey | String | required | encrypted private key |
| password | String | required | original password |
| newPassword | String | required | set new password of the account with length between 8 and 20, must containing both letters and digitals, the space not allowed |
Return
Result object in the following format:{
+ "success": true,
+ "data": {
+ "value":"a770c1886f566c973b6eb99543ef03825a89ed16e20d8dbe320aed64a85d5863ca23df43ef16ce0475424a49e192b6f9"
+ }
+}
+e.g Sample Code
resetPasswordOffline("2CacFwqMwcJiGNNBwiwV7bCL7bjwNBr","25368dbc0ff7eea4fc6da22bc37e85d7976a3846f8b58d4dc0cf484e740ba1b61f96395fbe1ddf70ece9fd21fcd95e7a","NULS111111", "nuls123456");
+Interface
Result createTransaction(List<Input> inputs, List<Output> outputs, String remark)
Instructions
Assembles the transaction by the input/output of the transaction passed in by the user. The parameters passed in are json objects, as shown in the e.g. section. **The input and output attributes in the example are mandatory. ** The fee is the difference between the total amount of inputs and outputs. There will be a minimum value for the fee based on the transaction size. When its fee is lower than the minimum value, the transaction will not be packaged. The calculation of the fee will be explained in detail later
Result.data
String: serialized transaction string in hexadecimal +
parameter type required or not note inputs List<Input> required usable output referred by the transaction outputs List<Output> required usable output newly generated by the transaction remark String optional transaction remarks
e.g Sample Code
String remark = "create transaction demo";
+long fee = 100000;
+List<Input> inputs = new ArrayList<>();
+List<Output> outputs = new ArrayList<>();
+
+// the inputs for assembly transaction, the attribute of the input in the example is mandatory.
+Input input = new Input();
+input.setFromHash("002023c66d10cf9047dbcca12aee3db3c921a2ec22e0dd63331cb85");
+input.setFromIndex(1);
+input.setAddress("2ejPVMKST7h4Qsd5Dqa8Q9Psr47mj5")
+input.setValue(1000000000L);
+input.setLockTime(0);
+inputs.add(input);
+
+// the outputs for assembly transaction, the attribute of the output in the example is mandatory.
+Output output = new Output();
+output.setAddress("2CjPVMKST7h4Q5Dqa8Q9P9CwYSmN7mG");
+output.setValue(1000000L);
+output.setLockTime(0L);
+outputs.add(output);
+
+output = new Output();
+output.setAddress("2CXJEuoXZMajeTEgL6TgiSxTRRMwiMM");
+output.setValue(1000000000L - 1000000 - fee);
+output.setLockTime(0L);
+outputs.add(output);
+
+Result result = NulsSDKTool.createTransaction(inputs, outputs, remark);
+** Calculation of transaction fee **: unit price of the fee* transaction size
** unit price of the fee (min)**:100000 NA/1KB
Calculation of transaction size:(124 + 50 * inputs.length + 38 * outputs.length + remark.bytes.length )/1024 +124 is the fixed length of the basic information, 50 is the length of a single input, 38 is the length of a single output, and remark is an optional field, whose byte length is calculated according to the UTF-8 character encoding when needed. The transaction size is in KB, and its maximum value is 300 KB. The part less than 1 KB is calculated as 1 KB. +When the block-forging node verifies each transaction, the difference between the input and the output is regarded as the fee paid by the user when the transaction is sent, and the minimum value of the fee is calculated based on the transaction size. If the user's fee is less than the minimum value, it will be regarded as an invalid transaction and will not be packaged. Therefore, when creating a transaction, you should calculate the fee with care to avoid transaction failure.
Interface
Result signTransaction(String txHex, String priKey, String address, String password)
Instructions
Signs the transaction by private key
Result.data
String: the signed transaction, serialized string in hexadecimal
| parameter | type | required or not | note |
|---|---|---|---|
| txHex | String | required | serialized transaction data in hexadecimal |
| priKey | String | required | private key of the transaction |
| address | String | required | the address corresponding to the private key, used to verify the validity of the private key. |
| password | String | optional | the password of the private key, leave it blank if the private key is not encrypted |
e.g Sample Code
String txHex ="020197320f96301001a78cb7fb8bb7b1710b4afa390d8341080fba7a47e8d030000000000000000";
+String priKey ="252f6d9d55b7ef539ea58df99ebaf71c9929bd9d0054338baf7a59c9b85b4fa631f816907c8";
+String address = "2CXJEuoXZMajeTEgL6TgiSxTRRMwiMM";
+String password = "NULS6352s!f";
+Result result = NulsSDKTool.signTransaction(txHex, priKey, address, password);
+Interface
Result getTxByHash(String hash)
Instructions
Queries transaction details by transaction hash
Result.data:
Transaction
| parameter | type | required or not | note |
|---|---|---|---|
| hash | String | required | transaction hash |
Return
Result object in the following format:{
+ "success": true,
+ "data": {
+ "hash": "00203a169b42e5e142e20b273ac925e55f773b5a38c5f5c907efdbc43abb7d7a67b2",
+ "type": 2,
+ "time": 1529323198461,
+ "blockHeight": 1884,
+ "fee": 100000,
+ "value": 99900000000,
+ "remark": "transfer",
+ "scriptSig": "21036dd27c9fa786a1e83df204e9b31ddc24745c378f1f6b42731d07f05347167c0000473045022100ff3372711d78eb554be331aa40cd7af246641ecd3bc06f2fdca7faefb25f74e50220743a2f2d9d01b5a77a878349b996cbe4953af5d1a946519a5ce4d1129cf99848",
+ "status": 1,
+ "confirmCount": 14,
+ "size": 255,
+ "inputs": [
+ {
+ "fromHash": "0020ab020707282932e6ec701f0b64e22e937fdd03ce9b37aab498aed2e00b6fa8e7",
+ "fromIndex": 0,
+ "address": "2ChDcC1nvki521xXhYAUzYXt4RLNULS",
+ "value": 9999899000000
+ }
+ ],
+ "outputs": [
+ {
+ "txHash": "00203a169b42e5e142e20b273ac925e55f773b5a38c5f5c907efdbc43abb7d7a67b2",
+ "index": 0,
+ "address": "2CiVA3n1VoNQobAax4d7qNEBZAfehLN",
+ "value": 99900000000,
+ "lockTime": 0,
+ "status": 0
+ },
+ {
+ "txHash": "00203a169b42e5e142e20b273ac925e55f773b5a38c5f5c907efdbc43abb7d7a67b2",
+ "index": 1,
+ "address": "2ChDcC1nvki521xXhYAUzYXt4RLNULS",
+ "value": 9899998900000,
+ "lockTime": 0,
+ "status": 0
+ }
+ ]
+ }
+}
+e.g Sample Code
getTxByHash("041f3d2ceed........");
+Interface
Result transfer(String address, String toAddress, String password, long amount, String remark)
Instructions
Initiates a transfer transaction
Result: the transaction hash
| parameter | type | required or not | note |
|---|---|---|---|
| address | String | required | address of the transferor account |
| toAddress | String | required | address of the transferee account |
| password | String | optional | password of the transferor account, leave it blank if the account is not encrypted. |
| amount | long | required | transfer amount (unit: Na) |
| remark | String | required | remarks |
Return
Result object in the following format:{
+ "success": true,
+ "data": {
+ "value":"00203a169b42e5e142e20b273ac925e55f773b5a38c5f5c907efdbc43abb7d7a67b2"
+ }
+}
+e.g Sample Code
//account with password
+transfer("2ChDcC1nvki521xXhYAUzYXt4RLNULS", "2CiU1CmB6c9jmSLDNBe6PouA7NgXXXX", "nuls123456", 8888800000000, "remarks 1NULS=10000000Na");
+//account without password
+transfer("2ChDcC1nvki521xXhYAUzYXt4RLNULS", "2CiU1CmB6c9jmSLDNBe6PouA7NgNULS", 8888800000000, " remarks 1NULS=10000000Na");
+Interface
Result getBalance(String address)
Instructions
Gets the account balance
Result.data
BalanceInfo
| parameter | type | required or not | note |
|---|---|---|---|
| address | String | required | account address |
Return
Result object in the following format:{
+ "success": true,
+ "data": {
+ "balance": 1009899998900000,
+ "usable": 1009899998900000,
+ "locked": 0
+ }
+}
+e.g Sample Code
getBalance("2ChDcC1nvki521xXhYAUzYXt4RLNULS");
+Interface
Result broadcastTransaction(String txHex);
Instruction
Broadcasts a transaction
Result.data String: transaction hash
| parameter | type | required or not | note |
|---|---|---|---|
| txHex | String | required | serialized transaction data in hexadecimal |
Return
Result object in the following format:{
+ "success": true,
+ "data": {
+ "value": "002023c66d10cf9047dbcca12aee2235ff9dfe0f13db3c921a2ec22e0dd63331cb85"
+ }
+}
+
+e.g Sample Code
String txHex = "1f9d3ad044e0e1201e117b041f3d2ceedacb44688e57969620f3ad7a4d6e9d241f9d3ad044e0e1201e117b041f3d2ceedacb44688e57969620f3ad7a4d6e9d24";
+Result result = service.broadcastTransaction(txHex);
+if(result.isSuccess()) {
+ String txHash = (String)result.getData();
+}
+Interface
Result createMultipleInputAddressTransaction(List<Input> inputs, List<Output> outputs, String remark)
Instructions
Assembles the transaction by the input/output of the transaction passed in by the user. The parameters passed in are json objects, as shown in the e.g. section. **The input and output attributes in the example are mandatory. ** The fee is the difference between the total amount of inputs and outputs. There will be a minimum value for the fee based on the transaction size. When its fee is lower than the minimum value, the transaction will not be packaged. The calculation of the fee will be explained in detail later
Result.data
String: serialized transaction string in hexadecimal
| parameter | type | required or not | note |
|---|---|---|---|
| inputs | List<Input> | required | usable output referred by the transaction |
| outputs | List<Output> | required | usable output newly generated by the transaction |
| nInputAccount | int | required | input account number |
| remark | String | optional | transaction remarks |
e.g Sample Code
String remark = "create transaction demo";
+long fee = 100000;
+List<Input> inputs = new ArrayList<>();
+List<Output> outputs = new ArrayList<>();
+int nInputAccount = 2;
+
+//the inputs for assembly transaction, the attribute of the input in the example is mandatory.
+Input input = new Input();
+input.setFromHash("002023c66d10cf9047dbcca12aee3db3c921a2ec22e0dd63331cb85");
+input.setFromIndex(1);
+input.setAddress("2ejPVMKST7h4Qsd5Dqa8Q9Psr47mj5")
+input.setValue(1000000000L);
+input.setLockTime(0);
+inputs.add(input);
+
+//the outputs for assembly transaction, the attribute of the output in the example is mandatory.
+ Output output = new Output();
+output.setAddress("2CjPVMKST7h4Q5Dqa8Q9P9CwYSmN7mG");
+output.setValue(1000000L);
+output.setLockTime(0L);
+outputs.add(output);
+
+output = new Output();
+output.setAddress("2CXJEuoXZMajeTEgL6TgiSxTRRMwiMM");
+output.setValue(1000000000L - 1000000 - fee);
+output.setLockTime(0L);
+outputs.add(output);
+
+Result result = NulsSDKTool.createMultipleInputAddressTransaction(inputs,nInputAccount, outputs, remark);
+** Calculation of transaction fee **: unit price of the fee* transaction size
** unit price of the fee (min)**:100000 NA/1KB
Calculation of transaction size:(124*nInputAccount + 50 * inputs.length + 38 * outputs.length + remark.bytes.length )/1024 +124 is the fixed length of the basic information, 50 is the length of a single input, 38 is the length of a single output, and remark is an optional field, whose byte length is calculated according to the UTF-8 character encoding when needed. The transaction size is in KB, and its maximum value is 300 KB. The part less than 1 KB is calculated as 1 KB. +When the block-forging node verifies each transaction, the difference between the input and the output is regarded as the fee paid by the user when the transaction is sent, and the minimum value of the fee is calculated based on the transaction size. If the user's fee is less than the minimum value, it will be regarded as an invalid transaction and will not be packaged. Therefore, when creating a transaction, you should calculate the fee with care to avoid transaction failure.
Interface
Result signMultipleAddressTransaction(String txHex, List<String> privKeys, List<String> passwords)
Instructions
Signs a transaction by private key
Result.data
String: signed transaction, serialized string in hexadecimal
| parameter | type | required or not | note |
|---|---|---|---|
| txHex | String | required | serialized transaction data in hexadecimal |
| privKeys | List | required | private key of the transaction |
| passwords | List | required | password corresponding to the private key (passwords for multiple accounts must be the same) + |
e.g Sample Code
String txHex ="020197320f96301001a78cb7fb8bb7b1710b4afa390d8341080fba7a47e8d030000000000000000";
+List<String> priKeys = Arrays.asList("08a605b754bd1be1ba765fabd5cd218a545eb38b54ad26a7eb8a3378f724e5be", "00a710f9679fb6b5953bcfbea67a198e9c0d8888c43bad78a7241258e36aeaf65d");
+List<String> passwords = Arrays.asList("123456","123456");
+Result result = NulsSDKTool.signMultiTransaction(txHex, priKeys, passwords);
+Interface
Result getblockHeader(int height)
Instructions
Gets a block header by block height
Result.data
BlockHeader
| parameter | type | required or not | note |
|---|---|---|---|
| height | int | required | block height |
Return
Result object in the following format:{
+ "success": true,
+ "data": {
+ "hash": "002078656b6e32f4f1e9e881e7b6c4c5de036ae81ec5bf78861bde9480f5ff3a1b33",
+ "preHash": "0020ee5d28fde669adb0ad16f3ed426f1ee8df40560bed0ab30bb99cbf95df276d64",
+ "merkleHash": "0020cc37658e2d110c1d42f64c7fd3dcb56d9653d4edc4d3a8406cb263a41f9f5488",
+ "time": 1529299160000,
+ "height": 4,
+ "txCount": 4,
+ "packingAddress": "2CWsZb9w8XXTE58TUhBGczxf4U6NULS",
+ "scriptSig": "2102e18d02154e0f68900898efea7ba72d6d14e37d7d173a62146df2871f40996d7300473045022100d4d92a9518ffd855441c7712f4b31bd003291dc108fa2b455fe26d51e54625f102202ae8375bd69bf1928f9967edac82619ff78f30550c17797cc489d5effd3202bf",
+ "roundIndex": 419517,
+ "consensusMemberCount": 1,
+ "roundStartTime": 1529299150000,
+ "packingIndexOfRound": 1,
+ "confirmCount": 1909,
+ "reward": 0,
+ "fee": 0,
+ "size": 1
+ }
+}
+e.g Sample Code
getblockHeader(10);
+Interface
Result getblockHeader(String hash)
Instructions
Gets a block header by block hash
Result.data
BlockHeader
| parameter | type | required or not | note |
|---|---|---|---|
| hash | String | required | block hash |
Return
Result object in the following format:{
+ "success": true,
+ "data": {
+ "hash": "002078656b6e32f4f1e9e881e7b6c4c5de036ae81ec5bf78861bde9480f5ff3a1b33",
+ "preHash": "0020ee5d28fde669adb0ad16f3ed426f1ee8df40560bed0ab30bb99cbf95df276d64",
+ "merkleHash": "0020cc37658e2d110c1d42f64c7fd3dcb56d9653d4edc4d3a8406cb263a41f9f5488",
+ "time": 1529299160000,
+ "height": 4,
+ "txCount": 4,
+ "packingAddress": "2CWsZb9w8XXTE58TUhBGczxf4U6NULS",
+ "scriptSig": "2102e18d02154e0f68900898efea7ba72d6d14e37d7d173a62146df2871f40996d7300473045022100d4d92a9518ffd855441c7712f4b31bd003291dc108fa2b455fe26d51e54625f102202ae8375bd69bf1928f9967edac82619ff78f30550c17797cc489d5effd3202bf",
+ "roundIndex": 419517,
+ "consensusMemberCount": 1,
+ "roundStartTime": 1529299150000,
+ "packingIndexOfRound": 1,
+ "confirmCount": 1909,
+ "reward": 0,
+ "fee": 0,
+ "size": 1
+ }
+}
+e.g Sample Code
getblockHeader("041f3d2ceed........");
+Interface
Result getBlock(int height)
Instructions
Gets a block by block height
Result.data
Block
| parameter | type | required or not | note |
|---|---|---|---|
| height | int | required | block height |
Return
Result object in the following formats:{
+ "success": true,
+ "data": {
+ "hash": "00209bbcd98110b57f1ecd66c9d94d1a2381e6c03c3b9aa77db25b6eb5955bb658d3",
+ "preHash": "00201c0fa53c98595c7f9ba817fca6367aa2da1c1e480f801766b7a4a16b39c54b67",
+ "merkleHash": "00200c2dfa0560229ef728cd6bdc858334ef4072d8e25c3b0831c8366f4d4cb0c168",
+ "time": 1529323210000,
+ "height": 1884,
+ "txCount": 1884,
+ "packingAddress": "2CWsZb9w8XXTE58TUhBGczxf4U6NULS",
+ "scriptSig": "2102e18d02154e0f68900898efea7ba72d6d14e37d7d173a62146df2871f40996d73004730450221009d1015b7cab19ac8099245390ae41ca14da9f47d5c28b3b7780a53bd8adcccd802202bf74bb764f9de248dfb892d98e9ff91bad25daa107cfdf4effd3fb1c266e5ae",
+ "roundIndex": 420416,
+ "consensusMemberCount": 5,
+ "roundStartTime": 1529323170000,
+ "packingIndexOfRound": 4,
+ "confirmCount": 33,
+ "reward": 100000,
+ "fee": 100000,
+ "size": 5,
+ "txList": [
+ {
+ "hash": "00202b9737b15bf7e4ebc74a58554e461fbed6fedf3e289c6ef41afa80d83f67babc",
+ "type": 1,
+ "time": 1529323210000,
+ "blockHeight": 1884,
+ "fee": 0,
+ "value": 0,
+ "remark": null,
+ "scriptSig": null,
+ "status": 0,
+ "confirmCount": 33,
+ "size": 54,
+ "inputs": [],
+ "outputs": [
+ {
+ "address": "2CWsZb9w8XXTE58TUhBGczxf4U6NULS",
+ "value": 100000,
+ "lockTime": 2884
+ }
+ ]
+ },
+ {
+ "hash": "00203a169b42e5e142e20b273ac925e55f773b5a38c5f5c907efdbc43abb7d7a67b2",
+ "type": 2,
+ "time": 1529323198461,
+ "blockHeight": 1884,
+ "fee": 100000,
+ "value": 0,
+ "remark": "transfer",
+ "scriptSig": "21036dd27c9fa786a1e83df204e9b31ddc24745c378f1f6b42731d07f05347167c0000473045022100ff3372711d78eb554be331aa40cd7af246641ecd3bc06f2fdca7faefb25f74e50220743a2f2d9d01b5a77a878349b996cbe4953af5d1a946519a5ce4d1129cf99848",
+ "status": 0,
+ "confirmCount": 33,
+ "size": 255,
+ "inputs": [
+ {
+ "fromHash": "0020ab020707282932e6ec701f0b64e22e937fdd03ce9b37aab498aed2e00b6fa8e7",
+ "fromIndex": 0,
+ "address": null,
+ "value": 9999899000000
+ }
+ ],
+ "outputs": [
+ {
+ "address": "2CiVA3n1VoNQobAax4d7qNEBZAfehLN",
+ "value": 99900000000,
+ "lockTime": 0
+ },
+ {
+ "address": "2ChDcC1nvki521xXhYAUzYXt4RLNULS",
+ "value": 9899998900000,
+ "lockTime": 0
+ }
+ ]
+ },
+ {
+ "hash": "002040370fcb2ad080abdcd2d91f952826c8f6e55bda7231c1c15f25d9d74dc8ad7f",
+ "type": 7,
+ "time": 1529323210000,
+ "blockHeight": 1884,
+ "fee": 0,
+ "value": 0,
+ "remark": null,
+ "scriptSig": null,
+ "status": 0,
+ "confirmCount": 33,
+ "size": 38,
+ "inputs": [],
+ "outputs": []
+ }
+ ]
+ }
+}
+e.g Sample Code
getBlock(10);
+Interface
Result getBlock(String hash)
Instructions
Gets a block by block hash
Result.data
Block
| parameter | type | required or not | note |
|---|---|---|---|
| hash | String | required | block hash |
Return
-Return Result object in the following format:
{
+ "success": true,
+ "data": {
+ "hash": "00209bbcd98110b57f1ecd66c9d94d1a2381e6c03c3b9aa77db25b6eb5955bb658d3",
+ "preHash": "00201c0fa53c98595c7f9ba817fca6367aa2da1c1e480f801766b7a4a16b39c54b67",
+ "merkleHash": "00200c2dfa0560229ef728cd6bdc858334ef4072d8e25c3b0831c8366f4d4cb0c168",
+ "time": 1529323210000,
+ "height": 1884,
+ "txCount": 1884,
+ "packingAddress": "2CWsZb9w8XXTE58TUhBGczxf4U6NULS",
+ "scriptSig": "2102e18d02154e0f68900898efea7ba72d6d14e37d7d173a62146df2871f40996d73004730450221009d1015b7cab19ac8099245390ae41ca14da9f47d5c28b3b7780a53bd8adcccd802202bf74bb764f9de248dfb892d98e9ff91bad25daa107cfdf4effd3fb1c266e5ae",
+ "roundIndex": 420416,
+ "consensusMemberCount": 5,
+ "roundStartTime": 1529323170000,
+ "packingIndexOfRound": 4,
+ "confirmCount": 33,
+ "reward": 100000,
+ "fee": 100000,
+ "size": 5,
+ "txList": [
+ {
+ "hash": "00202b9737b15bf7e4ebc74a58554e461fbed6fedf3e289c6ef41afa80d83f67babc",
+ "type": 1,
+ "time": 1529323210000,
+ "blockHeight": 1884,
+ "fee": 0,
+ "value": 0,
+ "remark": null,
+ "scriptSig": null,
+ "status": 0,
+ "confirmCount": 33,
+ "size": 54,
+ "inputs": [],
+ "outputs": [
+ {
+ "address": "2CWsZb9w8XXTE58TUhBGczxf4U6NULS",
+ "value": 100000,
+ "lockTime": 2884
+ }
+ ]
+ },
+ {
+ "hash": "00203a169b42e5e142e20b273ac925e55f773b5a38c5f5c907efdbc43abb7d7a67b2",
+ "type": 2,
+ "time": 1529323198461,
+ "blockHeight": 1884,
+ "fee": 100000,
+ "value": 0,
+ "remark": "transfer",
+ "scriptSig": "21036dd27c9fa786a1e83df204e9b31ddc24745c378f1f6b42731d07f05347167c0000473045022100ff3372711d78eb554be331aa40cd7af246641ecd3bc06f2fdca7faefb25f74e50220743a2f2d9d01b5a77a878349b996cbe4953af5d1a946519a5ce4d1129cf99848",
+ "status": 0,
+ "confirmCount": 33,
+ "size": 255,
+ "inputs": [
+ {
+ "fromHash": "0020ab020707282932e6ec701f0b64e22e937fdd03ce9b37aab498aed2e00b6fa8e7",
+ "fromIndex": 0,
+ "address": null,
+ "value": 9999899000000
+ }
+ ],
+ "outputs": [
+ {
+ "address": "2CiVA3n1VoNQobAax4d7qNEBZAfehLN",
+ "value": 99900000000,
+ "lockTime": 0
+ },
+ {
+ "address": "2ChDcC1nvki521xXhYAUzYXt4RLNULS",
+ "value": 9899998900000,
+ "lockTime": 0
+ }
+ ]
+ },
+ {
+ "hash": "002040370fcb2ad080abdcd2d91f952826c8f6e55bda7231c1c15f25d9d74dc8ad7f",
+ "type": 7,
+ "time": 1529323210000,
+ "blockHeight": 1884,
+ "fee": 0,
+ "value": 0,
+ "remark": null,
+ "scriptSig": null,
+ "status": 0,
+ "confirmCount": 33,
+ "size": 38,
+ "inputs": [],
+ "outputs": []
+ }
+ ]
+ }
+}
+e.g Sample Code
getBlock("041f3d2ceed........");
+Interface
Result getNewestBlockHash()
Instrucntions
Gets the latest block header
Result.data
BlockHeader
Return
Result object in the following format:{
+ "success": true,
+ "data": {
+ "hash": "002078656b6e32f4f1e9e881e7b6c4c5de036ae81ec5bf78861bde9480f5ff3a1b33",
+ "preHash": "0020ee5d28fde669adb0ad16f3ed426f1ee8df40560bed0ab30bb99cbf95df276d64",
+ "merkleHash": "0020cc37658e2d110c1d42f64c7fd3dcb56d9653d4edc4d3a8406cb263a41f9f5488",
+ "time": 1529299160000,
+ "height": 4,
+ "txCount": 4,
+ "packingAddress": "2CWsZb9w8XXTE58TUhBGczxf4U6NULS",
+ "scriptSig": "2102e18d02154e0f68900898efea7ba72d6d14e37d7d173a62146df2871f40996d7300473045022100d4d92a9518ffd855441c7712f4b31bd003291dc108fa2b455fe26d51e54625f102202ae8375bd69bf1928f9967edac82619ff78f30550c17797cc489d5effd3202bf",
+ "roundIndex": 419517,
+ "consensusMemberCount": 1,
+ "roundStartTime": 1529299150000,
+ "packingIndexOfRound": 1,
+ "confirmCount": 1909,
+ "reward": 0,
+ "fee": 0,
+ "size": 1
+ }
+}
+
+e.g Sample Code
getNewestBlockHash();
+Interface
Result getNewestBlockHight()
Instructions
Gets the height of the latest block
Result.data: height (Long)
Return
-Return Result object in the following format:
{
+ "success": true,
+ "data": {
+ "value": 5210
+ }
+}}
+
+e.g Sample Code
getNewestBlockHight();
+Interface
Result getNewestBlockHash()
Instructions
Gets the block Hash of the latest block
Result.data: Hash (String)
Return
Result object in the following format:{
+ "success": true,
+ "data": {
+ "value": "0020a2e1c99951184700927472c431a5a65847c7974cac0bbb97b242c7adf56ad27b"
+ }
+}}
+
+e.g Sample Code
getNewestBlockHash();
+Interface
Result createAgentTransaction(AgentInfo agentInfo, List<Input> inputs, Na fee)
Instructions
Assembles transaction for creating node offline
Result.data
String: serialized transaction string in hexadecimal
| parameter | type | required or not | note |
|---|---|---|---|
| agentInfo | Object | required | the information about the node to be created |
| inputs | List | required | input information |
| fee | Object | required | transaction fee |
e.g Sample Code
// the inputs for assembly transaction, the attribute of the input in the example is mandatory.
+List<Input> inputs = new ArrayList<>();
+Input input = new Input();
+input.setFromHash("0020b0a75a26caad17b4ea6cec7f059ac0e426d71696a6096f75bb2e9f30c11c60d6");
+input.setFromIndex(1);
+input.setAddress("Nse5x9foSzFjuwkwZLSvSjAHHLVf3MKJ");
+input.setValue(999998760000000L);
+inputs.add(input);
+
+// the information about the node to be created, the attribute of AgentInfo in the example is mandatory.
+AgentInfo info = new AgentInfo();
+info.setAgentAddress("Nse5x9foSzFjuwkwZLSvSjAHHLVf3MKJ"); // the agent address of the consensus node
+info.setPackingAddress("NsdwUo8XU52DtB9Zqjo2YkuLBW8VhGaQ"); // the address of the node actually packing block
+info.setDeposit(200000 * 100000000L);// deposit for creating a node, not less than 20000NULS and not more than 200000NULS
+info.setCommissionRate(10.0); // commission ratio ranging from 1 to 100
+
+//fee for creating a node
+Na fee = Na.valueOf(1000000L);
+
+Result result = NulsSDKTool.createAgentTransaction(info, inputs, fee);
+Map<String, Object> map = (Map<String, Object>) result.getData();
+String txHex = (String) map.get("value");
+** Calculation of transaction fee **: unit price of the fee* transaction size
** unit price of the fee (min)**:1000000 NA/1KB
Calculation of transaction size:(288 + 50 * inputs.length)/1024 +210 is the fixed length of the basic information, 50 is the length of a single input, 38 is the length of a single output, and remark is an optional field, whose byte length is calculated according to the UTF-8 character encoding when needed. The transaction size is in KB, and its maximum value is 300 KB. The part less than 1 KB is calculated as 1 KB. +When the block-forging node verifies each transaction, the difference between the input and the output is regarded as the fee paid by the user when the transaction is sent, and the minimum value of the fee is calculated based on the transaction size. If the user's fee is less than the minimum value, it will be regarded as an invalid transaction and will not be packaged. Therefore, when creating a transaction, you should calculate the fee with care to avoid transaction failure.
Interface
Result createDepositTransaction(DepositInfo depositInfo, List<Input> inputs, Na fee)
Instructions
Assembles an agent consensus transaction offline.
Result.data
String: serialized transaction data in hexadecimal
| parameter | type | required or not | note |
|---|---|---|---|
| depositInfo | Object | required | the information about the node to be created |
| inputs | List | required | input information |
| fee | Object | required | transaction fee |
e.g Sample Code
// the inputs for assembly transaction, the attribute of the input in the example is mandatory.
+List<Input> inputs = new ArrayList<>();
+Input input = new Input();
+input.setFromHash("0020b0a75a26caad17b4ea6cec7f059ac0e426d71696a6096f75bb2e9f30c11c60d6");
+input.setFromIndex(1);
+input.setAddress("Nse5x9foSzFjuwkwZLSvSjAHHLVf3MKJ");
+input.setValue(999998760000000L);
+inputs.add(input);
+
+// the information about the agent consensus node, the attribute of AgentInfo in the example is mandatory.
+DepositInfo info = new DepositInfo();
+info.setAddress("Nse5x9foSzFjuwkwZLSvSjAHHLVf3MKJ"); //address of the agent consensus node
+info.setDeposit(300000 * 100000000L);// the agent token number ranging from 2000NULS to 500000NULS
+info.setAgentHash("0020a467827d5f06feb3e78b4603eb03677711219cb5232d145b3e9d4ab48a3eb366");// the id of the transaction for creating consensus node
+
+//fee for creating a node
+Na fee = Na.valueOf(1000000L);
+
+Result result = NulsSDKTool.createDepositTransaction(info, inputs, fee);
+Map<String, Object> map = (Map<String, Object>) result.getData();
+String txHex = (String) map.get("value");
+** Calculation of fee for creating an agent transaction**: unit price of the fee* transaction size
** unit price of the fee (min)**:1000000 NA/1KB
Calculation of transaction size:(288 + 50 * inputs.length)/1024 +210 is the fixed length of the basic information, 50 is the length of a single input, 38 is the length of a single output, and remark is an optional field, whose byte length is calculated according to the UTF-8 character encoding when needed. The transaction size is in KB, and its maximum value is 300 KB. The part less than 1 KB is calculated as 1 KB. +When the block-forging node verifies each transaction, the difference between the input and the output is regarded as the fee paid by the user when the transaction is sent, and the minimum value of the fee is calculated based on the transaction size. If the user's fee is less than the minimum value, it will be regarded as an invalid transaction and will not be packaged. Therefore, when creating a transaction, you should calculate the fee with care to avoid transaction failure.
Interface
Result createCancelDepositTransaction(Output output)
Instructions
Assembles a transaction for canceling agent consensus offline
Result.data
String: serialized transaction string in hexadecimal
| parameter | type | required or not | note |
|---|---|---|---|
| output | Object | required | the output locked when participating in the consensus |
e.g Sample Code
// after the transaction for participating in agent consensus is packaged, there is an output record of lockTime = -1, which is the agent amount locked after the user delegates the consensus.
+/ / use the output as a parameter to generate an transaction for canceling agent consensus
+Output output = new Output();
+output.setTxHash("0020b0a75a26caad17b4ea6cec7f059ac0e426d71696a6096f75bb2e9f30c11c60d6");
+output.setIndex(0);
+output.setAddress("Nse5x9foSzFjuwkwZLSvSjAHHLVf3MKJ");
+output.setValue(20000000000000L);
+output.setLockTime(-1);
+
+Result result = NulsSDKTool.createCancelDepositTransaction(output);
+Map<String, Object> map = (Map<String, Object>) result.getData();
+String txHex = (String) map.get("value");
+Interface
Result createStopAgentTransaction(Output output)
Instructions
Assembles a transaction for stopping consensus node offline
Result.data
String: serialized transaction string in hexadecimal
| parameter | type | required or not | note |
|---|---|---|---|
| output | Object | required | the output locked when creating a node |
e.g Sample Code
// after the transaction for creating a node is packaged, there is an output record of lockTime = -1, which is the deposit amount locked after the user create a node.
+/ / use the output as a parameter to generate a transaction for canceling agent consensus
+Output output = new Output();
+output.setTxHash("0020b0a75a26caad17b4ea6cec7f059ac0e426d71696a6096f75bb2e9f30c11c60d6");
+output.setIndex(0);
+output.setValue(20000000000000L);
+output.setAddress("Nse5x9foSzFjuwkwZLSvSjAHHLVf3MKJ");
+output.setLockTime(-1);
+
+Result result = NulsSDKTool.createStopAgentTransaction(output);
+Map<String, Object> map = (Map<String, Object>) result.getData();
+String txHex = (String) map.get("value");
+Interface
Result getDeposits(String address, int pageNumber, int pageSize)
Instructions
Gets a list of agent consensus by agent address
Result.data List: a list of agent consensus
| parameter | type | required or not | note |
|---|---|---|---|
| address | String | required | agent address |
| pageNumber | int | required | page number |
| pageSize | int | required | record size displayed per page ranging from 1 to 100< |
Return
Result object in the following format:{
+ "success":true,
+ "data":{
+ "pageNumber":1,
+ "pageSize":10,
+ "total":1,
+ "pages":1,
+ "list":[
+ {
+ "deposit":20000010000000,
+ "agentHash":"00207654b3371e9c99295a4b3d0371a6cfec48ee31684825dabc04dc5ea314da0a0c",
+ "address":"NsdyD94pXWpxZudbtJ4zpkBHhh8XmBQA",
+ "txHash":"002029411a2e6797e2d3bec54c48008f73275c8208a240b4835be534a137452bc29e",
+ "blockHeight":98,
+ "agentAddress":"NsdyD94pXWpxZudbtJ4zpkBHhh8XmBQA"
+ }
+ ]
+ }
+}
+e.g Sample Code
Result result = NulsSDKTool.getDeposits(address, 1, 10);
+{
+"success": true,// interface executes correctly
+"data": data
+}
+{ // indicate the normal access to the interface, and the business service returns true
+ "success": true,// interface executes correctly
+ "data": {
+ "value":true // the result returned by interface business function
+ }
+}
+{
+ "success": true, // interface executes correctly
+ "data":{
+ "value": false // the result returned by interface business function
+ }
+}
+{ // indicate an error
+ "success": false,
+ "data":{
+ "code": "ACT005",
+ "msg": "xxxxxx...."
+ }
+}
+{
+ "success": true,
+ //data为List<account>
+ "data": {
+ "list":[
+ {
+ "address": "2CacFwqMwcJiGNNBwiwV7bCL7bjwNBr",
+ "alias": null,
+ "pubKey": "030d4e752b5aa5d784f19a1fcc73b02afb6f756752fd00ebc2fcaabc8d0979c4f0",
+ "extend": null,
+ "createTime": 1529041525794,
+ "encrypted": false,
+ "priKey": "00e4bfd347351ea899b5f0ae2c0a3e7a6951b202eaf72432d1a63a2dc85c59c82a",
+ "encryptedPriKey": ""
+ }
+ ]
+ }
+}
+{
+ "address": String, account address
+ "alias": String, account alias
+ "pubKey": String, public key
+ "extend": String, extension
+ "createTime": Long, create time
+ "encrypted": boolean, encrypted or not
+ "priKey": String, private key(not null only if a password-less offline account is created)
+ "encryptedPriKey": String, encrypted private key(not null only if an offline account with password is created)
+}
+ {
+ "fromHash": String, txHash of the output
+ "fromIndex": Integer, outIndexof the output
+ "address": String, transfer-in address
+ "value": Long, transfer-in amount
+ "lockTime": Long, lock time
+}
+ {
+ "txHash": String, transaction hash
+ "index": Integer, index
+ "address": String, address
+ "value": Long, amount
+ "lockTime": Long, lock time
+ "status": Integer status 0:usable(usable), 1:timeLock(time lock), 2:consensusLock(consensus lock), 3:spent(spent)
+}
+{
+ "hash": String, transaction hash
+ "type": Integer, transaction type
+ "time": Long, transaction initiation time
+ "blockHeight": Long, block height
+ "fee": Long, transaction fee
+ "value": Long, transaction amount
+ "remark": String, remarks
+ "scriptSig": String, signature
+ "status": Integer, transaction status 0:unConfirm(to be confirmed), 1:confirm(confirmed)
+ "confirmCount": Long, confirmation count
+ "size": int, size
+ "inputs": [
+ {
+"fromHash": String, txHash of the output
+ "fromIndex": Integer, outIndexof the output
+ "address": String, transfer-in address
+ "value": Long, transfer-in amount
+
+ }
+ ],
+ "outputs": [
+ {
+ "txHash": String, transaction hash
+ "index": Integer, index
+ "address": String, address
+ "value": Long, amount
+ "lockTime": Long, lock time
+ "status": Integer status 0:usable(usable), 1:timeLock(time lock), 2:consensusLock(consensus lock), 3:spent(spent)
+ }
+ ]
+}
+{
+ "balance": long, balance
+ "usable": long, available balance
+ “locked": long, locked balance
+}
+{
+ "hash": String, transaction hash
+ "preHash": String, hash value of the previous block
+ "merkleHash": String, merkle hash
+ "time": Long, block generation time
+ "height": Long, block height
+ "txCount": Long, count of transactions packaged by the block
+ "packingAddress": String, packing address
+ "scriptSig": String, signature
+ "roundIndex": Long, consensus round
+ "consensusMemberCount": Integer, count of members participating in the consensus
+ "roundStartTime": Long, the start time of the current consensus round
+ "packingIndexOfRound": Integer, the packing index of the current round
+ "confirmCount": Long, confirmation count
+ "reward": Long, consensus reward
+ "fee": Long, packing fee obtained
+ "size": int, size
+}
+{
+ "hash": String, transaction hash
+ "preHash": String, hash value of the previous block
+ "merkleHash": String, merkle hash
+ "time": Long, block generation time
+ "height": Long, block height
+ "txCount": Long, count of transactions packaged by the block
+ "packingAddress": String, packing address
+ "scriptSig": String, signature
+ "roundIndex": Long, consensus round
+ "consensusMemberCount": Integer, count of members participating in the consensus
+ "roundStartTime": Long, the start time of the current consensus round
+ "packingIndexOfRound": Integer, the packing index of the current round
+ "confirmCount": Long, confirmation count
+ "reward": Long, consensus reward
+ "fee": Long, packing fee obtained
+ "size": int, size
+ "txList": [
+ {
+ "hash": String, transaction hash
+ "type": Integer, transaction type
+ "time": Long, transaction initiation time
+ "blockHeight": Long, block time
+ "fee": Long, transaction fee
+ "value": Long, transaction amount
+ "remark": String, remarks
+ "scriptSig": String, signature
+ "status": Integer, transaction status 0:unConfirm(to be confirmed), 1:confirm(confirmed)
+ "confirmCount": Long, confirmation count
+ "size": int, size
+ "inputs": [inputs
+ {
+ "fromHash": String, txHash of the output
+ "fromIndex": Integer, outIndexof the output
+ "address": String, transfer-in address
+ "value": Long transfer-in amount
+ }
+ ],
+ "outputs": [ outputs
+ {
+ "address": String, address
+ "value": Long, amount
+ "lockTime": Long, lock time
+ }
+ ]
+ }
+ ]
+}
++ ← + + Wallet adds a random seed + + Linux CLI Manual + + → +
Background:Since the NULS Main-Net uses the UTXO model, the transaction size is also used as one of the charging standards.
In the main-net, there are now three more types of transactions: creating a smart contract, invoking a smart contract, deleting a smart contract
The difference between those three transactions and other transactions such as transfer is that the execution of smart contracts will be added. So, execution of smart contracts will also be applied to the charging standards.
public static final int COMPARISON = 1 ; //Compare bytecode
+public static final int CONSTANT = 1 ; //Simple numeric type bytecode
+public static final int LDC = 1 ; //Numeric constant, string constant (length * LDC)
+public static final int CONTROL = .5 ; //Control bytecode
+public static final int TABLESWITCH = 2 ; //Switch bytecode (size * TABLESWITCH)
+public static final int LOOKUPSWITCH = 2 ; //Switch bytecode (size * LOOKUPSWITCH)
+public static final int CONVERSION = 1 ; //Value conversion
+public static final int EXTENDED = 1 ; //Null determine
+public static final int MULTIANEWARRAY = 1 ; //Multidimensional Array (size * MULTIANEWARRAY)
+public static final int LOAD = 1 ; / /Send the local variable to the top of the stack
+public static final int ARRAYLOAD = 5 ; / /Send an item of the array to the top of the stack
+public static final int MATH = 1 ; //Mathematical operations and shift operations
+public static final int REFERENCE = 10 ; //Object related operations
+public static final int NEWARRAY = 1 ; //One-dimensional array (size * NEWARRAY)
+public static final int STACK = 2 ; //Stack operation
+public static final int STORE = 1 ; // Save the value in the top of the stack to a local variable
+public static final int ARRAYSTORE = 5; //Save the value of the stack to an array
+public static final int TRANSFER = 1000 ; //Transfer transaction
+
+The first part is the transaction fee based on the transaction size, calculated according to the byte size -> 0.001NULS/KB, which is 0.001 NULS per 1000 bytes. If the transaction size is less than 1000 bytes, the transaction fee is set as 0.001 NULS.
The second part is the ‘Gas*Price’ consumed by executing the contract. The ‘Price’ is the unit cost, which means how much ‘Na’ there is for each Gas. ‘Na’ is the smallest unit of NULS, and 1 NULS = 100 million Na.
For example, if executing a contract consumes 20,000 Gas and the set Price is 20 Na/Gas, then the Na consumed this time would be 20,000 * 20 = 400,000 Na, which is 0.004 NULS.
Still using the previous example, if the GasLimit set for the contract is 30,000 Gas and executing the contract consumes 20,000 Gas, then 10,000 Gas will be left. The 10,000 Gas has: 10,000 * 20 = 200,000 Na, which is 0.002 NULS. This will be returned to the contract invoker in the CoinBase transaction (consensus reward) of the current packing block.
To start the contract transaction, the contract invoker pays the first, second and third part. In practical, the third part will be returned to the contract invoker in the CoinBase transaction (consensus reward) of the current packing block.
Precondition:This part of the cost is reflected in the CoinBase transaction (consensus reward) of the block.
The block packer receives the first and second parts of the service charge, and the contract invoker receives the third part.




Input Project name, click finish

Smart contract code compilation refers to [developer document] (http://dev.nuls.io/contract/)

Click NULS plugin on the right, and call NULS plugin interface

Plugin automatically generates a node 127.0.0.1:8001, and developer adds a node to deploy the contract. +Recommendation: Start the local wallet, and add the wallet address as the node address.
Click + on the top left corner of panel, and select Add Node.

Input Node address and clock OK

Click + on the top left corner of panel, and select Add Account. Input Account address and click OK.

Click the second button on the top left corner of plugin to directly package the current Project. Two output forms after packaging: Jar package and Hex code

Click [copy code] to copy the HEX code to the [deploy contract] interface of wallet to deploy contract (optional step).

Click the third button on the plugin panel top or [Next] at the button of current package interface to access contract deploying interface


On Deploy interface, select the node and account for deploying contract from pull-down list. JarFilePath default value is the package route of the previous step.

Parameters following JarFilePath are the parameters of the contract construction function.

Click [advanced] to set gas value and price value. Gas varies from 1 to 10000000. Recommend to set a greater gas value to avoid failing in deploying contract.

Click [Test Deploy] to conduct a trial deployment of contract. In case of a success, it gives prompt of Success.

If success, click [Deploy]. After confirmation of contract creation transaction, it feeds back details of transaction, indicating a success of contract deployment.

Review the deployed contract on the top of panel

Click the deployed contract to review all method of this contract

Visit the NULS project on github: https://github.com/nuls-io/nuls
Option 1: downloading the source code directly
After accessing the github, click the "Clone or download" button and select Download ZIP to download the source-code package.
+ Option 2: running the git command to clone the NULS repository
` git clone https://github.com/nuls-io/nuls.git`
+ Option 3: (recommended): cloning the NULS repository with development tools such as IntelliJ IDEA.
Operating Systems: macOS, Windows
+
+Building Tools: maven
+
+Development Tools: IntelliJ IDEA
+
+Development Language: Java (JDK1.8)
+ Since blockchain is a decentralized network composed of multiple nodes, it makes no sense to launch a node with NULS source code alone, and it is also not feasible. This tutorial assumes an existing custom test-net running with NULS source code, and the source code other than the network parameters is not modified when building the network. How can we run the NULS source code and join the network
+ 2. Run IntelliJ IDEA
+ - If you download the source code package, extract it and import the NULS project via IntelliJ IDEA
+ - If you download the source code by running git command to clone the NULS repository, import the NULS project via IntelliJ IDEA.
+ - Clone the NULS repository via IntelliJ IDEA’s Git plugin.
+ 3. Configure network environment parameters consistent with the existing network.
+ - Open the module.ini configuration file in the client-module project
+ - It is recommended to replace the module.ini file with that of other nodes in the known custom test-net to ensure the consistency of the network environment parameters.
+ 4. Run the NULS boot class Bootstrap.java in the client-module project, located in io.nuls.client package.
+ 5. The NULS wallet interface will be opened during start-up process and the block height of the custom test-net will be synchronized, indicating that the startup is successful.
+ Connect Main-net + + → +
Preparations for deployment and invocation of smart contracts
Preparations for the development of smart contract code
[Downloading JDK8] +(https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) (Installation omitted)
[Downloading IntelliJ IDEA] (https://www.jetbrains.com/idea/download/) (Installation omitted)
[Downloading NULS smart contract plug-ins] +(https://nuls-usa-west.oss-us-west-1.aliyuncs.com/plugins/Docs%26plugin.zip)
[Installing the NULS smart contract plug-ins] (https://dev.nuls.io/zh-cn/contract/IdeaPlugin.html)
_Quickly compile and deploy a smart contract with the example _
+Import io.nuls.contract.sdk.Contract;
+Import io.nuls.contract.sdk.Msg;
+Import io.nuls.contract.sdk.annotation.Payable;
+Import io.nuls.contract.sdk.annotation.Required;
+Import io.nuls.contract.sdk.annotation.View;
+
+Import java.math.BigDecimal;
+Import java.math.BigInteger;
+
+Public class SimpleContract implements Contract {
+
+ Private String sayContent;
+
+ @Override
+ @Payable
+ Public void _payable() {
+ // override this method and mark the @Payable annotation. The smart contract can receive direct transfer of the NULS wallet assets
+ // you can do something else
+ // ...
+ }
+
+ Public String sayContent(@Required String content) {
+ this.sayContent = content;
+ Return "you want say " + content;
+ }
+
+ @Payable
+ Public String transferToContract() {
+ // mark the @Payable annotation. Smart contract can receive NULS when invoking this method
+ BigInteger value = Msg.value();
+ BigDecimal nuls = new BigDecimal(value).movePointLeft(8);
+ // you can do something else
+ // ...
+
+ Return "I received your transfer amount: " + nuls.toPlainString();
+ }
+
+ @View
+ Public String sayWhat() {
+ If(sayContent != null) {
+ Return "you want say " + sayContent;
+ }
+ Return "you want say nothing.";
+ }
+}
+
+[Smart contract repository collected by NULS officials] (https://github.com/nuls-io/contracts)
[Community member Angelillou's smart contract - Partnership income distribution smart contract] (https://github.com/amalcaraz/nuls-partnership-smartcontract)
[Community member Angelillou's smart contract - Lottery factory smart contract for Nuls blockchain)
[Community member Naveen's Smart Contracts - Contract to write reviews for any product] (https://github.com/naveen7252/ProductReviewContract)
[How to deploy and invoke the wallet smart contract] +(https://dev.nuls.io/zh-cn/contract/smartContract.html)
[Smart contract specifications and syntax] (https://dev.nuls.io/zh-cn/contract/index.html)
+ ← + + RPC-TOOL design document + + Development Manual + + → +
A standard interface for tokens.
The following standard allows for the implementation of a standard API for tokens within smart contracts. +This standard provides basic functionality to transfer tokens, as well as allow tokens to be approved so they can be spent by another on-chain third party.
A standard interface allows any tokens on Nuls to be re-used by other applications: from wallets to decentralized exchanges.
NOTE: Callers MUST handle false from return boolean. Callers MUST NOT assume that false is never returned!
Returns the name of the token - e.g. "MyToken".
@View
+public String name();
+Returns the symbol of the token. E.g. "MT".
@View
+public String symbol();
+Returns the number of decimals the token uses - e.g. 8, means to divide the token amount by 100000000 to get its user representation.
@View
+public int decimals();
+Returns the total token supply.
@View
+public BigInteger totalSupply();
+Returns the account balance of another account with address owner.
@View
+public BigInteger balanceOf(@Required Address owner);
+Transfers value amount of tokens to address to, and MUST fire the TransferEvent event.
+The function SHOULD revert if the from account balance does not have enough tokens to spend.
A token contract which creates new tokens SHOULD trigger a Transfer event with the from address set to null when tokens are created.
Note Transfers of 0 values MUST be treated as normal transfers and fire the TransferEvent event.
public boolean transfer(@Required Address to, @Required BigInteger value);
+Transfers value amount of tokens from address from to address to, and MUST fire the TransferEvent event.
The transferFrom method is used for a withdraw workflow, allowing contracts to transfer tokens on your behalf.
+This can be used for example to allow a contract to transfer tokens on your behalf and/or to charge fees in sub-currencies.
+The function SHOULD revert unless the from account has deliberately authorized the sender of the message via some mechanism, such as calling approve(@Required Address spender, @Required BigInteger value).
Note Transfers of 0 values MUST be treated as normal transfers and fire the TransferEvent event.
public boolean transferFrom(@Required Address from, @Required Address to, @Required BigInteger value);
+Allows spender to withdraw from your account multiple times, up to the value amount. If this function is called again it overwrites the current allowance with value.
public boolean approve(@Required Address spender, @Required BigInteger value);
+Returns the amount which spender is still allowed to withdraw from owner.
@View
+public BigInteger allowance(@Required Address owner, @Required Address spender);
+MUST trigger when tokens are transferred, including zero value transfers.
A token contract which creates new tokens SHOULD trigger a Transfer event with the from address set to null when tokens are created.
public TransferEvent(Address from, @Required Address to, @Required BigInteger value)
+MUST trigger on any successful call to approve(@Required Address spender, @Required BigInteger value).
public ApprovalEvent(@Required Address owner, @Required Address spender, @Required BigInteger value)
++ ← + + IDEA Plugin + + Service Charge + + → +
NULS was created to make blockchain very simple. So, in September 2017, the core team defined the modular architecture, which was designed to make it easier for developers to write, and for users to utilize. NULS 1.0 achieves the modular effect at the coding paradigm level, but this design doesn’t solve the problem of tight coupling between modules. Developers who want to use a module or participate in the development of a module would need to understand the design of other modules associated with it and can only use a specific language for the development of their module. This is not friendly to the NULS vision for the technical community which anticipates intense, active participation in the design and development of NULS architecture, as well as the user’s supply of simple and low-cost modules.
Since its conception in 2017, NULS has been committed to establishing a community-driven open-source project. This community-driven route for development is what stimulates continuous innovation and distinguishes blockchain projects from other commercial projects. Continuous iteration and innovation is both inherent and inevitable in open source projects, and is also a novel and valuable feature of blockchain. In order to allow ease of participation to the open-source and technical community for developing on NULS, and to establish ease of use provided by the “Module Repository”, which is an important part of the revolutionary product “Chain Factory”, the following difficulties had to be overcome:
Loosened coupling and removal of dependencies between modules;
Modules must be easier to extend, modify and replace. Each module must be simple and basic; and modules should not encompass the overall complexity of blockchain applications;
Complete elimination of programming language limitations.
The core team introduces an innovative microservice concept in the infrastructure design of blockchain, which designs software applications as service suites that can be deployed independently. This concept introduces the most advanced ideas in the 1.0 architecture and transforms them with enhanced flexibility into a new modular design, making modules as flexible as programs that can start independently. This new modular architecture enhanced with microservice suites, that have no programming language limitations, is called NULS 2.0. Modules in this architecture enjoy even more decoupling, while the feature of multi-language development greatly improves the contribution of code and the convenience of users. At the same time, it is even easier to extend, since the enhanced design of modules supports distributed deployment and hot module replacement. Both Chain Factory and Cross-Chain Modules are being developed in coordination with this architecture.
During the design of NULS 2.0, the NULS team and technical community also established the NULS CCC (Code Craft Council), to provide the first stage of autonomy for the technical community. Around this time, and as a matter of coincidence, Berzeck, a member of CCC, had been considering the idea of refactoring the NULS architecture with microservices, a problem which he worked on in former projects of considerable size. After reading the design proposed by Berzeck, the core team was very pleased to find that his version encapsulated an even more complete micro-service design, which coincided with the more flexible blockchain infrastructure the team was working to achieve. Berzeck’s design is divided into a three-layer system of architecture:
The first layer is the micro-service infrastructure layer.
The second layer is the basic service layer of the blockchain.
The third layer is the DApp application layer.
This design refactors NULS from the perspective of the blockchain, to a higher level of cognition that will bring NULS into the new era of NULS IS EVERYTHING. The core team has decided to refactor the NULS 2.0 architecture based on this new architectural design. The result of this decision inevitably means that with certainty NULS will become a truly powerful, one-of-a-kind and supremely flexible platform.
+
This architecture allows for the development of more advanced applications built on the second layer (such as the distributed system of exchanges, the data service system, and systems similar to DiDi, all of which can be built on the second layer). Another significant benefit of the architecture is that the NULS system will not only build out multiple chains and multiple DApps, but also other large and medium-sized non-blockchain commercial systems, such as Internet, mobile Internet, Internet of Things, car networking — the possibilities are endless!
The new design empowers NULS to be more than just the underlying infrastructure of the blockchain and instead transforms it into a distributed system infrastructure that seamlessly integrates with the blockchain system. It will be a platform for seamless communication between different systems (blockchain and other systems), which will enable businesses built around NULS to flourish more quickly while greatly reducing development costs. This overall optimization gives NULS innate, and undisputed competitive advantages.
+
The NULS2.0 microservice architecture evolved over time. For more information on how it came about, read the documentationNULS2.0:Philosophy of Design.The documentation details the NULS2.0 evolutionary path。
+ Quick Start + + → +
NULS was created to make blockchain very simple. So, in September 2017, the core team defined the modular architecture, which was designed to make it easier for developers to write, and for users to utilize. NULS 1.0 achieves the modular effect at the coding paradigm level, but this design doesn’t solve the problem of tight coupling between modules. Developers who want to use a module or participate in the development of a module would need to understand the design of other modules associated with it and can only use a specific language for the development of their module. This is not friendly to the NULS vision for the technical community which anticipates intense, active participation in the design and development of NULS architecture, as well as the user’s supply of simple and low-cost modules.
Since its conception in 2017, NULS has been committed to establishing a community-driven open-source project. This community-driven route for development is what stimulates continuous innovation and distinguishes blockchain projects from other commercial projects. Continuous iteration and innovation is both inherent and inevitable in open source projects, and is also a novel and valuable feature of blockchain. In order to allow ease of participation to the open-source and technical community for developing on NULS, and to establish ease of use provided by the “Module Repository”, which is an important part of the revolutionary product “Chain Factory”, the following difficulties had to be overcome:
Loosened coupling and removal of dependencies between modules;
Modules must be easier to extend, modify and replace. Each module must be simple and basic; and modules should not encompass the overall complexity of blockchain applications;
Complete elimination of programming language limitations.
The core team introduces an innovative microservice concept in the infrastructure design of blockchain, which designs software applications as service suites that can be deployed independently. This concept introduces the most advanced ideas in the 1.0 architecture and transforms them with enhanced flexibility into a new modular design, making modules as flexible as programs that can start independently. This new modular architecture enhanced with microservice suites, that have no programming language limitations, is called NULS 2.0. Modules in this architecture enjoy even more decoupling, while the feature of multi-language development greatly improves the contribution of code and the convenience of users. At the same time, it is even easier to extend, since the enhanced design of modules supports distributed deployment and hot module replacement. Both Chain Factory and Cross-Chain Modules are being developed in coordination with this architecture.
During the design of NULS 2.0, the NULS team and technical community also established the NULS CCC (Code Craft Council), to provide the first stage of autonomy for the technical community. Around this time, and as a matter of coincidence, Berzeck, a member of CCC, had been considering the idea of refactoring the NULS architecture with microservices, a problem which he worked on in former projects of considerable size. After reading the design proposed by Berzeck, the core team was very pleased to find that his version encapsulated an even more complete micro-service design, which coincided with the more flexible blockchain infrastructure the team was working to achieve. Berzeck’s design is divided into a three-layer system of architecture:
The first layer is the micro-service infrastructure layer.
The second layer is the basic service layer of the blockchain.
The third layer is the DApp application layer.
This design refactors NULS from the perspective of the blockchain, to a higher level of cognition that will bring NULS into the new era of NULS IS EVERYTHING. The core team has decided to refactor the NULS 2.0 architecture based on this new architectural design. The result of this decision inevitably means that with certainty NULS will become a truly powerful, one-of-a-kind and supremely flexible platform.
+
This architecture allows for the development of more advanced applications built on the second layer (such as the distributed system of exchanges, the data service system, and systems similar to DiDi, all of which can be built on the second layer). Another significant benefit of the architecture is that the NULS system will not only build out multiple chains and multiple DApps, but also other large and medium-sized non-blockchain commercial systems, such as Internet, mobile Internet, Internet of Things, car networking — the possibilities are endless!
The new design empowers NULS to be more than just the underlying infrastructure of the blockchain and instead transforms it into a distributed system infrastructure that seamlessly integrates with the blockchain system. It will be a platform for seamless communication between different systems (blockchain and other systems), which will enable businesses built around NULS to flourish more quickly while greatly reducing development costs. This overall optimization gives NULS innate, and undisputed competitive advantages.
+
The NULS2.0 microservice architecture evolved over time. For more information on how it came about, read the documentationNULS2.0:Philosophy of Design.The documentation details the NULS2.0 evolutionary path。
[TOC]
The Account Module is a basic module that provides information about the various functions of the account.It mainly supports the functions of account generation, security and storage, and information acquisition. Other modules can use various functions of the account and obtain account information according to the interface provided by the account module. Users or other applications can be based on RPC. The interface makes the account more practical and personalized. The account is the basic module and the carrier of the user data.
Account generation
Create an account, import an account.
Account security and storage
Backup of account, setting account password, modifying account password, removing account.
Access to account information
Query singel account information, query multiple account information, query account address, query account alias.
Other usability and personalization features
Set account alias, set account remark, verify account encryption, sign, verify account address format, verify account password is correct, etc.

The account is the underlying module that is dependent on the ledger, consensus, transaction, kernel, event bus, and community governance modules.
1、Account module depends on the ledger module
The ledger module needs to handle local transactions and relies on account information.
+
+The account module needs to create an alias transaction, which requires the ledger module to pay the fee.
+
+Account balance inquiry, need to rely on ledger module.
+ 2、Account module depends on kernel module
Report module information and share data operations.
+3、Account module depends on network module
Receive and send data through a network module.
+4、Account module depends on event bus module
Create an account, delete an account,change a password event,send a message through the event bus module.
+The account module is not strongly dependent on the event bus module,because even if the event fails to send,it does not affect the normal business process.
+5、Consensus module depends on account module
Consensus requires account information for packaging blocks.
+6、Transaction management module depends on account module
The transaction management module needs to verify the transaction,relying on the address function in the account to verify whether the address is legal.
+7、Community Governance Module depends on account Module
Community governance requires account signature
+
1.API: Provides an interface layer externally, providing operations such as creating, backing up, and setting aliases for accounts.
2.Business logic layer: the function of defining accounts, account addresses, and aliases.
3.Data persistence layer: save account, alias data.
Function Description
Create a user's account, including the account's address, public key, private key creation, account information saved to the database, and create an account to notify other nodes through the event.
Process description

Create Address: Create a satellite chain standard account address
1.Generate a random public-private key pair
+2.Get chainId and account type
+3.Calculate hash160 based on public key
+4.Stitching byte arrays to form addresses
+4.1.If it is the NULS system address: address=type+hash160
+4.2、If non-NULS system address (bitcoin): address=original address length + original address
+5、Generate address string: address byte[] + check digit, then perform base58 calculation to generate string
+5.1.If it is the NULS system check digit: xor=XOR(addressType+pkh)
+5.2.If non-NULS system check digit: xor=XOR(length+address)
+6. base58 calculation generates the address string:
+ NULS system address: Base58 (type+hash160+xor)+Hex(chainId)
+ Non-NULS system address: Base58 (length+address+xor)+Hex(chainId)
+7.Encrypt the private key according to the password and delete the plaintext of the private key
+8.Store account information
+9.Add account to cache
+10.Send Create Account Event
+ac_createAccount interface
Interface Description
This interface creates one or more accounts.
Request example
{
+ "cmd":"ac_createAccount",
+ "minVersion":1.0,
+ "params":[
+ 1234,
+ 10,
+ "123456"
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID, indicating which chain the account belongs to |
| 1 | count | false | Integer | To create an account number, constraints:1-100. |
| 2 | password | false | String | Account initial password, Can be empty |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "list":["address","",""]
+ }
+}
+| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| list | jsonArray | Account address list |
Dependent service
Event Bus: Send Create Account Event
Function Description
Create a user's offline account, including the account's address, public key, private key creation, account information is not saved to the database
Process description

Create Address: Create a satellite chain standard account address
1.Generate a random public-private key pair
+2.Get chainId and account type
+3.Calculate hash160 based on public key
+4.Stitching byte arrays to form addresses
+4.1.If it is the NULS system address: address=type+hash160
+4.2、If non-NULS system address (bitcoin): address=original address length + original address
+5、Generate address string: address byte[] + check digit, then perform base58 calculation to generate string
+5.1.If it is the NULS system check digit: xor=XOR(addressType+pkh)
+5.2.If non-NULS system check digit: xor=XOR(length+address)
+6. base58 calculation generates the address string:
+ NULS system address: Base58 (type+hash160+xor)+Hex(chainId)
+ Non-NULS system address: Base58 (length+address+xor)+Hex(chainId)
+7.Encrypt the private key according to the password and delete the plaintext of the private key
+8.Return account information, not saved to the database
+ac_createOfflineAccount interface
Interface Description
This interface creates one or more offline accounts.
Request example
{
+ "cmd":"ac_createOfflineAccount",
+ "minVersion":1.0,
+ "params":[
+ 1234,
+ 10,
+ "123456"
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID, indicating which chain the account belongs to |
| 1 | count | false | Integer | To create an account number, constraints:1-100. |
| 2 | password | false | String | Account initial password, Can be empty |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "list":["address","",""]
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| list | jsonArray | Account address list |
Function Description
Create a multi-signature account, including the address of the account, the creation of the script, and save the multi-signed account information to the database.
Process description
1. Verify the signature public key list, and verify that the minimum number of signatures is correct.
+2. create a multi-signature script.
+3. create a multi-signature type account address according to the multi-sign script.
+4. save the multi-signature account.
+5. return multi-signed account information.
+ac_createMultiSigAccount interface
Interface Description
This interface creates a multi-signature account.
Request example
{
+ "cmd": "createMultiAccount",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ ["pubKey1","pubKey2"],
+ 2
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID, indicating which chain the account belongs to |
| 1 | pubKeys | true | jsonArray | Public key list that needs to be signed |
| 2 | minSigns | true | String | Minimum number of signatures, at least a few public key verifications are required |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "address":"",
+ "minSigns":"",
+ "pubKeys":[{
+ "pubKey":"",
+ "address":""
+ },{}
+ ]
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| address | String | Multi-sign account address |
| minSigns | Integer | Minimum signature number |
| pubKeys | jsonObj | Public key list |
| --pubKey | String | Public key |
| --address | String | Account address |
Dependent service
no
Function Description
Remove the user's local account, including deleting the address of the local account, and notifying the other nodes through the event
Process description

1. Verify that the account address format is correct.
+2. Verify that the account exists
+3. Verify that the account is encrypted. If the account is encrypted and the account is unlocked, you need to verify the password.
+3.1. Obtain an unencrypted private key according to the account's encrypted private key and password.
+3.2, get the public key according to the unencrypted private key
+3.3. Compare the decrypted public key with the queried public key
+4, delete the data
+4.1. Delete local account information
+4.2. Delete account cache information
+5. send remove account events
+ac_removeAccount interface
Interface Description
This interface is used to remove the account.
Request example
{
+ "cmd": "ac_removeAccount",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "AAax8wqxALqjyhrL8Wv1tQiqswAshAnX",
+ "123456"
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | address | true | Integer | Account address to delete |
| 2 | password | false | String | account password |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "value":true
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| value | boolean | 删除是否成功 |
Dependent service
Event Bus Module: Send Remove Account Event.
Function Description
Import accounts based on private keys, generate accounts based on private keys, and import account book data.
Process description

Import account information based on private key
1. Generate a public-private key pair based on the private key.
+2. get the chainId and account type.
+3. calculate hash160 according to Public key.
+4.Stitching byte arrays to form addresses
+4.1.If it is the NULS system address: address=type+hash160
+4.2、If non-NULS system address (bitcoin): original address length + original address
+5、Generate address string: address byte[] + check digit, then perform base58 calculation to generate string
+5.1.If it is the NULS system check digit: xor=XOR(addressType+pkh)
+5.2.If non-NULS system check digit: xor=XOR(length+address)
+6. base58 calculation generates the address string:
+ NULS system address: Base58 (type+hash160+xor)+Base58(chainId)
+ Non-NULS system address: Base58 (length+address+xor)+Base58(chainId)
+7. Encrypt the private key according to the password and delete the plaintext of the private key.
+8. storage account information.
+9. add the account to the cache.
+10. If you send an import account event: If the account already exists, the new event will not be released, only the update will be made.
+ac_importAccountByPriKey interface
Interface Description
The interface is imported into the account based on the account private key.
Request example
{
+ "cmd": "ac_importAccountByPriKey",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "00c22ad91a170fc49df53b79791f702879eb0604235787eee2c303463bf6e41111",
+ "123456",
+ true
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | priKey | true | String | Account private key |
| 2 | password | false | String | Account password |
| 3 | overwrite | true | Boolean | Whether to overwrite when the account exists |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "address":"NseMUi1q9TefkXUcaysAuvFjj4NbTEST"
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| address | String | Account address |
Dependent service
Event Bus Module: Send Import Account Event when the account does not exist.
Account Book: Import Account leger(confirmed transaction)
Function Description
According to the keystore import account, according to the keystore parsing and decrypting to get the private key and generate an account, and import the account book data
Process description

1. Verify that the keystore and password match.
+2. decrypt the private key in the keystore according to the password.
+3. Generate public and private based on the private key.
+4. get the chainId and account type.
+5. spliced byte array to form an address.
+6. generate an address string.
+7. Verify that the address string and the address in the keystore are consistent.
+8. storage account information.
+9. send import account event: the account already exists, do not post new events, only do the coverage update.
+ac_importAccountByKeystore interface
Interface Description
This interface is used to import accounts keystore
Request example
{
+ "cmd": "ac_importAccountByKeystore",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "HEX",
+ "123456",
+ true
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | keyStore | true | String | Imported keyStore hex code |
| 2 | password | false | String | Account password |
| 3 | overwrite | true | Boolean | Whether to overwrite when the account exists |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "address":"ABCMUi1q9TefkXUcaysAuvFjj4NbTEST"
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| address | String | Account address |
Dependent service
Event Bus Module: Send Import Account Event when the account does not exist
Account Book: Import Account leger(confirmed transaction)
Function Description
Import a multi-signed account related to the local address, including the address of the account, the creation of the script, and save the multi-signed account information to the database.
Process description
1. Verify that the multi-sign address, the signature public key list, and the minimum number of verified signatures are correct.
+2. create a multi-signature script.
+3. Create an account address of multiple signature types according to the multi-signed script.
+4. Determine whether the imported multi-sign address is the same as the address generated by the script. If it is not the same, it prompts an import error.
+5. save multi-signed account information, including: address, public key list, minimum number of verification signatures.
+6. return to multi-signal address.
+
+ac_importMultiSigAccount interface
Interface Description
This interface is used to import multi-signature accounts.
Request example
{
+ "cmd": "ac_importMultiSigAccount",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "ABCMUi1q9TefkXUcaysAuvFjj4NbTEST",
+ ["pubKey1","pubKey2"],
+ 2
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | address | true | String | Multi-sign account address |
| 2 | pubkeys | true | jsonArray | Public key list that needs to be signed |
| 3 | minSigns | true | Integer | Minimum signature number, At least a few Public key verifications are required |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "address":"NseMUi1q9TefkXUcaysAuvFjj4NbTEST"
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| address | String | Multi-sign address |
Function Description
Export Account private key hex code
Process description

Export Account private key
1. Verify that the account exists and verify that the password is correct.
+2. decrypt the private key, generate a Hex string
+ac_exportAccountPriKey interface
Interface Description
This interface is used to export the Account private key.
Request example
{
+ "cmd": "ac_importMultiSigAccount",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "ABCMUi1q9TefkXUcaysAuvFjj4NbTEST",
+ "123456"
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | address | true | String | Account address |
| 2 | password | true | String | Account password |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "address":"NseMUi1q9TefkXUcaysAuvFjj4NbTEST",
+ "priKey":"1cb336b834494fb7eef070cf9c3e60a5a49e762ca1f81cb2592593047235f308"
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| address | String | Account address |
| priKey | String | Private key hex |
Function Description
Export account keystore
Process description

Export account keystore
1. Verify that the account exists and verify that the password is correct.
+2. generate a keystore file.
+ac_exportAccountKeyStore interface
Interface Description
This interface is used to export the account keystore.
Request example
{
+ "cmd": "ac_exportAccountKeyStore",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "ABCMUi1q9TefkXUcaysAuvFjj4NbTEST",
+ "123456"
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | address | true | String | Account address |
| 2 | password | true | String | Account password |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "address":"NseMUi1q9TefkXUcaysAuvFjj4NbTEST",
+ "encryptedPrivateKey":"",
+ "pubKey":"1cb336b834494fb7eef070cf9c3e60a5a49e762ca1f81cb2592593047235f308"
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| address | String | Account address |
| encryptedPrivateKey | String | Encrypted private key |
| pubKey | String | Public key hex |
Function Description
Query all accounts
Process description
1. query all account information
+ac_getAccountList interface
Interface Description
This interface is used to query all accounts.
Request example
{
+ "cmd":"ac_getAccountList",
+ "minVersion":1.0,
+ "params":[
+ 1234
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "list":[{
+ "address":"",
+ "alias":"",
+ "pubkeyHex":"",
+ "encryptedPrikeyHex":""
+ },{}]
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| list | List | Account list collection |
| address | String | Account address |
| alias | String | alias |
| pubkeyHex | String | Public key hex code |
| encryptedPrikeyHex | String | Encrypted private key hex code |
Function Description
Get an account based on address
Process description
1. Verify that the address exists.
+2. get an account based on the address
+ac_getAccountByAddress interface
Interface Description
This interface is used to get an account based on the address.
Request example
{
+ "cmd": "ac_getAccountByAddress",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "ABCMUi1q9TefkXUcaysAuvFjj4NbTEST"
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | address | true | String | Account address |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "address":"",
+ "alias":"",
+ "pubkeyHex":"",
+ "encryptedPrikeyHex":""
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| address | String | Account address |
| alias | String | alias |
| pubkeyHex | String | Public key hex code |
| encryptedPrikeyHex | String | Encrypted private key hex code |
Function Description
Query the list of Account addresses
Process description
1. Check whether the paging parameter is legal. The number of pages and the size of the page cannot be less than 0, and must be an integer.
+2. Query all accounts.
+3. Filter accounts that meet the paging conditions.
+4. Return only the address list of the account.
+ac_getAddressList interface
Interface Description
This interface is used to query the list of Account addresses.
Request example
{
+ "cmd": "ac_getAddressList",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ 0,
+ 10
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | pageNumber | true | Integer | pageNumber |
| 2 | pageSize | true | Integer | pageSize |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "list":["","",""]
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| list | jsonArray | Address list collection |
Function Description
Get an address based on alias
Process description
1. query whether the existence of alias
+2. return the Account address used to set the alias, and use Base58 to encode the Account address
+ac_getAddressByAlias interface
Interface Description
This interface is used to get the address based on alias.
Request example
{
+ "cmd": "ac_getAddressList",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "abc"
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | alias | true | String | alias |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "address":"NseMUi1q9TefkXUcaysAuvFjj4NbTEST",
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| address | String | Account address, Base58 code |
Function Description
Query Account private key
Process description
1. Check whether the address is correct, use Base58 decoding, and check the Chain ID, address type, and check digit respectively.
+2. Verify that the account exists.
+3. If the account is over-densified (with password) and is not unlocked, decrypt it by AES and verify that the password is correct, and obtain the unencrypted private key.
+4. use hexadecimal encoding, and return to Account private key.
+ac_getPriKeyByAddress interface
Interface Description
This interface is used to query the Account private key.
Request example
{
+ "cmd": "ac_getPriKeyByAddress",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "NseMUi1q9TefkXUcaysAuvFjj4NbTEST",
+ "123456"
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | address | true | String | address |
| 2 | password | false | String | Account password |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "priKey":"1cb336b834494fb7eef070cf9c3e60a5a49e762ca1f81cb2592593047235f308"
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| priKey | String | Private key hex |
Function Description
Query all Account private keys
Process description
1. Verify that the password format is correct and the password can be empty.
+2. get all local accounts.
+3. The encryption information of the local account must be the same. If the parameter password is not empty, the passwords of all accounts must be the same. If the parameter password is empty, all accounts cannot be set. Otherwise, the error is displayed.
+4. If the account is encrypted, the unencrypted private key is reversed by the password, otherwise the private key is obtained without encryption.
+5. Add all private keys to the collection and return.
+ac_getAllPriKey interface
Interface Description
This interface is used to query all Account private keys.
Request example
{
+ "cmd": "ac_getAllPriKey",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "123456"
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 2 | password | false | String | Account password |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "list":["",""]
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| list | String | Private key collection |
Function Description
set password
Process description
1. Verify that the account exists.
+2. Verify that the password has been set.
+3. set Account password.
+ac_setPassword interface
Interface Description
This interface is used to set the Account password.
Request example
{
+ "cmd": "ac_setPassword",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "NseMUi1q9TefkXUcaysAuvFjj4NbTEST",
+ "123456"
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | address | true | String | Account address |
| 2 | password | true | String | Account password |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "value":true
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| value | boolean | Data return object, password setting is successful |
Function Description
Set offline Account password
Process description
1. Verify that the address is correct.
+2. Verify that the private key is correct.
+3. create according to the private key.
+4. set offline Account password.
+ac_setOfflineAccountPassword interface
Interface Description
This interface is used to set the offline Account password.
Request example
{
+ "cmd": "ac_setOfflineAccountPassword",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "NseMUi1q9TefkXUcaysAuvFjj4NbTEST",
+ "00c22ad91a170fc49df53b79791f702879eb0604235787eee2c303463bf6e41111",
+ "123456"
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | address | true | String | Account address |
| 2 | priKey | true | String | Account private key |
| 3 | password | true | String | Account password |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "encryptedPriKey":""
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| encryptedPriKey | String | Encrypted private key |
Request Body
Function Description
change Password
Process description
1. verify the correctness of the old password.
+2. Update the private key ciphertext.
+3. send a password change event.
+ac_updatePassword interface
Interface Description
This interface is used to modify the Account password.
Request example
{
+ "cmd": "ac_updatePassword",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "NseMUi1q9TefkXUcaysAuvFjj4NbTEST",
+ "123456",
+ "111111"
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | address | true | String | Account address |
| 2 | password | true | String | Account password |
| 3 | newPassword | true | String | Account new password |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "value":true
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| value | boolean | Whether the password modification is successful |
Function Description
Modify offline Account password
Process description
1. Verify that the address is correct.
+2. Generate an offline account based on address, private key, and new password.
+ac_updateOfflineAccountPassword interface
Interface Description
This interface is used to modify the offline Account password.
Request example
{
+ "cmd": "ac_updateOfflineAccountPassword",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "NseMUi1q9TefkXUcaysAuvFjj4NbTEST",
+ "00c22ad91a170fc49df53b79791f702879eb0604235787eee2c303463bf6e41111",
+ "123456",
+ "111111"
+ ]
+}
+
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | address | true | String | Account address |
| 2 | priKey | true | String | Private key |
| 3 | password | true | String | Account password |
| 4 | newPassword | true | String | Account new password |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "encryptedPriKey":""
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| encryptedPriKey | String | Encrypted private key |
Function Description
verify password
Process description
1. Verify that the password is correct.
+2. return verification results.
+ac_validationPassword interface
Interface Description
This interface is used to verify the password.
Request example
{
+ "cmd": "ac_validationPassword",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "NseMUi1q9TefkXUcaysAuvFjj4NbTEST",
+ "123456"
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | address | true | String | Account address |
| 2 | password | true | String | Account password |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "value":true
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| value | boolean | Is the password correct |
Function Description
Verify that the account is encrypted
Process description
1. Verify that the account exists.
+2. Verify that the account is encrypted.
+3. return verification results.
+ac_isEncrypted interface
Interface Description
This interface is used to verify that the account is encrypted.
Request example
{
+ "cmd": "ac_isEncrypted",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "NseMUi1q9TefkXUcaysAuvFjj4NbTEST"
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | address | true | String | Account address |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "value":true
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| value | boolean | Whether the account is encrypted |
Function Description
Set up an account alias
Process description
1. Verify that alias is legal
+2. generate settings alias transaction
+3. call ledger to fill transaction fee information
+4. broadcast transactions
+5. After the transaction is confirmed, the alias will be saved to the database, and address and alias will be stored as keys respectively. That is, the alias data will store two data, mainly for the convenience of querying according to address and alias.
+ac_setAlias interface
Interface Description
This interface is used to set the account alias.
Request example
{
+ "cmd": "ac_setAlias",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "NseMUi1q9TefkXUcaysAuvFjj4NbTEST",
+ "123456",
+ "abc"
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | address | true | String | Account address |
| 2 | password | false | String | Account password |
| 3 | alias | true | String | alias |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "txHash":"1cb336b834494fb7eef070cf9c3e60a5a49e762ca1f81cb2592593047235f308"
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| txHash | String | Alias transaction hash |
Dependent service
Account module: setting an alias requires a fee
Function Description
Get set alias fee
Process description
1. Verify that the account exists and verify that the alias is correct.
+2. calculate the fees required for the alias setting.
+ac_getAliasFee interface
Interface Description
This interface is used to get the set alias fee.
Request example
{
+ "cmd": "ac_getAliasFee",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "NseMUi1q9TefkXUcaysAuvFjj4NbTEST",
+ "abc"
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | address | true | String | Account address |
| 2 | alias | true | String | alias |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "fee":"100",
+ "maxAmount":"10000"
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| fee | String | Alias transaction fee |
| maxAmount | String | Maximum transaction fee |
Function Description
Query alias based on address
Process description
1. Verify that the account exists.
+2. query the account corresponding alias from the database
+ac_getAliasByAddress interface
Interface Description
This interface is used to query aliases based on the address.
Request example
{
+ "cmd": "ac_getAliasByAddress",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "NseMUi1q9TefkXUcaysAuvFjj4NbTEST"
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | address | true | String | Account address |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "alias":""
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| alias | String | Account alias |
Function Description
Verify that alias is available
Process description
1. Query whether the alias already exists. If it exists, it is not available. Otherwise, it is available.
+ac_isAliasUsable interface
Interface Description
This interface is used to verify if alias is available.
Request example
{
+ "cmd": "ac_isAliasUsable",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "abc"
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | alias | true | String | Account alias |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "value":true
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| value | boolean | Is alias available |
Function Description
Set account remark
Process description
1. Verify that the account exists.
+2. modify the remarks information and save
+ac_setRemark interface
Interface Description
This interface is used to set account remark.
Request example
{
+ "cmd": "ac_setRemark",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "NseMUi1q9TefkXUcaysAuvFjj4NbTEST"
+ "remark1"
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | address | true | String | Account address |
| 2 | remark | true | String | Account remark |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "value":true
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| value | boolean | Whether the setting is successful |
Function Description
Set up multi-sign account alias
Process description
1. Verify that the Account address, alias, Account password, and signature address parameters are legal.
+2. Query whether the Account address and the signature address exist.
+3. generate a set of multi-sign account alias trading.
+4, call ledger to fill transaction fee information.
+5. Sign the transaction using a signed account.
+6. Save the unconfirmed transaction to the local account when the signed number is equal to the minimum number of signatures.
+7. Broadcast the transaction.
+8. return the transaction hash.
+ac_setMultiSigAlias interface
Interface Description
This interface is used to set the multi-sign account alias.
Request example
{
+ "cmd": "ac_setMultiSigAlias",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "NseMUi1q9TefkXUcaysAuvFjj4NbTEST",
+ "DCQMUi1q9TefkXUcaysAuvFjj4NbTEST",
+ "123456",
+ "abc"
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | address | true | String | Multi-sign account address |
| 2 | signAddress | true | String | Signature address |
| 3 | password | false | String | Account password |
| 4 | alias | true | String | alias |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "txHash":"1cb336b834494fb7eef070cf9c3e60a5a49e762ca1f81cb2592593047235f308"
+ }
+}
+
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| txHash | String | Multi-signalias alias transactionhash |
Dependent service
Account module: setting a multi-signal alias requires a fee.
Function Description
Remove multi-signed account
Process description
1. Verify that the Account address is correct.
+2. delete the multi-signed account in the database.
+3. return to delete is successful.
+ac_removeMultiSigAccount interface
Interface Description
This interface is used to remove multi-signed accounts.
Request example
{
+ "cmd": "ac_setMutilSigAlias",
+ "minVersion":1.0,
+ "params": [
+ 1234,
+ "DCQMUi1q9TefkXUcaysAuvFjj4NbTEST",
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | address | true | String | Multi-sign account address |
Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "value":true
+ }
+}
+
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| value | boolean | Whether the removal was successful |
Function Description
account module all transaction verification interface, currently only alias transaction
Process description
1. Is the transaction list empty
+2. loop through all transaction lists, processing for alias transactions
+3. Check if the same alias is set in the current transaction list.
+4. Check whether there is an account duplicate setting alias in the current transaction list.
+5. If there is no conflict in the transaction list, the verification is passed.
+ac_accountTxValidate interface
Interface Description
This interface is used to batch verify all transactions in the account module.
Request example
{
+ "cmd": "ac_accountTxValidate",
+ "minVersion":1.0,
+ "params": [chianId, ["txHex","txHex","txHex", ...]]
+}
+
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | txHex | true | array | Alias transaction serialization data array |
txHex description
{
+ "type":3,
+ "time":"12546545596",
+ "scriptSig":"",
+ "hash":"",
+ "coinData":
+ {
+ "froms":
+ [{
+ "address":"Nse8m2Te1UNGPhD1tjZ3A4GDW3dCJxqE",
+ "amount":10000,
+ "nonce":"123",
+ }],
+ "to":
+ [{
+ "address":"Nse8m2Te1UNGPhD1tjZ3A4GDW3dCJxqE",
+ "amount":1
+ }]
+ },
+ "txData":
+ {
+ "chainId":"12345",
+ "address":"Nse8m2Te1UNGPhD1tjZ3A4GDW3dCJxqE",
+ "alias":"lucas"
+ }
+}
+Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "list":["txHex", "txHex", "txHex", ...]
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| list | jsonArray | Illegal transaction serialization data array |
Function Description
alias transaction verification interface
Process description
1. deserialize txHex alias transaction data
+2. verify the alias format
+3. Verify that the alias is already occupied.
+4. Verify that the account has an alias set.
+5. verify the coinData input and output
+6. verify the script signature format
+7. Verify that the signature contains the address of the alias.
+If it is not included, it is a malicious foul.
+Otherwise, the verification is passed.
+ac_aliasTxValidate interface
Interface Description
This interface is used for a single alias transaction.
Request example
{
+ "cmd": "ac_aliasTxValidate",
+ "minVersion":1.0,
+ "params": [chainId,"txHex"]
+}
+
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | txHex | true | String | alias transaction serialization data |
txHex description
{
+ "type":3,
+ "time":"12546545596",
+ "scriptSig":"",
+ "hash":"",
+ "coinData":
+ {
+ "froms":
+ [{
+ "address":"Nse8m2Te1UNGPhD1tjZ3A4GDW3dCJxqE",
+ "amount":10000,
+ "nonce":"123",
+ }],
+ "to":
+ [{
+ "address":"Nse8m2Te1UNGPhD1tjZ3A4GDW3dCJxqE",
+ "amount":1
+ }]
+ },
+ "txData":
+ {
+ "chainId":"12345",
+ "address":"Nse8m2Te1UNGPhD1tjZ3A4GDW3dCJxqE",
+ "alias":"lucas"
+ }
+}
+Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "value":true
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| value | boolean | Whether the verification is successful |
Function Description
Alias transaction submit, save alias
Process description
1. deserialize txHex alias transaction data
+2. save the alias alias to the database
+3. set the alias to account and save to the database
+4. Re-cache the modified account
+5. return the alias save is successful
+ac_aliasTxCommit interface
Interface Description
This interface is used to save aliases.
Request example
{
+ "cmd": "ac_aliasTxCommit",
+ "minVersion":1.0,
+ "params": [chainId,"txHex","secondaryDataHex"]
+}
+
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | txHex | true | String | Alias transaction serialization data |
| 2 | secondaryDataHex | true | String | Block header serialization data |
txHex description
{
+ "type":3,
+ "time":"12546545596",
+ "scriptSig":"",
+ "hash":"",
+ "coinData":
+ {
+ "froms":
+ [{
+ "address":"Nse8m2Te1UNGPhD1tjZ3A4GDW3dCJxqE",
+ "amount":10000,
+ "nonce":"123",
+ }],
+ "to":
+ [{
+ "address":"Nse8m2Te1UNGPhD1tjZ3A4GDW3dCJxqE",
+ "amount":1
+ }]
+ },
+ "txData":
+ {
+ "chainId":"12345",
+ "address":"Nse8m2Te1UNGPhD1tjZ3A4GDW3dCJxqE",
+ "alias":"lucas"
+ }
+}
+secondaryDataHex description
"txData":
+ {
+ "hash":"",
+ "height":1,
+ "time":13369748564
+ }
+Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "value":true
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| value | boolean | Is the alias transaction saved successfully |
Function Description
Alias transaction rollback interface
Process description
1. deserialize txHex alias transaction data
+2. delete the alias object data from the database
+3. take the corresponding account to clear the alias, re-sent the database
+4. re-cache account
+5. return the alias rollback is successful
+ac_aliasTxRollback interface
Interface Description
This interface is used to roll back an alias.
Request example
{
+ "cmd": "ac_aliasTxRollback",
+ "minVersion":1.0,
+ "params": [chainId,"txHex","secondaryDataHex"]
+}
+
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Short | Chain ID |
| 1 | txHex | true | String | Alias transaction serialization data |
| 2 | secondaryDataHex | true | String | Block header serialization data |
txHex description
{
+ "type":3,
+ "time":"12546545596",
+ "scriptSig":"",
+ "hash":"",
+ "coinData":
+ {
+ "froms":
+ [{
+ "address":"Nse8m2Te1UNGPhD1tjZ3A4GDW3dCJxqE",
+ "amount":10000,
+ "nonce":"123",
+ }],
+ "to":
+ [{
+ "address":"Nse8m2Te1UNGPhD1tjZ3A4GDW3dCJxqE",
+ "amount":1
+ }]
+ },
+ "txData":
+ {
+ "chainId":"12345",
+ "address":"Nse8m2Te1UNGPhD1tjZ3A4GDW3dCJxqE",
+ "alias":"lucas"
+ }
+}
+secondaryDataHex description
"txData":
+ {
+ "hash":"",
+ "height":1,
+ "time":13369748564
+ }
+Return example
{
+ "code": 0,
+ "msg": "success",
+ "version":1.0,
+ "result": {
+ "value":true
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| code | Integer | Return result status |
| msg | String | Failure message |
| result | jsonObj | Data return object |
| value | boolean | Is the alias transaction rollback successful |
create Account
event_topic : "evt_ac_createAccount"
data:{
+ address:''
+ isEncrypted:true //Is the password set
+}
+remove account
event_topic : "evt_ac_removeAccount"
data:{
+ address:''
+}
+change password
event_topic : "evt_ac_updatePassword"
data:{
+ address:''
+}
+no
Set alias
protocol
Compared with the general transaction, only the type and txData are different, the specific difference is as follows
type: n //Set the type of alias transaction
+txData:{
+ address: //VarByte Set the address of alias
+ alias: //VarByte Array of bytes converted into an alias string, decoded with UTF-8
+}
+| Len | Fields | Data Type | Remark |
|---|---|---|---|
| 24 | address | byte[] | Set the address of alias |
| 32 | alias | byte[] | Array of bytes converted into an alias string, decoded with UTF-8 |
1. alias format legality verification.
+2. the address must be the satellite chain address, and an address can only be set to an alias.
+3. burn a token unit.
+4. Transaction fee.
+5. signature: set address, input, signature verification.
+1. the asset processor.
+2. store alias data.
+3. Update local account information.
+server.ip:0.0.0.0 //Native ip, used to provide services to other modules
+server.port:8080 //Service port
+Account Object design
The key used when the table is stored:
NULS system:chainId+type+hash160
non-NULS system:chainId+length+address
Field name | type | Description |
|---|---|---|
| chainId | short | Chain ID |
| address | String | Account address(Base58(address)+Base58(chainId)) |
| alias | String | Account alias |
| status | Integer | Account Status |
| pubKey | byte[] | Public key |
| priKey | byte[] | Private key - not encrypted |
| encryptedPriKey | byte[] | Encrypted private key |
| extend | byte[] | Extended data |
| remark | String | ramark |
| createTime | long | create time |
Field name | type | Description |
|---|---|---|
| chainId | short | Chain ID |
| addressType | byte | Address type |
| hash160 | byte[] | Public key hash |
| addressBytes | byte[] | Address byte array |
Alias object design
The key used when the table is stored:
Address and alias are stored as keys respectively, and alias data is stored in two copies.
Need to create different alias tables according to different chains.
Field name | type | Description |
|---|---|---|
| address | byte[] | Account address |
| alias | String | Account alias |
Field name | type | Description |
|---|---|---|
| address | String | Account address |
| pubKeyList | List<byte[]> | Public key list that needs to be signed |
| minSigns | long | Minimum number of signatures |
[TOC]
All transaction data in the blockchain is stored in the block, so there is a module responsible for the saving and management of the block, so that other modules can obtain the block when verifying the data in the block and processing the business etc.
When the blockchain program is started for the first time, it is necessary to synchronize the full blocks from the network to the local. This process is generally time consuming, and the transaction cannot be initiated when the synchronization is not completed, so it is suitable for the work to be performed by a separate module.
In summary, it is necessary to provide a unified block data service for other modules, and it is also better to separate the management of the block from the specific service of the block. The modules who used the block do not have to care about the details of block's acquire.
When the system starts, it is judged whether the height of the local block reaches the latest height of most nodes on the network. If it is not reached, the block is downloaded from the network to the local, and then the block will be verified. If the verification is passed, the data is saved to the local database. This is called synchronization of blocks.
After the block synchronization is completed, the system starts normal operation.Let's discuss separately below
If the self-node performs the packing block, the consensus module broadcasts the block information to the network before the packaged block is handed over to the block management module. The block management module verifies whether the block is legal, if legal then save it to the database, and respond to requests from other nodes on the network to get this block.
If other nodes on the network are packing blocks, the local node will receive the forwarding block message sent from the network. At this time, the block information is obtained from other nodes, verified and saved.
In the abnormal case, the block's verification fails, and the new block cannot be connected to the last block on the main chain. The block is regarded as a forked block and placed in the forked chain set for maintenance. When it is found that one of the forked chains A is longer than the main chain B, the switching is performed, and the bifurcation chain A is the latest main chain, and the original main chain B enters the bifurcation chain assembly maintenance.
Provide block header and block's query services for other modules or clients.
Block management is one of the underlying modules. The following sub-functions discuss module dependencies.
rely
Be dependent


Sample request
{
+ "cmd": "bl_bestBlockHeader",
+ "minVersion":"1.1",
+ "params": ["888"]
+}
+Instructions of request parameters
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Long | chain ID |
response sample
Failed
{
+ "version": 1.2,
+ "code": 1,
+ "msg": "error message",
+ "result": {}
+}
+Success
{
+ "version": 1.2,
+ "code": 0,
+ "result": {
+ "chainId": "888",
+ "hash": "xxxxxxx",
+ "preHash": "xxxxxxx",
+ "merkleHash": "1",
+ "height": 1,
+ "size": 1,
+ "time": 1,
+ "txCount": 1,
+ "packingAddress": "1",
+ "reward": 0,
+ "fee": 0,
+ "extend": xxxxxxx,HEX
+ "scriptSig": "1"
+ }
+}
+Instructions of response parameters
| parameter | type | description |
|---|---|---|
| chainId | Long | chain ID |
| hash | String | block HASH |
| preHash | String | pre block HASH |
| merkleHash | String | block's MerkleHash |
| height | Long | block height |
| size | Integer | block size |
| time | Long | packing timestamp |
| txCount | Integer | count of transactions |
| packingAddress | String | packing address |
| reward | Long | Consensus reward |
| fee | Long | procedure fee |
| extend | String | Extension field,HEX,contains roundIndex、roundStartTime、consensusMemberCount、packingIndexOfRound、stateRoot |
| scriptSig | String | block's signature |
Sample request
{
+ "cmd": "bl_bestBlock",
+ "minVersion":"1.1",
+ "params": [“888”]
+}
+Instructions of request parameters
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Long | chain ID |
response sample
Failed
```
+{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+```
+ Success
{
+ "version": 1.2,
+ "code": 0,
+ "result": {
+ "blockHeader": {
+ "chainId": "888",
+ "hash": "xxxxxxx",
+ "preHash": "xxxxxxx",
+ "merkleHash": "1",
+ "height": 1,
+ "size": 1,
+ "time": 1,
+ "txCount": 1,
+ "packingAddress": "1",
+ "reward": 0,
+ "fee": 0,
+ "extend": xxxxxxx,HEX
+ "scriptSig": "1"
+ }, //block header
+ "transactions": [
+ {
+ "chainId": "888", //chain Id
+ "height": "1", //block height
+ "hash": "1", //transaction HASH
+ "remark": "1", //transaction remark
+ "size": "1", //transaction size
+ "time": "1", //transaction timestamp
+ "type": "1", //transaction type
+ "transactionSignature": "1", //transaction sign
+ "coinData": {
+ "from" : [
+ {
+ “fromAssetsChainId”:“”
+ “fromAssetsId”:“”
+ “fromAddress”:“”
+ “amount”:“”
+ “nonce”:“”//Transaction sequence number and increasing
+ },{...}
+ ]
+ "to" : [
+ {
+ “toAssetsChainId”:“”
+ “toAssetsId”:“”
+ “toAddress”:“”
+ “amount”:“”
+ “locktime”:“”
+ },{...}
+ ]
+ }
+ "txData": XXXX, //Special transaction data HEX
+ },
+ {...}
+ ], //transaction list
+ }
+}
+Instructions of response parameters
omit
Sample request
{
+ "cmd": "bl_getBlockHeaderByHeight",
+ "minVersion":"1.1",
+ "params": ["111","888"]
+}
+Instructions of request parameters
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Long | chain ID |
| 1 | height | true | Long | block's height |
response sample
Failed
{
+ "version": 1.2,
+ "code": 1,
+ "msg": "error message",
+ "result": {}
+}
+Success
{
+ "version": 1.2,
+ "code": 0,
+ "result": {
+ "chainId": "888",
+ "hash": "xxxxxxx",
+ "preHash": "xxxxxxx",
+ "merkleHash": "1",
+ "height": 1,
+ "size": 1,
+ "time": 1,
+ "txCount": 1,
+ "packingAddress": "1",
+ "reward": 0,
+ "fee": 0,
+ "extend": xxxxxxx,HEX
+ "scriptSig": "1"
+ }
+}
+Instructions of response parameters
| parameter | type | description |
|---|---|---|
| chainId | Long | chain ID |
| hash | String | block hash |
| preHash | String | pre block hash |
| merkleHash | String | block's MerkleHash |
| height | Long | block's height |
| size | Integer | block's size |
| time | Long | block's packing timestamp |
| txCount | Integer | count of transactions |
| packingAddress | String | address of packing |
| reward | Long | Consensus reward |
| fee | Long | procedure fee |
| extend | String | Extension field,HEX,contains roundIndex、roundStartTime、consensusMemberCount、packingIndexOfRound、stateRoot |
| scriptSig | String | Signature of block |
Sample request
{
+ "cmd": "bl_getBlockByHeight",
+ "minVersion":"1.1",
+ "params": [“111”,"888"]
+}
+Instructions of request parameters
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Long | chain ID |
| 1 | height | true | Long | block's height |
response sample
Failed
```
+{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+```
+ Success
{
+ "version": 1.2,
+ "code": 0,
+ "result": {
+ "blockHeader": {
+ "chainId": "888",
+ "hash": "xxxxxxx",
+ "preHash": "xxxxxxx",
+ "merkleHash": "1",
+ "height": 1,
+ "size": 1,
+ "time": 1,
+ "txCount": 1,
+ "packingAddress": "1",
+ "reward": 0,
+ "fee": 0,
+ "extend": xxxxxxx,HEX
+ "scriptSig": "1"
+ }, //block header
+ "transactions": [
+ {
+ "chainId": "888",//chain ID
+ "height": "1", //block's height
+ "hash": "1", //transaction's hash
+ "remark": "1", //transaction's remark
+ "size": "1", //transaction's size
+ "time": "1", //transaction's timestamp
+ "type": "1", //transaction's type
+ "transactionSignature": "1", //transaction's sign
+ "coinData": {
+ "from" : [
+ {
+ “fromAssetsChainId”:“”
+ “fromAssetsId”:“”
+ “fromAddress”:“”
+ “amount”:“”
+ “nonce”:“”
+ },{...}
+ ]
+ "to" : [
+ {
+ “toAssetsChainId”:“”
+ “toAssetsId”:“”
+ “toAddress”:“”
+ “amount”:“”
+ “nonce”:“”
+ },{...}
+ ]
+ }
+ "txData": XXXX, //HEX
+ },
+ {...}
+ ],
+ }
+}
+Instructions of response parameters
omit
Sample request
{
+ "cmd": "bl_getBlockHeaderByHash",
+ "minVersion":"1.1",
+ "params": ["888","aaa"]
+}
+Instructions of request parameters
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Long | chain ID |
| 1 | hash | true | String | block hash |
response sample
Failed
{
+ "version": 1.2,
+ "code": 1,
+ "msg": "error message",
+ "result": {}
+}
+Success
{
+ "version": 1.2,
+ "code": 0,
+ "result": {
+ "chainId": "888",
+ "hash": "xxxxxxx",
+ "preHash": "xxxxxxx",
+ "merkleHash": "1",
+ "height": 1,
+ "size": 1,
+ "time": 1,
+ "txCount": 1,
+ "packingAddress": "1",
+ "reward": 0,
+ "fee": 0,
+ "extend": xxxxxxx,HEX
+ "scriptSig": "1"
+ }
+}
+Instructions of response parameters
| parameter | type | description |
|---|---|---|
| chainId | Long | chain ID |
| hash | String | block hash |
| preHash | String | pre block hash |
| merkleHash | String | block's MerkleHash |
| height | Long | block's height |
| size | Integer | block's size |
| time | Long | block's packing timestamp |
| txCount | Integer | count of transactions |
| packingAddress | String | address of packing |
| reward | Long | Consensus reward |
| fee | Long | procedure fee |
| extend | String | Extension field,HEX,contains roundIndex、roundStartTime、consensusMemberCount、packingIndexOfRound、stateRoot |
| scriptSig | String | Signature of block |
Sample request
{
+ "cmd": "bl_getBlockByHash",
+ "minVersion":"1.1",
+ "params": ["888",“aaa”]
+}
+Instructions of request parameters
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Long | chain ID |
| 1 | hash | true | String | block hash |
response sample
Failed
```
+{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+```
+ Success
{
+ "version": 1.2,
+ "code": 0,
+ "result": {
+ "blockHeader": {
+ "chainId": "888",
+ "hash": "xxxxxxx",
+ "preHash": "xxxxxxx",
+ "merkleHash": "1",
+ "height": 1,
+ "size": 1,
+ "time": 1,
+ "txCount": 1,
+ "packingAddress": "1",
+ "reward": 0,
+ "fee": 0,
+ "extend": xxxxxxx,HEX
+ "scriptSig": "1"
+ }, //block header
+ "transactions": [
+ {
+ "chainId": "888",
+ "height": "1", //block's height
+ "hash": "1", //transaction's hash
+ "remark": "1", //transaction's remark
+ "size": "1", //transaction's size
+ "time": "1", //transaction's timestamp
+ "type": "1", //transaction's type
+ "transactionSignature": "1", //transaction's sign
+ "coinData": {
+ "from" : [
+ {
+ “fromAssetsChainId”:“”
+ “fromAssetsId”:“”
+ “fromAddress”:“”
+ “amount”:“”
+ “nonce”:“”
+ },{...}
+ ]
+ "to" : [
+ {
+ “toAssetsChainId”:“”
+ “toAssetsId”:“”
+ “toAddress”:“”
+ “amount”:“”
+ “nonce”:“”
+ },{...}
+ ]
+ }
+ "txData": XXXX, //HEX
+ },
+ {...}
+ ],
+ }
+}
+Instructions of response parameters
omit
When the block synchronization on a ChainID is completed, the cached synchronization status identifier is updated. It is forbidden to initiate a transaction when the block synchronization is not completed.
Sample request
{
+ "cmd": "bl_getSynchronizeInfo",
+ "minVersion":"1.1",
+ "params": ["888"]
+}
+Instructions of request parameters
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Long | chain ID |
response sample
Failed
{
+ "version": 1.2,
+ "code": 1,
+ "msg": "error message",
+ "result": {}
+}
+Success
{
+ "version": 1.2,
+ "code": 0,
+ "result": {"sync": "true"}
+}
+Instructions of response parameters
| parameter | type | description |
|---|---|---|
| sync | String | Block the synchronization to be achieved |
Sample request
{
+ "cmd": "bl_getBlockHeaderBetweenHeights",
+ "minVersion":"1.1",
+ "params": ["888",111","111"]
+}
+Instructions of request parameters
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Long | chain ID |
| 1 | startHeight | true | Long | start Height |
| 2 | endHeight | true | Long | end Height |
response sample
Failed
{
+ "version": 1.2,
+ "code": 1,
+ "msg": "error message",
+ "result": {}
+}
+Success
{
+ "version": 1.2,
+ "code": 0,
+ "result": {
+ “list” : [
+ {
+ "chainId": "888",
+ "hash": "xxxxxxx",
+ "preHash": "xxxxxxx",
+ "merkleHash": "1",
+ "height": 1,
+ "size": 1,
+ "time": 1,
+ "txCount": 1,
+ "packingAddress": "1",
+ "reward": 0,
+ "fee": 0,
+ "extend": xxxxxxx,HEX
+ "scriptSig": "1"
+ }
+ ]
+
+ }
+}
+Instructions of response parameters
| parameter | type | description |
|---|---|---|
| chainId | Long | chain ID |
| hash | String | block hash |
| preHash | String | pre block hash |
| merkleHash | String | block's MerkleHash |
| height | Long | block's height |
| size | Integer | block's size |
| time | Long | block's packing timestamp |
| txCount | Integer | count of transactions |
| packingAddress | String | address of packing |
| reward | Long | Consensus reward |
| fee | Long | procedure fee |
| extend | String | Extension field,HEX,contains roundIndex、roundStartTime、consensusMemberCount、packingIndexOfRound、stateRoot |
| scriptSig | String | Signature of block |
Sample request
{
+ "cmd": "bl_getBlockBetweenHeights",
+ "minVersion":"1.1",
+ "params": ["888",111","111"]
+}
+Instructions of request parameters
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | Long | chain ID |
| 1 | startHeight | true | Long | start Height |
| 2 | endHeight | true | Long | end Height |
response sample
Failed
{
+ "version": 1.2,
+ "code": 1,
+ "msg": "error message",
+ "result": {}
+}
+Success
{
+ "version": 1.2,
+ "code": 0,
+ "result": {
+ “list” : [
+ {
+ "blockHeader": {
+ "chainId": "888",
+ "hash": "xxxxxxx",
+ "preHash": "xxxxxxx",
+ "merkleHash": "1",
+ "height": 1,
+ "size": 1,
+ "time": 1,
+ "txCount": 1,
+ "packingAddress": "1",
+ "reward": 0,
+ "fee": 0,
+ "extend": xxxxxxx,HEX
+ "scriptSig": "1"
+ }, //block header
+ "transactions": [
+ {
+ "chainId": "888",
+ "height": "1", //block's height
+ "hash": "1", //transaction's hash
+ "remark": "1", //transaction's remark
+ "size": "1", //transaction's size
+ "time": "1", //transaction's timestamp
+ "type": "1", //transaction's type
+ "transactionSignature": "1", //transaction's sign
+ "coinData": {
+ "from" : [
+ {
+ “fromAssetsChainId”:“”
+ “fromAssetsId”:“”
+ “fromAddress”:“”
+ “amount”:“”
+ “nonce”:“”
+ },{...}
+ ]
+ "to" : [
+ {
+ “toAssetsChainId”:“”
+ “toAssetsId”:“”
+ “toAddress”:“”
+ “amount”:“”
+ “nonce”:“”
+ },{...}
+ ]
+ }
+ "txData": XXXX, //HEX
+ },
+ {...}
+ ],
+ }
+ ]
+
+ }
+}
+Instructions of response parameters
omit
After the local node's consensus module paking a block, this interface is called to save the block data.
Sample request
{
+ "cmd": "bl_receivePackingBlock",
+ "minVersion":"1.1",
+ "params": [
+ blockhex
+ ]
+}
+Instructions of request parameters
omit
response sample
Failed
{
+ "version": 1.2,
+ "code": 1,
+ "msg": "error message",
+ "result": {}
+}
+Success
{
+ "version": 1.2,
+ "code": 0,
+ "result": {"sync": "true"}
+}
+Instructions of response parameters
| parameter | type | description |
|---|---|---|
| sync | String | wherther the Block's save is completed |
After the chain factory releases a chain, the core module calls the interface of the block management module, initializes the block and the forked chain database according to the chainID, starts a series of work threads corresponding to the chainID, and prepares for running the new chain.
Sample request
{
+ "cmd": "bl_startChain",
+ "minVersion":"1.1",
+ "params": ["888"]
+}
+Instructions of request parameters
omit
response sample
Failed
{
+ "version": 1.2,
+ "code": 1,
+ "msg": "error message",
+ "result": {}
+}
+Success
{
+ "version": 1.2,
+ "code": 0,
+ "result": {"result": "true"}
+}
+Instructions of response parameters
| parameter | type | description |
|---|---|---|
| result | String | whether the new chain started successfully |
After stopping a chain in the chain factory, the core module will call the interface of the block management module, delete the cache block and the fork chain data of the chain, and stop a series of work threads corresponding to the chainID.
Sample request
{
+ "cmd": "bl_stopChain",
+ "minVersion":"1.1",
+ "params": ["888"]
+}
+Instructions of request parameters
omit
response sample
Failed
{
+ "version": 1.2,
+ "code": 1,
+ "msg": "error message",
+ "result": {}
+}
+Success
{
+ "version": 1.2,
+ "code": 0,
+ "result": {"result": "true"}
+}
+Instructions of response parameters
| parameter | type | description |
|---|---|---|
| result | String | whether the new chain started successfully |
Functional specifications:
omit
process description

Dependent service
Tool module、kernel module
Description storage table division
A complete block consists of a block header and a transaction, and the block header is stored separately from the transaction. +Block header: (in the block management module) +Key(block's height)-value(block header hash) block-header-index +Key(block headerhash)-value(complete block header) block-header +Trading: (put in the transaction management module)
fork chain's storage
+Cache each forked chain (starting height, starting hash, ending height, ending hash) in memory, and cache full forked chain data in the hard disk
+ There are different tables for the bifurcation chain collection of different chains. The table name is added with the chainID suffix. Each bifurcation chain object is as follows:
+ Key (start block height + start block hash) - value (complete chains) fork chains
+ Private chain chain;
+ Private String id;
+ Private String preChainId;
+ Private BlockHeader startBlockHeader;
+ Private BlockHeader endBlockHeader;
+ Private List
process description
omit
Dependent service
Database storage tool of tool modules
Functional specifications:
omit
process description

1. Traverse the node and count the two MAPs, assuming that each node (the latest HASH+ latest height) is the key
+ 2. A key with the key as the number of statistics
+ 3. A key is used to record the list of nodes holding the key.
+ 4. Finally, the most frequently occurring key is obtained, and the current trusted latest height and latest hash, as well as the list of trusted nodes are obtained.
+
+ for example:
+ Now connect to 10 nodes at the same time. The latest block's height of 4 nodes (A, B, C, D) is 100, the latest block hash is aaa, and the latest block's height of 6 nodes (E, F, G, H, I, J) is 101. The latest block hash is bbb.
+ Finally return (101, bbb, [E, F, G, H, I, J]).
+
Before the official download of the block, it is necessary to determine whether the local and the network are forked, and whether it needs to be rolled back. In order to find the exact block download height.
+ The following discussion is divided into:
+ Take the result of the previous step (101, bbb, [E, F, G, H, I, J]), while LH(N) represents the hash of the local Nth block, and RH(N) represents the hash of the Nth block on the network. .
+ 1. Local height 100 < network height 101, LH (100) == RH (100), normal, behind the remote node, download block
+ 2. Local height 100 < network height 101, LH (100)! = RH (100), think local fork, roll back the local block, if LH (99) == RH (99)
+ At the end of the rollback, download from 99 blocks. If LH(99)!=RH(99), continue to roll back and repeat the above logic. However, if you roll back 10 blocks at most, it will stop and wait for the next synchronization. This will avoid being attacked by malicious nodes and roll back normal blocks in large quantities.
+ 3. Local height 102> network height 101, LH (101) == RH (101), normal, leading than remote node, no need to download block
+ 4. Local height 102> network height 101, LH (101)! = RH (101), think local fork, first roll back to the height and remote consistency, repeat scene 2
+ 5. Local height 101 = network height 101, LH (101) == RH (101), normal, consistent with the remote node, no need to download the block
+ 6. Local height 101 = network height 101, LH (101)! = RH (101), think local fork, repeat scene 2
+
+ In the scenario that needs to be rolled back, the number of available nodes (10) > configuration, the number of consistent available nodes (6) accounted for more than 80%, and avoiding too few nodes leads to frequent rollback. The above two conditions are not met, empty the connected nodes, and re-acquire the available nodes.
+
+ When you actually download the block, give a chestnut:
+ The current height is 100, the network height is 500, 12 nodes are available, 10 nodes are consistently available, and each node downloads 2 blocks at a time.
+ Then calculate that you need to download 400 blocks, 400/(2*10)=20 rounds of downloading, and you can calculate the height range of each node download block per round.
+ Pseudo code representation
+ For (20 rounds){
+ For (10 nodes) {
+ Each node downloads the corresponding block and puts it in the shared queue for the block verification thread to process
+ }
+ }
+ Consider the case where the node is dropped during the download process. It is possible that 20 rounds cannot be downloaded, so the outer layer is added to the loop.
+ While (not downloaded){
+ Recalculate the round, download the block's height interval for each node
+ For (20 rounds){
+ For (10 nodes) {
+ Each node downloads the corresponding block and puts it in the shared queue for the block verification thread to process
+ }
+ }
+ }
+
Dependent service
Database storage tool of tool modules、RPC tool
Functional specifications:
Verify the correctness of the block's own data, verify during the download process, verify that there is no problem with the block data itself, and discard the block if the verification fails.
process description



Dependent service
Database storage tool of tool modules
Functional specifications:
Verify the correctness of the block context. After the download is complete, verify that the block is connected to the main chain. +The verification failure indicates that the block is bifurcated and enters the forked chain processing logic.
process description
Dependent service
Database storage tool of tool modules
Functional specifications:
Determine if the fork chain and the main chain need to be switched
process description +
Dependent service
Database storage tool of tool modules
Functional specifications:
omit
process description
Dependent service
Database storage tool of tool modules
Functional specifications:
omit
process description
Dependent service
Database storage tool of tool modules
Functional specifications:
omit
process description
Dependent service
Database storage tool of tool modules
Description: The synchronization is completed. When the height of the area is the same as the height of the network, the event is released.
Event_topic : "bl_blockSyncComplete",
Data:{
+ chainId
+ Height
+ Hash
+}
+Description:Each save a block, release the event
event_topic : "evt_bl_saveBlock",
data:{
+ chainId
+ height
+ hash
+}
+Description:Each roll back a block, release the event
event_topic : "evt_bl_rollbackBlock",
data:{
+ chainId
+ height
+ hash
+}
+omit
+ omit
+ Message description:Used for the "forward block" function
Message type(cmd)
ForwardSmallBlock
Message format(txData)
| Length | Fields | Type | Remark |
|---|---|---|---|
| 32 | chainID | uint32 | chain ID |
| 1 | digestAlgType | byte | digest algorithm identifier |
| ? | hashLength | VarInt | array's length |
| ? | hash | byte[] | hash |
Message validation
omit
Message processing logic
Message description:Used for the "forward block" function
Message type(cmd)
GetSmallBlock
Message format(txData)
| Length | Fields | Type | Remark |
|---|---|---|---|
| 32 | chainID | uint32 | chain ID |
| 1 | digestAlgType | byte | digest algorithm identifier |
| ? | hashLength | VarInt | array's length |
| ? | hash | byte[] | hash |
Message validation
omit
Message processing logic
Message description:Used for "forwarding block" and "broadcast block" functions
Message type(cmd)
SmallBlock
Message format(txData)
| Length | Fields | Type | Remark |
|---|---|---|---|
| 32 | chainID | uint32 | chain ID |
| 1 | digestAlgType | byte | digest algorithm identifier |
| ? | preHashLength | VarInt | preHash array's length |
| ? | preHash | byte[] | preHash |
| 1 | digestAlgType | byte | digest algorithm identifier |
| ? | merkleHashLength | VarInt | merkleHash array's length |
| ? | merkleHash | byte[] | merkleHash |
| 48 | time | Uint48 | time |
| 32 | height | Uint32 | block's height |
| 32 | txCount | Uint32 | count of transactions |
| ? | extendLength | VarInt | extend array's length |
| ? | extend | byte[] | extend |
| 32 | publicKeyLength | Uint32 | public key array's length |
| ? | publicKey | byte[] | public key |
| 1 | signAlgType | byte | Signature algorithm type |
| ? | signBytesLength | VarInt | sign array's length |
| ? | signBytes | byte[] | sign bytes |
| ? | txHashListLength | VarInt | transaction's hash list array's length |
| 1 | digestAlgType | byte | digest algorithm identifier |
| ? | txHashLength | VarInt | transaction's hash array's length |
| ? | txHash | byte[] | transaction's hash |
Message validation
omit
Message processing logic
Message description:For the "sync block" function
Message type(cmd)
GetBlocksByHeight
Message format(txData)
| Length | Fields | Type | Remark |
|---|---|---|---|
| 32 | chainID | uint32 | chain ID |
| 32 | startHeight | uint32 | start Height |
| 32 | endHeight | uint32 | end Height |
Message validation
omit
Message processing logic
Message description:Used for "block synchronization"
Message type(cmd)
GetBlock
Message format(txData)
| Length | Fields | Type | Remark |
|---|---|---|---|
| 32 | chainID | uint32 | chain ID |
| 1 | digestAlgType | byte | digest algorithm identifier |
| ? | HashLength | VarInt | Hash array's length |
| ? | Hash | byte[] | Hash |
Message validation
omit
Message processing logic
Message description:Used for "block synchronization"
Message type(cmd)
Block
Message format(txData)
| Length | Fields | Type | Remark |
|---|---|---|---|
| 32 | chainID | uint32 | chain ID |
| 1 | digestAlgType | byte | digest algorithm identifier |
| ? | preHashLength | VarInt | preHash array's length |
| ? | preHash | byte[] | preHash |
| 1 | digestAlgType | byte | digest algorithm identifier |
| ? | merkleHashLength | VarInt | merkleHash array's length |
| ? | merkleHash | byte[] | merkleHash |
| 48 | time | Uint48 | time |
| 32 | height | Uint32 | block's height |
| 32 | txCount | Uint32 | count of transactions |
| ? | extendLength | VarInt | extend array's length |
| ? | extend | byte[] | extend |
| 32 | publicKeyLength | Uint32 | public key array's length |
| ? | publicKey | byte[] | public key |
| 1 | signAlgType | byte | Signature algorithm type |
| ? | signBytesLength | VarInt | sign array's length |
| ? | signBytes | byte[] | Signature of block |
| 16 | type | uint16 | transaction's type |
| 48 | time | uint48 | transaction's timestamp |
| ? | remarkLength | VarInt | remark array's length |
| ? | remark | byte[] | remark bytes |
| 32 | fromCount | Uint32 | count of froms |
| 32 | fromAssetsChainId | Uint32 | chain id |
| 32 | fromAssetsId | Uint32 | asset id |
| ? | fromAddress | VarChar | from account address |
| 48 | amount | Uint48 | Transfer amount |
| 32 | nonce | Uint32 | Transaction sequence number, increment |
| 32 | toCount | Uint32 | count of tos |
| 32 | toAssetsChainId | Uint32 | chain id |
| 32 | toAssetsId | Uint32 | asset id |
| ? | toAddress | VarChar | to account address |
| 48 | amount | Uint48 | Transfer amount |
| 32 | lockTime | Uint32 | lock time |
| ? | txData | T | data of special transaction |
| ? | txSignLength | VarInt | transaction's sign array's length |
| ? | txSign | byte[] | transaction's sign |
Message validation
omit
Message processing logic
Message description:A generic message for an asynchronous request that marks the target node not finding the corresponding information.
Message type(cmd)
NotFound
Message format(txData)
| Length | Fields | Type | Remark |
|---|---|---|---|
| 32 | chainID | uint32 | chain ID |
| 1 | msgType | byte | Data type not found |
| 1 | digestAlgType | byte | digest algorithm identifier |
| ? | HashLength | VarInt | Hash array's length |
| ? | Hash | byte[] | Hash |
Message validation
omit
Message processing logic
Message description:A generic message, used for asynchronous requests, to flag that the target node receives the request and is processing it.
Message type(cmd)
React
Message format(txData)
| Length | Fields | Type | Remark |
|---|---|---|---|
| 32 | chainID | uint32 | chain ID |
| 1 | digestAlgType | byte | digest algorithm identifier |
| ? | HashLength | VarInt | Hash array's length |
| ? | Hash | byte[] | Hash |
Message validation
omit
Message processing logic
Message description:A generic message for asynchronous requests that marks the end of asynchronous request processing.
Message type(cmd)
Complete
Message format(txData)
| Length | Fields | Type | Remark |
|---|---|---|---|
| 32 | chainID | uint32 | chain ID |
| 1 | digestAlgType | byte | digest algorithm identifier |
| ? | HashLength | VarInt | Hash array's length |
| ? | Hash | byte[] | Hash |
| 1 | success | byte | flag |
Message validation
omit
Message processing logic
Message description:Used for "forwarding blocks"
Message type(cmd)
GetTxGroup
Message format(txData)
| Length | Fields | Type | Remark |
|---|---|---|---|
| 32 | chainID | uint32 | chain ID |
| ? | ArrayLength | VarInt | Hash list length |
| 1 | digestAlgType | byte | digest algorithm identifier |
| ? | HashLength | VarInt | Hash array's length |
| ? | Hash | byte[] | Hash |
Message validation
omit
Message processing logic
Message description:Used for "forwarding blocks"
Message type(cmd)
TxGroup
Message format(txData)
| Length | Fields | Type | Remark |
|---|---|---|---|
| 32 | chainID | uint32 | chain ID |
| 1 | digestAlgType | byte | digest algorithm identifier |
| ? | requestHashLength | VarInt | requestHash array's length |
| ? | requestHash | byte[] | requestHash |
| ? | txCount | VarInt | count of transactions |
| 16 | type | uint16 | transaction's type |
| 48 | time | uint48 | transaction's timestamp |
| ? | remarkLength | VarInt | remark array's length |
| ? | remark | byte[] | remark bytes |
| 32 | fromCount | Uint32 | count of froms |
| 32 | fromAssetsChainId | Uint32 | chain id |
| 32 | fromAssetsId | Uint32 | asset id |
| ? | fromAddress | VarChar | from account address |
| 48 | amount | Uint48 | Transfer amount |
| 32 | nonce | Uint32 | Transaction sequence number, increment |
| 32 | toCount | Uint32 | count of tos |
| 32 | toAssetsChainId | Uint32 | chain id |
| 32 | toAssetsId | Uint32 | asset id |
| ? | toAddress | VarChar | to account address |
| 48 | amount | Uint48 | Transfer amount |
| 32 | lockTime | Uint32 | lock time |
| ? | txData | T | data of special transaction |
| ? | txSignLength | VarInt | transaction's sign array's length |
| ? | txSign | byte[] | transaction's sign |
Message validation
omit
Message processing logic
omit
{
+ {
+ "name": "serverIp",
+ "remark": "service ip",
+ "changable": "true",
+ "default": "127.0.0.1"
+ },
+ {
+ "name": "serverPort",
+ "remark": "service port",
+ "changable": "true",
+ "default": ""
+ },
+ {
+ "name": "blockSize",
+ "remark": "block size",
+ "changable": "false",
+ "default": "3m"
+ },
+ {
+ "name": "resetTime",
+ "remark": "When the block height is not updated for a long time, the available nodes are reacquired",
+ "changable": "true",
+ "default": "180"
+ },
+ {
+ "name": "forkCount",
+ "remark": "When the fork chain is higher than the main chain, switch",
+ "changable": "false",
+ "default": "3"
+ },
+ {
+ "name": "cacheSize",
+ "remark": "forked chain cache size",
+ "changable": "true",
+ "default": "50m"
+ },
+ {
+ "name": "heightRange",
+ "remark": "Cache to the height range of the forked chain",
+ "changable": "false",
+ "default": "1000"
+ },
+ {
+ "name": "maxRollback",
+ "remark": "How many blocks are rolled back at most each time",
+ "changable": "true",
+ "default": "20"
+ },
+ {
+ "name": "consistencyNodePercent",
+ "remark": "The lowest percentage of consistent nodes available, below this number of unsynchronized blocks",
+ "changable": "false",
+ "default": "80"
+ },
+ {
+ "name": "minNodeAmount",
+ "remark": "The minimum number of available nodes, lower than this number of unsynchronized blocks",
+ "changable": "false",
+ "default": "10"
+ },
+ {
+ "name": "downloadNumber",
+ "remark": "How many blocks are downloaded from one node each time during synchronization",
+ "changable": "true",
+ "default": "20"
+ },
+ {
+ "name": "extendMaxSize",
+ "remark": "block header extension field maximum value",
+ "changable": "false",
+ "default": "1024"
+ }
+}
+
field namefield typeinstructionblockHeader BlockHeader block header transactions List transaction's list
field namefield typeinstructionblockHeader BlockHeader block header transactions List transaction's hash list subTxList List Transactions that other nodes must not have (such as consensus reward transactions, red and yellow card transactions, etc.
field namefield typeinstructionchainId long chain ID hash String block hash preHash String pre block hash merkleHash String block's MerkleHash height int block's height size short block's size time long block's packing timestamp txCount short count of transactions packingAddress String address of packing extend byte[] Extension field blockSignature BlockSignature Signature of block
field namefield typeinstructionsignData String Signature of block publicKey byte[] public key
[TOC]
In NULS 1.0, there is only one chain (NULS main network), so no chain management module is required.
In NULS 2.0, the NULS main network can register other friend information, including:
The Chain Management module is used to manage all the friends that join the NULS main network.
Glossary:
Hypothesis 1: Friendship A, which owns asset A
Hypothesis 2: Friendship B, which owns asset B
Remarks: Regardless of the assets in the chain or the assets outside the chain, as long as the assets are traded across the chain, the main network needs to be confirmed.
The Chain Management module is used to manage basic information about the chain that joins the NULS main network, including:
"chain management" dependent module:
Kernel module
Network module
Transaction management module
Account module
"chain management" weakly dependent module:
Event bus module


Function Description:
he NULS main network will provide an entry (web page) through which you can register a new friend chain to the NULS main network.
Process description

步骤描述:
Step description:
1> The user registers the registration chain information with the terminal and the asset information initialized with the chain.
+
+2> The chain management module performs the encapsulation of the chain transaction and sends it to the transaction module.
+ During the period, you need to obtain the account balance and the transaction nonce value through the ledger module.
+ And the seed node information of the cross-chain is obtained through the network module and returned to the user.
+
+3>The transaction module will perform a callback of the data check during the transaction process.
+
+4>The chain management module performs registration data submission through the transaction module callback interface of the “submission chain registration transaction”.
+
+5> The chain management module stores the data and sends the registration information to the network module.
+
+6> The registration chain requires 1000NULS, of which 20% is directly destroyed, 80% is used for mortgages, and is returned when assets are deleted.
+ Interface definition
Register friendchain information with the chain management module.
method : cm_chainReg
{
+ "chainId": 152,
+ "chainName": "nuls chain",
+ "addressType": "1",
+ "magicNumber":454546,
+ "supportInflowAsset":"1",
+ "minAvailableNodeNum":5,
+ "singleNodeMinConnectionNum":5,
+ "txConfirmedBlockNum":30,
+ "address":"NsdxSexqXF4eVXkcGLPpZCPKo92A8xpp",
+ "assetId":85,
+ "symbol":"NULS",
+ "assetName":"NULS CHAIN",
+ "initNumber":"1000000000",
+ "decimalPlaces":8,
+ "password":"xxxxxxxxxxxxx"
+
+}
+| parameter | required | type | description |
|---|---|---|---|
| chainId | true | int | Chain identification |
| chainName | true | string | Chain name |
| addressType | true | int | The address type of the account created on the chain: 1 within the ecological 2 non-ecological |
| magicNumber | true | string | Network magic parameter |
| minAvailableNodeNum | true | int | Minimum number of available nodes |
| singleNodeConMinNodeNum | true | int | Minimum number of single node connections |
| txConfirmBlockNum | true | int | Transaction confirmation block number |
| symbol | true | string | Asset symbol |
| assetName | true | string | Asset Name |
| initNumber | true | string | Initial value of assets |
| decimalPlaces | true | int | Minimum asset separable digits |
| address | true | string | Create the primary network address of the chain |
| password | true | string | Password corresponding to the private key |
Return example
Failed
Unified RPC standard format
+
+Success
{
+"seeds":"xxx.xxx.xxx.xxx:8001,xxx.xxx.xxx.xxx:8002"
+}
+
+Return field description
| parameter | type | description |
|---|---|---|
| seeds | String | Seed node |
Dependent service
Function Description:
The NULS main network will provide an entry (web page) through which you can log out existing friends.
Process description

1>The chain is created with the asset, so the logout chain must be checked for assets. Only the last asset will be deleted and the chain will be logged off.
2>Conditions for determining whether to allow cancellation:
Assets and chains exist.
There is only one last asset with the chain.
Chain assets have n% of assets in their own main chain.
3>The chain management module performs the encapsulation of the chain transaction and sends it to the transaction module.
During the period, you need to obtain the account balance and the transaction nonce value through the ledger module.
4>The transaction module will perform a callback of the data check during the transaction process.
5>The chain management module performs the logout data submission through the transaction module callback interface of the “commit chain cancellation transaction”.
6>The chain management module stores the data and sends the registration information to the network module.
7>Deleting the chain with the cancelled assets will return 80% of the mortgage deposit.
Interface definition
Unregister the chain information to the chain management module (the asset logout interface is called because the chain is logged off with the last asset)
method : cm_assetDisable
{
+ "chainId": 152,
+ "assetId": 45,
+ "address":"NsdxSexqXF4eVXkcGLPpZCPKo92A8xpp",
+ "password":"xxxxxxxxxxxxx"
+
+}
+| parameter | required | type | description |
|---|---|---|---|
| chainId | true | int | Chain identification |
| assetId | true | int | Asset id |
| address | true | string | Create the main network account address of the chain |
| password | true | string | Password corresponding to the private key |
Return example
Failed
Unified RPC standard format
+
+Success
Unified RPC standard format
+
+Return field description
| parameter | type | description |
|---|---|---|
Dependent service
Function Description:
The NULS main network will provide an entry (web page) through which the selection chain and registered assets can be registered.
Process description

Step description: + 1>The user enters the asset information through the terminal selection chain and the chain: judge whether the assets overlap. + 2> The chain management module performs the encapsulation of the chain transaction and sends it to the transaction module. + During the period, you need to obtain the account balance and the transaction nonce value through the ledger module. + 3> The transaction module will perform a callback of the data check during the transaction process. + 4> The chain management module performs registration data submission through the transaction module callback interface of “submit asset registration transaction”. + 5> Registered assets receive 1000NULS, of which 20% are directly destroyed, 80% are used for mortgage, and returned when assets are deleted.
Interface definition
Register asset information with the chain management module
method : cm_assetReg
{
+ "chainId": 152,
+ "assetId":85,
+ "symbol":"NULS",
+ "assetName":"NULS",
+ "initNumber":"1000000000",
+ "decimalPlaces":8,
+ "address":"NsdxSexqXF4eVXkcGLPpZCPKo92A8xpp",
+ "password":"xxxxxxxxxxxxx"
+
+}
+| parameter | required | type | description |
|---|---|---|---|
| chainId | true | int | Chain identification |
| symbol | true | string | Asset symbol |
| assetName | true | string | Asset Name |
| initNumber | true | string | Initial value of assets |
| decimalPlaces | true | int | Minimum asset separable digits |
| address | true | string | Create the primary network address of the chain |
| password | true | string | Password corresponding to the private key |
Return example
Failed
Unified RPC standard format
+Success
Unified RPC standard format
+Return field description
| parameter | type | description |
|---|---|---|
Dependent service
Function Description:
The NULS main network will provide an entry (web page) through which the assets can be destroyed for the specified friend chain.
Process description

Step description: +1> When there are multiple assets registered, the single asset is allowed to be written off. If there is only one asset, the asset is written off along with the chain. +2> Conditions for determining whether to allow cancellation: + There are multiple assets in the chain. + Chain assets have n% of assets in their own main chain. +3>The chain management module performs the encapsulation of the chain transaction and sends it to the transaction module. + During the period, you need to obtain the account balance and the transaction nonce value through the ledger module. +4>The transaction module will perform a callback of the data check during the transaction process. +5>The chain management module performs the logout data submission through the transaction module callback interface of the “commit chain cancellation transaction”. +6>The cancellation of the assets will be refunded 80% of the mortgage deposit.
Interface definition
Log out asset information to the chain management module
method : cm_assetDisable
{
+ "chainId": 152,
+ "assetId": 45,
+ "address":"NsdxSexqXF4eVXkcGLPpZCPKo92A8xpp",
+ "password":"xxxxxxxxxxxxx"
+
+}
+| parameter | required | type | description |
|---|---|---|---|
| chainId | true | int | Chain identification |
| assetId | true | int | Asset id |
| address | true | string | Create the main network account address of the chain |
| password | true | string | Password corresponding to the private key |
Return example
Failed
Unified RPC standard format
+
+Success
Unified RPC standard format
+
+Return field description
| parameter | type | description |
|---|---|---|
Dependent service
Function Description:
When the transaction module generates a cross-chain transaction, the interface is called to perform cross-chain asset verification.
Process description
1>Check chain and assets are registered normally in the cross-chain module
2>Check if the amount of assets on the chain is overdrawn.
3>Verify that the asset status is normal.
Interface definition
Submit verification to chain management when cross-chain assets are in circulation
method : cm_assetCirculateValidator
{
+ "coinDatas": "FFAABB214324"
+}
+| parameter | required | type | description |
|---|---|---|---|
| coinDatas | true | String | Trading the HEX value of coindata |
Return example
Failed
Unified RPC standard format
+
+Success
Unified RPC standard format
+
+Return field description
| parameter | type | description |
|---|---|---|
Dependent service
Function Description:
When the transaction module generates a cross-chain transaction and verifies the pass, it calls the interface to submit the cross-chain asset.
Process description
Used to change chain assets and manage them for chain assets
Direct call cm_assetCirculateCommit
Interface definition
When the cross-chain asset is circulated, the transaction can be submitted to the chain management when the verification is passed and the confirmation is submitted.
method : cm_assetCirculateCommit
{
+ "coinDatas": "FFAABB214324"
+}
+| parameter | required | type | description |
|---|---|---|---|
| coinDatas | true | String | Trading the HEX value of coindata |
Return example
Failed
Unified RPC standard format
+
+Success
Unified RPC standard format
+
+Return field description
| parameter | type | description |
|---|---|---|
Dependent service
Function Description:
When the module is started, registration of the transaction callback function is required, so that the transaction module performs callback processing when performing related type transaction processing.
The registration function is divided into 4 categories: 1> transaction verification 2> transaction submission 3> transaction rollback 4> module batch transaction verification within a block
Process description
1>Chain management module startup.
2>Determine whether the transaction module RPC call status is accessible.
3>Submit callback interface.
Interface definition
See the "Registering a Transaction" section in the Transaction Module Design Document.
Dependent service
Function Description:
Query registration chain information
Process description
NA
Interface definition
Query registration friend information
method : cm_chain
{
+ "chainId":4545
+}
+| parameter | required | type | description |
|---|---|---|---|
| chainId | true | int | Chain identification |
Return example
Failed
Unified RPC standard format
+
+Success
{
+ "chainId": 152,
+ "chainName": "nuls chain",
+ "addressType": 1,
+ "magicNumber":454546,
+ "supportInflowAsset":"1",
+ "minAvailableNodeNum":5,
+ "singleNodeMinConnectionNum":5,
+ "txConfirmedBlockNum":30,
+ "regAddress":"NsdxSexqXF4eVXkcGLPpZCPKo92A8xpp",
+ "regTxHash":"FFFFF",
+ "selfAssetKeyList":["1232_32","528_8"],
+ "totalAssetKeyList":["1232_32","528_8"],
+ "createTime":1212131
+}
+Return field description
| parameter | type | description |
|---|---|---|
| chainId | int | Chain identification |
| chainName | string | Chain name |
| addressType | int | The address type of the account created on the chain: 1 within the ecological 2 non-ecological |
| magicNumber | string | Network magic parameter |
| minAvailableNodeNum | int | Minimum number of available nodes |
| singleNodeConMinNodeNum | int | Minimum number of single node connections |
| txConfirmBlockNum | int | Transaction confirmation block number |
| regTxHash | string | Transaction hash |
| regAddress | string | Create the primary network address of the chain |
| selfAssetKeyList | list | List of assets registered under the chain, asset key value combined by chainId_assetId |
| totalAssetKeyList | list | List of assets circulating under the chain, asset key value combined by chainId_assetId |
| createTime | long | Creation time |
Dependent service
NA
Function Description:
Query a chain asset information
Process description
NA
Interface definition
Query the asset management module for an asset information.
method : cm_asset
{
+ "chainId":4545,
+ "assetId":45
+}
+| parameter | required | type | description |
|---|---|---|---|
| chainId | true | int | Chain identification |
| assetId | true | int | Asset id |
Return example
Failed
Unified RPC standard format
+
+Success
{
+ "chainId": 152,
+ "assetId":85,
+ "symbol":"NULS",
+ "assetName":"NULS ASSET",
+ "initNumber":"1000000000",
+ "decimalPlaces":8,
+ "address":"NsdxSexqXF4eVXkcGLPpZCPKo92A8xpp",
+ "txHash":"xxxxxxxxxxxxx",
+ "createTime":125848
+ }
+Return field description
| parameter | type | description |
|---|---|---|
| chainId | int | Chain identification |
| symbol | string | Asset symbol |
| assetName | string | Asset Name |
| initNumber | string | Initial value of assets |
| decimalPlaces | int | Minimum asset separable digits |
| address | string | Create the primary network address of the chain |
| txHash | string | Transaction hash |
| createTime | long | Creation time |
Dependent service
NA
| Length | Fields | Type | Remark |
|---|---|---|---|
| 2 | chainId | uint16 | Chain Id |
| 2 | assetId | uint16 | Asset id |
| 4 | randomCode | uint32 | random number |
| Length | Fields | Type | Remark |
|---|---|---|---|
| 2 | chainId | uint16 | Chain Id |
| 2 | assetId | uint16 | Asset id |
| 48 | biginteger | Total assets amount | |
| 4 | randomCode | uint32 | random number |
Compared with the general transaction, only the type and txData are different, the specific difference is as follows
Transaction type definition:10101
txData definition
| Length | Fields | Type | Remark |
|---|---|---|---|
| 2 | chainId | uint16 | Chain ID |
| ? | name | byte[] | Chain Name |
| 1 | addressType | uint8 | address type |
| 4 | magicNumber | uint32 | Magic parameter |
| 1 | supportInflowAsset | uint8 | Whether to spend asset inflows |
| 2 | minAvailableNodeNum | uint16 | Minimum number of available nodes |
| 2 | singleNodeMinConnectionNum | uint16 | Single node minimum connection number |
| ? | address | byte[] | Account address |
| 2 | assetId | uint16 | Asset id |
| ? | symbol | byte[] | symbol |
| ? | assetName | byte[] | Asset name |
| 2 | depositNuls | uint16 | Mortgage NULS quantity |
| 48 | initNumber | Biginteger | Initial quantity of assets |
| 1 | decimalPlaces | uint8 | Minimum number of assets |
Compared with the general transaction, only the type and txData are different, the specific difference is as follows
Transaction type definition:10102
txData definition:Same as 4.2.1 chain registration transaction
Compared with the general transaction, only the type and txData are different, the specific difference is as follows
Transaction type definition:10103
txData definition:
| Length | Fields | Type | Remark |
|---|---|---|---|
| 2 | chainId | uint16 | Chain Id |
| 2 | assetId | uint16 | Asset id |
| ? | symbol | byte[] | symbol |
| ? | assetName | byte[] | Asset name |
| 2 | depositNuls | uint16 | Mortgage NULS quantity |
| 48 | initNumber | Biginteger | Initial quantity of assets |
| 1 | decimalPlaces | uint8 | Minimum number of assets |
| ? | address | byte[] | Account address |
Compared with the general transaction, only the type and txData are different, the specific difference is as follows
Transaction type definition:10104
txData definition:New transactions with 4.2.3 assets
[system]
+language = en
+encoding = UTF-8
+
+[db]
+rocksdb.datapath = ../data
+
+[param]
+asset_symbol_max = 5
+asset_name_max = 20
+asset_depositNuls = 200000
+asset_depositNuls_destroy_rate = 0.2
+asset_depositNuls_lock_rate = 0.8
+asset_initNumber_min = 10000
+asset_initNumber_max = 100000000
+asset_decimalPlaces_min = 4
+asset_decimalPlaces_max = 8
+asset_recovery_rate = 0.9
+
+[defaultAsset]
+nuls_chain_id = 8964
+nuls_chain_name = nuls chain
+nuls_asset_id = 1
+nuls_asset_initNumber_max = 100000000
+nuls_asset_symbol = NULS
+NA
NA
[TOC]
As we all know, the core of the blockchain is the consensus mechanism. Unlike the traditional Internet's clipet-server architecture, the agents of the blockchain are peer-to-peer, without the center, and everyone has the same rights; so in order to make the data consistent, let a network without a center maintain a set of books that everyone agrees with. This is the role of the consensus mechanism.
Broadly speaking, the consensus mechanism is the rule or algorithm that each agent of the blockchain adheres to, and is the basis for mutual trust. In this way, it can achieve decentralized unsupervised and maintain the normal operation of the entire platform.
In a narrow sense, the consensus mechanism determines the mechanism by which each agent verifies and validates transactions on the blockchain.
Each transaction in the blockchain must be approved by each agent, and the transaction is completed only after the entire network has reached a consensus. It is like in a democratic election, the voting method or rules must be recognized by the whole people, based on which the election can be completed. In the blockchain, the main performance of the consensus mechanism is the incentive system, which is the reward for the miners. Under the guarantee of the consensus mechanism, every miner can be rewarded, and the entire blockchain can operate in an orderly manner, providing a fair, transparent and trusting environment. Therefore, the consensus module needs to provide a specific algorithm to maintain, that is, the consensus algorithm.
There are many public chain consensus mechanisms, and the mainstream is POW, POS, and DPOS. The NULS main network adopts the self-originated POC (Proof Of Credit) consensus mechanism, which inherits the security and high efficiency of the Dpos consensus mechanism. At the same time, it has made great improvements in collaboration, which can be regarded as an upgraded version. Dpos.
POC Consensus module responsibility:
Legality verification after block synchronization
Create consensus agents, delegate participation consensus, cancel delegation, and cancel consensus agents ★
Consensus agent packs out blocks
Disbursement of network maintenance incentives
Bad agent punishment ★
PS:Different consensus mechanisms have different consensus algorithms. The above marked ★ is unique to POC consensus.
The consensus module is a relatively core piece in the system. It is mainly responsible for packing transactions, verifying block headers, managing consensus agent information in the management system, entrusting information, and penalizing information.

Description:
The NULS 2.0 design concept is to provide modular services, and each module should support multiple chains of data running at the same time, so the consensus module needs to implement algorithms with different consensus mechanisms. When the consensus module is started, it can simultaneously support multiple chains to run at the same time.
The main network of NULS adopts the independent POC consensus mechanism. To realize POC, you first need to know the design concept and business rules of POC. The following content is taken from the introduction part of the NULS white paper POC consensus. If you are familiar, you can skip it directly.
Consensus mechanism——POC
+ The NULS main chain defaults to the credit consensus mechanism POC (Proof-Of-Credit). In the case where the agent credit is up to standard, a certain margin can be locked to join the consensus. After the consensus agent is reordered, each round will flow out of the block, and the margin will be unlocked when the consensus is exited.
+
+1、Consensus entry and exit mechanism
+ Anyone can join the NULS consensus at any time, as long as they meet the conditions and follow the rules, that is, they can continue to receive NULS token rewards. The addition of POC is divided into hard indicators and soft indicators. The hard indicator means that the credit score must reach a certain standard line, and exclude some agents that have been evil. The soft index refers to the need to freeze a certain amount of NULS tokens as a margin, in order to prevent the proliferation of agents and make the whole system more fair. The number of margins can be freely selected by anyone except the minimum value. The amount of the deposit will be tied to the final reward.
+
+1.1 Yellow card penalty
+ Due to the hardware configuration of the agent or the network, the disconnection, crash, etc. during the consensus period cannot be blocked. It is not a violation, but it will affect the whole system. Therefore, the system has a mild warning mechanism for such cases. : lower the agent credit value.
+
+1.2 Red card penalty
+ For some double-split, repeated block-outs, attempts to fork the system, and malicious human-induced damage that does not comply with system rules, the NULS system is firmly resisted, and all agents can detect this kind of situation; once a malicious agent tries to challenge the system, Then the corresponding margin will be locked for 2 months, and the credit rating will never reach the consensus threshold.
+
+2、Credit Rating
+ In the NULS system, credit is the credit factor of the account in the system, and the credit of all accounts is automatically calculated by the credit rating algorithm formula in the interval [-1, 1].
+
+ Credit evaluation formula: credit base = capacity coefficient + responsibility coefficient
+ Capacity factor: calculated based on the number of historical blocks
+ Responsibility factor: Calculated according to violations and correctness of the block
+
+3、Consensus reward
+ For the balance and fairness of the entire NULS system, the consensus reward is calculated based on the margin and consensus agent credits submitted by all consensus agents. Consensus reward calculation formula: see (Figure p1)
+
+4、Subchain consensus mechanism
+ There are two types of sub-chains that access NULS. The first one is accessed through the standard interface protocol of the NULS system, and the second is deployed through the NULS program.
+
+ NULS is a common blockchain underlying infrastructure that does not run any application services on its main chain, and all application services are run by sub-chains. Through the NULS system, NULS-based sub-chains can be quickly deployed, and various operational parameters of the sub-chain can be flexibly customized, including whether to support basic tokens, encryption algorithms, consensus mechanisms, and storage mechanisms.
+
+ NULS defines a standard consensus module to provide interfaces that are compatible with different consensus mechanisms. The NULS community will develop consensus mechanisms such as POW, DPOS, POS, PBFT, and POOL verification pools for users to choose freely.
+
+Figure p1: Consensus reward calculation formula:

The above is a functional analysis of the implementation of the consensus module POC consensus mechanism. The details of each function implementation are described in the next section.
The consensus module is the core module of the blockchain. Due to the different consensus mechanisms, the services provided by the outside are not the same. The module service will describe in detail the services shared by the consensus module and the services specific to the POC mechanism.
Function Description:
Create an address that specifies the packaged block (the fast address when the consensus agent satisfies the packageable condition), the commission ratio (the commission ratio of other accounts participating in the agent consensus), and the consensus reward settlement address (the reward for the consensus agent) The consensus agent of the home address, waiting for other agents to delegate consensus, when the commissioned consensus amount reaches the standard amount, the agent can package the block to earn the reward.
+Process description
- Verify parameter correctness
+- Create a transaction
+- Determine if the account balance is sufficient
+- Verify the transaction
+- Save the transaction
+- Broadcasting transactions
+Interface definition
Interface Description
By creating a agent interface, the NULS user can initiate the creation of a agent transaction, and after the transaction is confirmed and packaged, the consensus agent can be successfully created.
+Request example
{
+ "method":"cs_createAgent",
+ "version:"1.0",
+ "params":["agentAddress","packingAddress","rewardAddress",10,20000,"password","chainId"]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | agentAddress | true | String | Request to create a agent account address |
| 1 | packingAddress | true | String | Packing block address |
| 2 | rewardAddress | false | String | Reward settlement address (default is the same as the agent address) |
| 3 | commissionRate | true | double | Commission rate |
| 4 | deposit | true | long | Create a agent's margin |
| 5 | password | false | String | password |
| 6 | chainId | true | String | chain ID |
Return example
success
{
+ "version": 1.0,
+ "code":0,
+ "msg" :"Success message",
+ "result":{
+ "value":"tx.getHash().getDigestHex()" //Generated transaction hash value
+ }
+}
+fail
{
+ "version": 1.0,
+ "code":1,
+ "msg" :"Error message",
+ "result":{
+
+ }
+}
+Return parameter description
| parameter | type | description |
|---|---|---|
| value | String | The hex string of the generated transaction hash value |
Function Description:
Create a validator for agent transactions
+Process description
- Verify that the transaction contains agent information
+- Verify that the trade creator is correct
+- agent address and package address cannot be verified
+- agent reward address and package address cannot be verified
+- Commission proportional validity verification
+- Create a agent's margin validity verification
+- Signature correctness verification
+- CoinData verification (lock time verification)
+Interface definition
Interface Description
This interface is mainly to verify the block round information, the packager, the transaction in the block and whether the CoinBase is correct, and verify whether there is a red and yellow card penalty.
+Request example
{
+ "method":"cs_createAgentValid",
+ "version:"1.0",
+ "params":["tx","chainId"]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | tx | true | String | Create serialized data for agent transactions |
| 1 | chainId | true | String | chain ID |
Return example
success
{
+ "version":"1.0",
+ "code": 0, //error code
+ "msg": "Prompt message", //Prompt message
+ "result": { //Returned business data set
+
+ }
+}
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"错误Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+Return parameter description
无
+Function Description:
Save the created consensus node information
+Process description
- Save node information to the database
+Interface definition
Interface Description
Save consensus node information to the database
+Request example
{
+ "method":"cs_createAgentCommit",
+ "version:"1.0",
+ "params":["tx","blockHeader","chainId"]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | tx | true | String | Create serialized data for agent transactions |
| 1 | blockHeader | true | String | Block header hex string |
| 2 | chainId | true | String | chain ID |
Return example
success
{
+ "version":"1.0",
+ "code": 0, //error code
+ "msg": "Prompt message", //Prompt message
+ "result": { //Returned business data set
+
+ }
+}
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+Return parameter description
nothing
+Function Description:
Delete consensus agent information
+Process description
- Delete consensus agent information
+Interface definition
Interface Description
Remove consensus agent information from the data
+Request example
{
+ "method":"cs_createAgentRollBack",
+ "version:"1.0",
+ "params":["tx","blockHeader","chainId"]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | tx | true | String | Create serialized data for agent transactions |
| 1 | blockHeader | true | String | Block header hex string |
| 2 | chainId | true | String | chain ID |
Return example
success
{
+ "version":"1.0",
+ "code": 0, //error code
+ "msg": "Prompt message", //Prompt message
+ "result": { //Returned business data set
+
+ }
+}
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+Return parameter description
nothing
+Function Description:
Log out a consensus agent created by yourself, and the consensus amount and consensus bonus of the agents participating in the consensus after unregistering the agent will be thawed after a certain time.
+Process description
- Verify parameter correctness
+- Create a transaction
+- Determine if the account balance is sufficient
+- Verify the transaction
+- Save the transaction
+- Broadcasting transactions
+Interface definition
Interface Description
By deregistering the agent interface, the NULS user can initiate a transaction to cancel the agent created by himself. After the transaction is confirmed to be packaged, the consensus agent can be successfully logged out.
+Request example
{
+ "method":"cs_stopAgent",
+ "version:"1.0",
+ "params":["address","password",chainId]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | address | true | String | Create the address of the logout agent trading account |
| 1 | password | false | String | password |
| 2 | chainId | true | String | chian ID |
Return example
success
{
+ "version":"1.0",
+ "code": 0, //error code
+ "msg": "Prompt message", //Prompt message
+ "result": { //Returned business data set
+ "value":"tx.getHash().getDigestHex()" //Generated transaction hash value
+ }
+}
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+Return parameter description
| parameter | type | description |
|---|---|---|
| value | String | The hex string of the generated transaction hash value |
Function Description:
Verify the correctness of the logout agent transaction验证注销节点交易的正确性
+Process description
- Verify that the deleted consensus agent exists and that the consensus agent has been logged out
+- Verify that the trade creator is correct
+- CoinData verification (output address must exist)
+- Query all consensus information participating in the consensus agent and the total consensus amount of the agent
+- Check whether the total amount of UTXO spent in the logout agent transaction is equal to the consensus agent entrusted amount in the database query. If not, verify the fail.
+- Verify that each UTXO unlocked in the logout agent transaction is correct
+Interface definition
Interface Description
Verify that the logout agent transaction is correct.
+Request example
{
+ "method":"cs_stopAgentValid",
+ "version:"1.0",
+ "params":["tx",chainId]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | tx | true | String | Logout serialized data for agent transactions |
| 1 | chainId | true | String | chain ID |
Return example
success
{
+ "version":"1.0",
+ "code": 0, //error code
+ "msg": "Prompt message", //Prompt message
+ "result": { //Returned business data set
+
+ }
+}
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+Return parameter description
nothing
+Function Description:
Submit logout agent data transaction
+Process description
- Set all delegate data under the consensus agent to deleted
+- Set the consensus agent data to deleted
+Interface definition
Interface Description
Log out the consensus agent and set all the delegate data and consensus agents under the consensus agent to the deleted state.
+Request example
{
+ "method":"cs_stopAgentCommit",
+ "version:"1.0",
+ "params":["tx","blockHeader","chainId"]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | tx | true | String | Create serialized data for agent transactions |
| 1 | blockHeader | true | String | Block header hex string |
| 2 | chainId | true | String | chain ID |
Return example
success
{
+ "version":"1.0",
+ "code": 0, //error code
+ "msg": "Prompt message", //Prompt message
+ "result": { //Returned business data set
+ }
+}
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+Return parameter description
nothing
+Function Description:
Logout agent transaction data rollback
+Process description
- Set all delegate data under the consensus agent to not deleted
+- Set the consensus agent data to not deleted
+Interface definition
Interface Description
Rollback logout agent transaction data
+Request example
{
+ "method":"cs_stopAgentRollback",
+ "version:"1.0",
+ "params":["tx","blockHeader","chainId"]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | tx | true | String | Logout serialized data for agent transactions |
| 1 | blockHeader | true | String | Block header hex string |
| 2 | chainId | true | String | chian ID |
Return example
success
{
+ "version":"1.0",
+ "code": 0, //error code
+ "msg": "Prompt message", //Prompt message
+ "result": { //Returned business data set
+
+ }
+}
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+Return parameter description
nothing
+Function Description:
Entrust the specified amount to the consensus agent to participate in the consensus to earn consensus rewards. The entrusted amount and consensus reward will be frozen during the consensus period.
+Process description
- Verify parameter correctness
+- Create a transaction
+- Determine if the account balance is sufficient
+- Verify the transaction
+- Save the transaction
+- Broadcasting transactions
+Interface definition
Interface Description
Through this interface, users can entrust the specified agent address to join the consensus and earn bonuses.
+Request example
{
+ "method":"cs_depositToAgent",
+ "version:"1.0",
+ "params":["address","agentHash",20000,"password","chainId"]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | address | true | String | Apply for a consensus account address |
| 1 | agentHash | true | String | Consensus agent id |
| 2 | deposit | true | long | Amount of participation in the consensus |
| 3 | password | false | String | Apply for a password for participating in the consensus account |
| 4 | chainId | true | String | chain ID |
Return example
success
{
+ "version":"1.0",
+ "code": 0, //error code
+ "msg": "Prompt message", //Prompt message
+ "result": { //Returned business data set
+ "value":"tx.getHash().getDigestHex()" //Generated transaction hash value
+ }
+}
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+Return parameter description
| parameter | type | description |
|---|---|---|
| value | String | The hex string of the transaction hash value |
Function Description:
Entrusted consensus transaction correctness verification委托共识交易正确性验证
+Process description
- Verify that the consensus agent to apply for is valid
+- Verify that the consensus agent that applied to join has reached the maximum number allowed to join the consensus
+- Verify that the entrusted amount is valid
+- Verify that the transaction was created by the account that requested the application.
+- Verify that the commission amount is equal to the output UTXO amount, and that the output UTXO lock time is correct.
+Interface definition
Interface Description
Verify the validity of the entrusted agent in the entrusted transaction, verify the correctness of the entrusted amount, verify whether the entrusted transaction creator is correct, and whether the UTXO output by the entrusted transaction is correct. Verify that the logout agent transaction is correct.
+Request example
{
+ "method":"cs_depositValid",
+ "version:"1.0",
+ "params":["tx","chainId"]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | tx | true | String | Serialized data for commissioned consensus transactions |
| 1 | chainId | true | String | chain ID |
Return example
success
{
+ "version":"1.0",
+ "code": 0, //error code
+ "msg": "Prompt message", //Prompt message
+ "result": { //Returned business data set
+
+ }
+}
+
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+Return parameter description
nothing
+Function Description:
Entrusted transaction submission
+Process description
- Save commissioned transaction information
+Interface definition
Interface Description
Save commissioned transaction data
+Request example
{
+ "method":"cs_depositCommit",
+ "version:"1.0",
+ "params":["tx",1000000,"chainId"]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | tx | true | String | Serialized data for transactions |
| 1 | height | true | long | The height of the block where the commissioned transaction is packaged |
| 2 | chainId | true | String | chain ID |
Return example
success
{
+ "version":"1.0",
+ "code": 0, //error code
+ "msg": "Prompt message", //Prompt message
+ "result": { //Returned business data set
+
+ }
+}
+
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+Return parameter description
nothing
+Function Description:
Delegate consensus transaction rollback, delete delegate consensus transaction data
+Process description
- Delete delegate consensus transaction information
+Interface definition
Interface Description
When the commissioned consensus transaction commits an error, this interface needs to be dropped to delete the delegate consensus transaction data.
+Request example
{
+ "method":"cs_depositRollback",
+ "version:"1.0",
+ "params":["tx",1000000,"chainId"]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | tx | true | String | Serialized data for commissioned consensus transactions |
| 1 | height | true | long | The height of the consigned consensus transaction is packaged |
| 2 | chainId | true | String | chain ID |
Return example
success
{
+ "version":"1.0",
+ "code": 0, //error code
+ "msg": "Prompt message", //Prompt message
+ "result": { //Returned business data set
+
+ }
+}
+
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+Return parameter description
nothing
+Function Description:
Apply for withdrawal from the consensus, after the transaction is verified, the deposit and reward will be released after the specified time.
+Process description
- Verify parameter correctness
+- Create a transaction
+- Determine if the account balance is sufficient
+- Verify the transaction
+- Save the transaction
+- Broadcasting transactions
+Interface definition
Interface Description
Apply for withdrawal from the consensus, after the transaction is verified, the deposit and reward will be released after the specified time.
+Request example
{
+ "method":"cs_withdraw",
+ "version:"1.0",
+ "params":["address","txHash","password","chainId"]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | address | true | String | Apply to withdraw from the consensus account address |
| 1 | txHash | true | String | Transaction hash when joining consensus |
| 2 | password | false | String | password |
| 3 | chainId | true | String | chain ID |
Return example
success
{
+ "version":"1.0",
+ "code": 0, //error code
+ "msg": "Prompt message", //Prompt message
+ "result": { //Returned business data set
+ "value":"tx.getHash().getDigestHex()" //Generated transaction hash value
+ }
+}
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+Return parameter description
| parameter | type | description |
|---|---|---|
| value | String | The hex string of the transaction hash value |
Function Description:
Verify that the exit consensus transaction is correct
+Process description
- Verify that the consensus to exit has been delegated before and has not exited
+- Verify that the account that created the transaction is correct
+Interface definition
Interface Description
Before exiting, verify that the account has participated in the delegate and is still in the delegate. Also verify that the transaction creator is the principal.
+Request example
{
+ "method":"cs_withdrawValid",
+ "version:"1.0",
+ "params":["tx","chainId"]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | tx | true | String | Exit serialized data for a trusted transaction |
| 1 | chainId | true | String | chain ID |
Return example
success
{
+ "version":"1.0",
+ "code": 0, //error code
+ "msg": "Prompt message", //Prompt message
+ "result": { //Returned business data set
+
+ }
+}
+
+
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+Return parameter description
nothing
+Function Description:
Exit the consensus transaction submission, save the data related to the exit consensus transaction
+Process description
- Save exit consensus transaction related data
+Interface definition
Interface Description
Save the transaction-related data by calling the interface after exiting the consensus transaction verification success
+Request example
{
+ "method":"cs_depositCommit",
+ "version:"1.0",
+ "params":["tx","blockHeader","chainId"]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | tx | true | String | Serialized data for transactions |
| 1 | blockHeader | true | String | Block header hex string |
| 2 | chainId | true | String | chain ID |
Return example
success
{
+ "version":"1.0",
+ "code": 0, //error code
+ "msg": "Prompt message", //Prompt message
+ "result": { //Returned business data set
+
+ }
+}
+
+
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+Return parameter description
nothing
+Function Description:
Exit consensus transaction data rollback
+Process description
- Rollback exit consensus transaction data
+Interface definition
Interface Description
When exiting the consensus transaction submission error, you need to call this interface to roll back the data to ensure the correctness of the data.
+Request example
{
+ "method":"cs_withdrawRollback",
+ "version:"1.0",
+ "params":["tx","blockHeader","chainId"]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | tx | true | String | Exit serialized data for a trusted transaction |
| 1 | blockHeader | true | String | Block header hex string |
| 2 | chainId | true | String | chain ID |
Return example
success
{
+ "version":"1.0",
+ "code": 0, //error code
+ "msg": "Prompt message", //Prompt message
+ "result": { //Returned business data set
+
+ }
+}
+
+
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+Return parameter description
nothing
+Function Description:
Obtain all the consensus agent lists that you have joined or the whole network, support keyword query, sort, page query
+Process description
- Verify parameter correctness
+- Get a list of consensus agents on the local primary chain
+- Filter the list of consensus agents to get a list of consensus agents that meet the criteria
+- Consensus agent list sorting
+- Pagination
+- Return to the list of consensus agents
+Interface definition
Interface Description
Obtain all the consensus agent lists that you have joined or the whole network, support keyword query, sort, page query
+Request example
{
+ "method":"cs_getAgentList",
+ "version:"1.0",
+ "params":[1,10,"address","keyword","sortType","chainId"]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | pageNumber | true | int | page number |
| 1 | pageSize | true | int | Amount of data per page |
| 2 | keyword | false | String | Keyword (agent address, packed address, agent alias, agent ID) |
| 3 | sortType | false | String | The sort type (deposit creates the lock amount of the consensus agent, the commissionRate commission ratio, the creditVal reward amount, the total amount of the total deposit consensus, the comprehensive sort of comprehensive) |
| 4 | chainId | true | String | chain ID |
Return example
success
{
+ "code": 0, //error code
+ "msg": "success", //Prompt message
+ "version":"1.0",
+ "result": { //Returned business data set
+ "pageNumber":1, //page number
+ "pageSize":10, //Amount of data per page
+ "total":100, //Total data volume
+ "pages",10, //total pages
+ "data":[
+ {
+ "agentHash":"", //agent hash
+ "agentAddress";"", //Create the address of the agent
+ "packingAddress";"", //Packed address
+ "rewardAddress";"", //Reward address
+ "deposit";, //Margin
+ "commissionRate";, //Commission rate
+ "agentName";"", //agent name
+ "agentId";"", //agent ID
+ "introduction";"", //Introduction
+ "time";, //Creation time
+ "blockHeight";, //Block height
+ "delHeight":, //Block height at which the consensus agent is deleted
+ "status":, //status
+ "creditVal":, //Reputation value
+ "totalDeposit":, //Total amount of participation in the consensus
+ "txHash":"", //Transaction hash
+ "memberCount":, //Number of people joining the agent consensus
+ "version": //version
+ },{
+
+ }
+ ]
+ }
+}
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+Return parameter description
data:
| parameter | type | description |
|---|---|---|
| pageNumber | int | page number |
| pageSize | int | Amount of data per page |
| total | int | Total data volume |
| pages | int | total pages |
| data | List | Consensus agent list |
Agent:
| parameter | type | description |
|---|---|---|
| agentHash | String | agnet hash |
| agentAddress | String | Create the address of the agent |
| packingAddress | String | Packed address |
| rewardAddress | String | Reward address |
| deposit | long | Margin |
| commissionRate | double | Commission rate |
| agentName | String | agent name |
| agentId | String | agent ID |
| introduction | String | Introduction |
| time | long | Creation time |
| blockHeight | long | Create the height of the block where the agent is trading |
| delHeight | long | Write off the height of the block where the transaction is located |
| status | int | status |
| creditVal | double | Reputation value |
| totalDeposit | long | Total commission amount |
| txHash | String | Transaction hash |
| memberCount | int | Number of orders |
| version | String | Protocol version |
Function Description:
Query detailed information of the specified consensus agent, including the creation time of the consensus agent, margin, commission ratio, agent address, package address, consensus status, credit value, commission amount, consensus number, etc.
+Process description
- Verify parameter correctness
+- Get a list of consensus agents on the local primary chain
+- Find the corresponding agent information from the list
+Interface definition
Interface Description
Query the details of the agent through the agent hash
+Request example
{
+ "method":"cs_getAgent",
+ "version:"1.0",
+ "params":["agentHash","chainId"]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | agentHash | true | String | Consensus agent id |
| 1 | chainId | true | String | chain ID |
Return example
success
{
+ "code": 0, //error code
+ "msg": "success", //Prompt message
+ "version":"1.0",
+ "result": { //Returned business data set
+ "data":{
+ "agentHash":"",
+ "agentAddress";"",
+ "packingAddress";"",
+ "rewardAddress";"",
+ "deposit";,
+ "commissionRate";,
+ "agentName";"",
+ "agentId";"",
+ "introduction";"",
+ "time";,
+ "blockHeight";,
+ "delHeight":,
+ "status":,
+ "creditVal":,
+ "totalDeposit":,
+ "txHash":"",
+ "memberCount":,
+ "version":
+ }
+ }
+}
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+Return parameter description
| parameter | type | description |
|---|---|---|
| agentHash | String | agent hash |
| agentAddress | String | Create the address of the agent |
| packingAddress | String | Packed address |
| rewardAddress | String | Reward address |
| deposit | long | Margin |
| commissionRate | double | Commission rate |
| agentName | String | agent name |
| agentId | String | agent ID |
| introduction | String | Introduction |
| time | long | Creation time |
| blockHeight | long | Create the height of the block where the agent is trading |
| delHeight | long | Write off the height of the block where the transaction is located |
| status | int | status |
| creditVal | double | Reputation value |
| totalDeposit | long | Total commission amount |
| txHash | String | tx hash |
| memberCount | int | Number of orders |
| version | String | Protocol version |
Function Description:
Obtain the penalty record (red card and yellow card penalty) obtained by the consensus agent. The user can customize the query for all penalty records or only the red card or yellow card penalty information.
+Process description
- Verify parameter correctness
+- Get the penalty based on the type of query
+Interface definition
Interface Description
Query the penalty record specifying the block address
+Request example
{
+ "method":"cs_getPunishList",
+ "version:"1.0",
+ "params":["address",0,"chainId"]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | address | true | String | Block address |
| 1 | type | true | int | Penalty type 1 yellow card, 2 red card, 0 all |
| 2 | chainId | true | String | chain ID |
Return example
success
{
+ "code": 0, //error code
+ "msg": "success", //Prompt message
+ "version":"1.0",
+ "result": { //Returned business data set
+ "pageNumber":1, //page number
+ "pageSize":10, //Amount of data per page
+ "total":100, //Total data volume
+ "pages",10, //total pages
+ "data":[
+ {
+ "type",,
+ "address","",
+ "time","",
+ "height",,
+ "roundIndex",,
+ "reasonCode",""
+ },{
+ ......
+ }
+ ]
+ }
+}
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+Return parameter description
data:
| parameter | type | description |
|---|---|---|
| pageNumber | int | page number |
| pageSize | int | Amount of data per page |
| total | int | Total data |
| pages | int | total pages |
| data | List | Penalty list data |
Punish:
| parameter | type | description |
|---|---|---|
| type | byte | Type of punishment |
| address | String | address |
| time | String | punishment time |
| height | long | Punish the height of the block |
| roundIndex | long | round |
| reasonCode | String | Reason for punishment |
Function Description:
1. Query the list of all delegation information participating in the specified address
+2. Query the delegation information of the specified consensus agent participating in the specified account
+3. Query the specified consensus agent trust list information
+Process description
- Verify parameter correctness
+- Get a list of participating consensus information on the local primary chain
+- Filter the consensus list to get the consensus list of the specified account participation or the consensus list information of the specified agent
+Interface definition
Interface Description
Obtain the consensus list information accepted by the specified account or specified by the consensus agent. When querying all the consensus lists of the specified account, the agentHash field is passed "". When all the delegated lists of the specified agent need to be queried, the address field is passed "".
+Request example
{
+ "method":"cs_getDepositList",
+ "version:"1.0",
+ "params":[1,10,"address","agentHash","chainId"]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | pageNumber | true | int | page number |
| 1 | pageSize | true | int | Amount of data per page |
| 2 | address | false | String | The account address of the participating delegation (the entrusted information of the query agent is the designated pass "") |
| 3 | agentHash | false | String | Specify the proxy agent ID (this field is passed "" when querying all account delegation information) |
| 4 | chainId | true | String | chain ID |
Return example
success
{
+ "code": 0, //error code
+ "msg": "success", //Prompt message
+ "version":"1.0",
+ "result": { //Returned business data set
+ "pageNumber":1, //page number
+ "pageSize":10, //Amount of data per page
+ "total":100, //Total data volume
+ "pages",10, //total pages
+ "data":[
+ {
+ "agentHash":"",
+ "address";"",
+ "deposit";,
+ "time";,
+ "blockHeight";,
+ "delHeight":,
+ "txHash":"",
+ "status":,
+ "agentName":"",
+ "agentAddress":""
+ },{
+
+ }
+ ]
+ }
+}
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+Return parameter description
data:
| parameter | type | description |
|---|---|---|
| pageNumber | int | page number |
| pageSize | int | Amount of data per page |
| total | int | otal data |
| pages | int | page number |
| data | List | Json string of consensus data list |
Deposit:
| parameter | type | description |
|---|---|---|
| agentHash | String | agent hash |
| address | String | Apply to join the consensus account address |
| deposit | long | Commission amount |
| time | long | Commission time |
| blockHeight | long | The height of the block where the transaction is located |
| delHeight | long | Exit the height of the commissioned exchange |
| txHash | String | tx hash |
| status | int | Consensus agent status (to be agreed, consensus) |
| agentName | String | agent name |
| agentAddress | String | agent address |
Function Description:
Query the overall information of the network consensus, including the number of agents, total mortgage, total number of participating consensus accounts, etc.
+Process description
- Get a list of network-wide consensus agents
+- Filter the list of consensus agents and wait until the list of valid consensus agents
+- Get current package round information
+- According to the current package round information, the total amount of accounts and the total amount of entrusted funds that the current network participates in the consensus
+Interface definition
Interface Description
Query the number of agents in the whole network, the total commission amount, the accounts participating in the consensus, and the number of consensus agents that meet the packaging conditions.
+Request example
{
+ "method":"cs_getWholeInfo",
+ "version:"1.0",
+ "params":["chainId"]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | String | chain ID |
Return example
success
{
+ "code": 0, //error code
+ "msg": "success", //Prompt message
+ "version":"1.0",
+ "result": { //Returned business data set
+ "data":{
+ "agentCount":,
+ "totalDeposit":,
+ "rewardOfDay":,
+ "consensusAccountNumber":,
+ "packingAgentCount":
+ }
+ }
+}
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+Return parameter description
| parameter | type | description |
|---|---|---|
| agentCount | int | Number of agents |
| totalDeposit | long | Total amount of entrusted amount |
| rewardOfDay | long | Reward amount within 24 hours |
| consensusAccountNumber | int | Number of accounts participating in the consensus |
| packingAgentCount | int | Current rounded number of consensus agents |
Function Description:
Query the consensus information of the specified account, including the number of consensus nodes created by the account and the node hash, the total amount of participation in the consensus, the number of consensus nodes participating in the account, the available balance, the consensus bonus, and the consensus bonus obtained within 24 hours.
+Process description
- Get a list of network-wide consensus nodes
+- Check if there is a consensus node created by the account in the consensus node list + - Get the current network delegate list + - Get the list of delegates participating in the account from the delegate list + - Obtain commission information for the account from the delegate list of the account
+- Interface definition
+
+- Interface Description
+
+Query the consensus information of the specified account, including the number of consensus nodes created by the account and the node hash, the total amount of participation in the consensus, the number of consensus nodes participating in the account, the available balance, the consensus bonus, and the consensus bonus obtained within 24 hours.
+```
+ Request example
{
+ "method":"cs_getInfo",
+ "version:"1.0",
+ "params":["address","chainId"]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | address | true | String | Account address |
| 1 | chainId | true | String | chain ID |
Return example
success
{
+ "code": 0, //error code
+ "msg": "success", //Prompt message
+ "version":"1.0",
+ "result": { //Returned business data set
+ "data":{
+ "agentCount":,
+ "totalDeposit":,
+ "joinAgentCount":,
+ "usableBalance":,
+ "reward":,
+ "rewardOfDay":,
+ "agentHash":""
+ }
+ }
+}
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"错误Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+Return parameter description
| parameter | type | description |
|---|---|---|
| data | Object | Consensus information |
| agentCount | int | The number of agents created by this account |
| totalDeposit | long | The total commission amount of the account |
| joinAgentCount | int | The number of consensus agents participating in the account |
| usableBalance | long | Available Balance |
| reward | long | All rewards for account participation consensus |
| rewardOfDay | long | Consensus rewards obtained within 24 hours of the account |
| agentHash | String | The hash of the agent created by the account |
Function Description:
Verify the block round information, package the person, the transaction information in the block, whether the CoinBase is correct, and verify whether there is red and yellow card transaction generation.
+Process description
- Verify fork (call block management module interface), generate red card trade with fork
+- Verify double flower (call transaction module interface), generate double card transaction with double flower and return to verify fail directly + - Generate red card trades and place red card trades in the trading pool to be packaged + - Verify block rotation information and packager correct + - Verify transaction correctness in the block (call transaction module interface) + - Verify CoinBase transactions
+- Interface definition
+
+- Interface Description
+
+This interface is mainly to verify the block round information, the packager, the transaction in the block and whether the CoinBase is correct, and verify whether there is a red and yellow card penalty.
+```
+ Request example
{
+ "method":"cs_validSmallBlock",
+ "version:"1.0",
+ "params":["SmallBlock","chainId"]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | smallBlock | true | String | SmallBlock serialization data |
| 1 | chainId | true | String | chain ID |
Return example
success
{
+ "version":"1.0",
+ "code": 0, //error code
+ "msg": "Prompt message", //Prompt message
+ "result": { //Returned business data set
+
+ }
+}
+
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+Return parameter description
nothing
+Function Description:
Consensus module transaction batch verification, verify the correctness of each transaction, verify transaction conflict
+Process description
- Cycle to verify that each transaction is correct
+- Verify that there is a conflicting transaction in the transaction list
+- Interface definition
+
+- Interface Description
+
+Loop to verify that each transaction in the incoming transaction list is correct and verify that there is a conflicting transaction in the transaction list
+```
+ Request example
{
+ "method":"cs_batchValid",
+ "version:"1.0",
+ "params":[["tx1","tx2","tx3"],"chainId"]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | tx1,tx2,tx3...... | true | String | Serialized data for transactions |
| 1 | chainId | true | String | chain id |
Return example
{
+ "version":"1.0",
+ "code": 0, //error code
+ "msg": "Prompt message", //Prompt message
+ "result": { //Returned business data set
+ "data":[
+ "tx1_hash",
+ "tx2_hash",
+ "tx3_hash"
+ ]
+ }
+}
+Return parameter description
| parameter | type | description |
|---|---|---|
| data | String | Verify the list of transactions that failed |
| tx1_hash,tx2_hash,tx3_hash..... | String | Verify the hash of the transaction that failed |
Function Description:
Query the package round information of the current network consensus node, including the consensus node of the current network in the packed state, the start end time of the current round of packaging, and the basic information of all the packed nodes in the current round.
+Process description
nothing
+Interface definition
Interface Description
Query the current network consensus node packaging round information
+Request example
{
+ "method":"cs_getRoundInfo",
+ "version:"1.0",
+ "params":["chainId"]
+}
+
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | String | chain ID |
Return example
success
{
+ "code": 0, //error code
+ "msg": "success", //Prompt message
+ "version":"1.0",
+ "result": { //Returned business data set
+ "data":{
+ "totalWeight":,
+ "index":,
+ "startTime":,
+ "endTime":,
+ "memberCount":,
+ "memberList":[
+ {
+ "agentAddress":"",
+ "packingAddress":"",
+ "agentHash":"",
+ "packingIndexOfRound":,
+ "creditVal":,
+ "packStartTime":,
+ "packEndTime":,
+ "Weight":
+ },{
+
+ }
+ ],
+ "myMember":{
+ "agentAddress":"",
+ "packingAddress":"",
+ "agentHash":"",
+ "packingIndexOfRound":,
+ "creditVal":,
+ "packStartTime":,
+ "packEndTime":,
+ "weight":
+ }
+ }
+ }
+}
+
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+
+Return parameter description
data
| parameter | type | description |
|---|---|---|
| totalWeight | double | Total weight (used to calculate consensus rewards) |
| index | long | Current round subscript |
| startTime | long | Current round start packing time |
| endTime | long | Current end of packaging time |
| memberCount | int | Current number of packaged packages |
| memberList | List | Current round packed agent packing information |
| myMember | MeetingMember | Current agent packing information |
MeetingMember
| parameter | type | description |
|---|---|---|
| agentAddress | String | agent address |
| packingAddress | String | Packed address |
| agentHash | String | agent ID |
| packingIndexOfRound | int | The consensus agent packs the subscript in the current round |
| creditVal | double | Credit value |
| packStartTime | long | Consensus agent packaging start time |
| packEndTime | long | Consensus agent packaging end time |
| weight | double | Current consensus agent weight (total commission amount * credit value) |
Function Description:
Query the current status of the specified consensus agent (consensus, packaged)
+Process description
- Query whether the agent exists
+- Query agent status
+Interface definition
Interface Description
Query the current status of the specified consensus agent
+Request example
{
+ "method":"cs_getAgentStatus",
+ "version:"1.0",
+ "params":["agentHash","chainId"]
+}
+
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | agentHash | true | String | agnet ID |
| 1 | chainId | true | String | chain ID |
Return example
success
{
+ "code": 0, //error code
+ "msg": "success", //Prompt message
+ "version":"1.0",
+ "result": { //Returned business data set
+ "data":{
+ "status":1
+ }
+ }
+}
+
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+
+Return parameter description
| parameter | type | description |
|---|---|---|
| status | int | agent status (0 consensus, 1 package) |
Function Description:
When the local agent starts, notify the consensus module to package after the block management module synchronizes the block.
+Process description
- Modify agent packing status
+Interface definition
Interface Description
Modify agent packing status
+Request example
{
+ "method":"cs_updatePackStatus",
+ "version:"1.0",
+ "params":["chainId"]
+}
+
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | String | chain ID |
Return example
success
{
+ "code": 0, //error code
+ "msg": "success", //Prompt message
+ "version":"1.0",
+ "result": { //Returned business data set
+
+ }
+}
+
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+
+Return parameter description
nothing
+Function Description:
Pause a running chain
+Process description
nothing
+Interface definition
Interface Description
Pause a running chain
+Request example
{
+ "method":"cs_stopChain",
+ "version:"1.0",
+ "params":["chainId"]
+}
+
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | String | chain ID |
Return example
success
{
+ "code": 0, //error code
+ "msg": "success", //Prompt message
+ "version":"1.0",
+ "result": { //Returned business data set
+
+ }
+}
+
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+
+Return parameter description
nothing
+Function Description:
Run a new subchain locally
+Process description
nothing
+Interface definition
Interface Description
Run a new subchain locally
+Request example
{
+ "method":"cs_runChain",
+ "version:"1.0",
+ "params":["chainId",1999,8000,12131,24274727,54646,12.5,80.5,200000,700000,2000,500000]
+}
+
+Request parameter description(待完善)
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | String | chain ID |
| 1 | packing_interval | true | long | Packing interval (unit: s) |
| 2 | packing_amount | true | long | Minimum amount of the block |
| 3 | coinbase_lockHeight | true | long | Bonus lock block number |
| 4 | redPublish_lockTime | true | long | Get red card margin lock time (unit: s) |
| 5 | stopAgent_lockTime | true | long | Logout agent margin lock time (unit: s) |
| 6 | commissionRate_min | true | double | Commission ratio minimum |
| 7 | commissionRate_max | true | double | Commission ratio maximum |
| 8 | deposit_min | true | int | Create a agent margin minimum amount |
| 9 | deposit_max | true | int | Create a agent margin maximum amount |
| 10 | commission_min | true | int | Commissioned consensus minimum amount |
| 11 | Commission_max | true | int | Maximum amount of commissioned consensus |
Return example
success
{
+ "code": 0, //error code
+ "msg": "success", //Prompt message
+ "version":"1.0",
+ "result": { //Returned business data set
+
+ }
+}
+
+
+fail
{
+ "version": 1.0,
+ "code":1, //error code
+ "msg" :"Prompt message", //Prompt message
+ "result":{
+
+ }
+}
+
+
+Return parameter description
The POC consensus mechanism is to take the agent round out of the block that participates in the consensus, reach a consensus, and jointly maintain a set of books. However, due to network reasons or some consensus agents do evil (send different packing blocks to different agents), there will be bifurcation. For this malicious agent system, different penalties will be given according to the severity, when it is a turn When the agent fails to issue the block at the specified time, the system will give the agent a yellow card penalty. The penalty will lower the credit value of the agent. When the agent credit value drops to -1, the agent will be punished with a red card; The agent will be directly punished with a red card. The agent that receives the red card penalty will stop packing and the agent will never be able to create a consensus agent again, and the margin will be frozen for a certain period of time. The other commissioned amount of the agent will be returned to the client; When a normal block is issued, the agent will receive a block reward, and the account entrusted to the agent will also receive a corresponding proportion of the bonus according to the amount of the commission.
In addition to providing packaged blocks, the consensus module will also do the statistical work of bonuses, statistics on the total amount of rewards issued within 24 hours, the amount of rewards accumulated in local accounts within 24 hours, and the details of rewards within 24 hours.
Consensus module startup process
initialization:
start up:
Package out process

Consensus reward statistics

Description: This event is released when a new zone is successfully packaged successfully.
+ event_topic : "evt_cs_packing"
+data:{
+ "chainId":88,
+ "smallBlock":"Serialize a smallBlock object into a hex string"
+}
+Description: Issue the event after the create agent transaction is confirmed and packaged into the block
+ event_topic : "evt_cs_createAgent"
+data:{
+ "chainId":88,
+ "agentList":{ //List of consensus agents created in the packaging block
+ "agent1", //Serialization of the Agent object to a hex string
+ "agent2",
+ "agent3"
+ }
+}
+Description: Issue the event after the logout agent transaction is confirmed and packaged into the block
+ event_topic : "evt_cs_stopAgent"
+data:{
+ "chainId":88,
+ "agentList":{ //List of consensus agents that are logged out in the packaging block
+ "agent1", //Serialization of the Agent object to a hex string
+ "agent2",
+ "agent3"
+ }
+}
+Description: Issue the event when the consensus agent status changes
+ event_topic : "evt_cs_agentStatusChage"
+data:{
+ "chainId":88,
+ "agentList":{ //The list of consensus agents for the table in the state of the packed block
+ "agent1", //Serialization of the Agent object to a hex string
+ "agent2",
+ "agent3"
+ }
+}
+Description: Issue the event after the delegate consensus transaction is confirmed and packaged into the block
+ event_topic : "evt_cs_deposit"
+data:{
+ "chainId":88,
+ "depositList":{ //Delegate list in the packaging block
+ "deposit1", /Deposit object serialized to a hex string
+ "deposit2"
+ }
+}
+Description: Issue the event after the exit consensus transaction is confirmed and packaged into the block
+ event_topic : "evt_cs_withdraw"
+data:{
+ "chainId":88,
+ "depositList":{ //Exit the delegation list in the packaging block
+ "deposit1", //The deposit object is serialized as a hex string
+ "deposit2"
+ }
+}
+Description: When there is a consensus agent to get a yellow card penalty is to issue the event
+ event_topic : "evt_cs_yellowPublish"
+data:{
+ "chainId":88,
+ "yellowPublishList":{ //Yellow card list in the packing block
+ "yellowPublish1", //YellowPublish object serialized to a hex string
+ "yellowPublish2"
+ }
+}
+Description: Obtain the event when there is a consensus agent to get a red card transaction
+ event_topic : "evt_cs_redPublish"
+data:{
+ "chainId":88,
+ "redPublishList":{ //Red card list in the package block
+ "redPublish1", //Serializing a RedPublish object to a hex string
+ "redPublish2"
+ }
+}
+nothing
+New area for broadcast packaging
| Length | Fields | Type | Remark |
|---|---|---|---|
| 4 | chainId | int | chain ID |
| ?? | smallBlock | String | SmallBlock object serialized hex string |
{
+ {
+ "name": "packing_interval",
+ "remark": “packaging interval”,
+ "changable": "true",
+ "default": "10秒"
+ },
+ {
+ "name": "packing_amount",
+ "remark": “minimum amount of the block”,
+ "changable": "true",
+ "default": "200000"
+ },
+ {
+ "name": "coinbase_unlock_height",
+ "remark": “Number of bonus lock blocks”,
+ "changable": "true",
+ "default": "100"
+ },
+ {
+ "name": "redPublish_lockTime",
+ "remark": “Get red card margin lock time”,
+ "changable": "true",
+ "default": "3 months"
+ },
+ {
+ "name": "stopAgent_lockTime",
+ "remark": “Logout agent margin lock time”,
+ "changable": "true",
+ "default": "3 days"
+ },
+ {
+ "name": "commissionRate_min",
+ "remark": “minimum and minimum commission ratio”,
+ "changable": "true",
+ "default": "10"
+ },
+ {
+ "name": "commissionRate_max",
+ "remark": “Maximum commission ratio”,
+ "changable": "true",
+ "default": "80"
+ },
+ {
+ "name": "deposit_min",
+ "remark": “Create the minimum margin for the agent”,
+ "changable": "true",
+ "default": "20000"
+ },
+ {
+ "name": "deposit_max",
+ "remark": “Create the maximum margin for the agent”,
+ "changable": "true",
+ "default": "700000"
+ },
+ {
+ "name": "commission_min",
+ "remark": “trust the maximum amount”,
+ "changable": "true",
+ "default": "2000"
+ },
+ {
+ "name": "commission_max",
+ "remark": “delegate the minimum amount”,
+ "changable": "true",
+ "default": "680000"
+ }
+}
+[TOC]
The Event Bus Module is a functional module designed to receive and notify processing module events, managing all module events.
Provide event subscription, receiving, sending and other functions, which is an event transfer station between modules
The event module is an edge system that provides some major asynchronous messaging, which means that even without an event bus, the system can operate normally, is lightweight, and does not depend on other module systems.



This module provides event subscriptions, event forwarding
Only rely on the core system, the core system can start, stop, modify parameters, etc. of the event module system,

Module internal work mainly includes, subscription manager, event manager, and forwarding manager.


Exception logic processing in case of event forwarding failure (such as network reason), according to the following two logics:
cmd: subscribe
{
+ "cmd": "subscribe",
+ "min_version": 1.0,
+ "params":[
+ "app.nuls.network.bandwidth",//topic event topic
+ "moduleId" //moduleId subscriber module id
+ ]
+}
+{
+ "version": 1.2,
+ "code": 0,
+ "msg": "reponse message.", // information on failure
+ "result": {
+ "app_secret": "xxxxxxxxxxxx" // app_secret, temporarily not needed, may need to be verified later if it is not required to be called locally
+ }
+}
+cmd: unsubscribe
{
+ "cmd": "unsubscribe",
+ "min_version": 1.0,
+ "params":[
+ "app.nuls.network.bandwidth", //topic event topic
+ "moduleId" //moduleId subscriber module id
+ ]
+}
+{
+ "version": 1.2,
+ "code": 0,
+ "msg": "reponse message.", // information on failure
+ "result": {
+ }
+}
+Do you keep a certain amount of time when no one is subscribed?
cmd: send
{
+ "cmd": "send",
+ "min_version": 1.0,
+ "params":[
+ "app.nuls.network.bandwidth",//topic event topic
+ "moduleId", //moduleId subscriber module id
+ {"key" : "data value"} // event to be sent, jsonObj
+ ]
+}
+{
+ "version": 1.2,
+ "code": 0,
+ "msg": "reponse message.", // information on failure
+ "result": {
+ }
+}
+I need each interface to provide an interface when subscribing to events. I can call it when I broadcast. I am using multithreading to remove your interface. You need to return the correct code, otherwise there will be a retry mechanism.
{
+ "cmd": "dispatcher",
+ "min_version": 1.0,
+ "params":[
+ {} //data event to be sent, payload
+ ]
+}
+{
+ "version": 1.2,
+ "code": 0, // must return correctly, do not need to tell you whether the business logic is wrong, as long as you receive it, tell me that you have successfully received it.
+ "msg": "reponse message.", // information on failure
+ "result": {
+ }
+}
+The functional interface is the interface provided to the interface and command line tools
cmd: topics
{
+ "cmd": "topics",
+ "min_version": 1.0,
+ "params":[]
+}
+{
+ "version": 1.2,
+ "code": 0, // must return correctly, do not need to tell you whether the business logic is wrong, as long as you receive it, tell me that you have successfully received it.
+ "msg": "reponse message.", // information on failure
+ "result": {
+ "topics":[{
+ "topic": "", //topic id
+ "createTime":"", //Create time
+ "moduleId":"", // theme creator (module) Id
+ "subscribes":[//subscriber information
+ {
+ "moduleId":"", //subscriber
+ "subscribeTime":"" //Subscription time
+ }
+ ]}
+ ]
+ }
+}
+cmd : get_topic
does not depend on any events
no
General support configuration, port, number of retries, retry time, thread pool size of default executor, network call timeout configuration, etc.
Server:
+ Ip: 127.0.0.1 // local ip, used to provide services to other modules, you can not fill, the default is automatically obtained
+ Port: 8080 //The port that provides the service, you can leave it blank, the default is automatically obtained.
+Core object class definition, storing data structures, ...
Required content not covered above
[TOC]
Usually, when a hash is computed within Satellite-chain, it is computed twice. Most of the time SHA-256 hashes are used, however RIPEMD-160 is also used when a shorter hash is desirable (for example when creating a NULS address).
Example of double-SHA-256 encoding of string "nuls":
nuls
+96cc377699e3289875d6d40da436110d692e823eb8900ae13a7107cb36c7310c (first round of sha-256)
+7e0590c37ab91aacabdac1bedec9ff6acd609215d019e489cc0a5dcf38b7b055(second round of sha-256)
+
+For NULS addresses (RIPEMD-160) this would give:
nuls
+96cc377699e3289875d6d40da436110d692e823eb8900ae13a7107cb36c7310c (first round is sha-256)
+f8e8d1c6f1511c356effad8b986b0aa439a88c44(with ripemd-160)
+Merkle trees are binary trees of hashes. Merkle trees in NULS use a double SHA-256, the SHA-256 hash of the SHA-256 hash of something.
If, when forming a row in the tree (other than the root of the tree), it would have an odd number of elements, the final double-hash is duplicated to ensure that the row has an even number of hashes.
First form the bottom row of the tree with the ordered double-SHA-256 hashes of the byte streams of the transactions in the block.
Then the row above it consists of half that number of hashes. Each entry is the double-SHA-256 of the 64-byte concatenation of the corresponding two hashes below it in the tree.
This procedure repeats recursively until we reach a row consisting of just a single double-hash. This is the Merkle root of the tree.
For example, imagine a block with three transactions a, b and c. The Merkle tree is:
d1 = dhash(a)
+d2 = dhash(b)
+d3 = dhash(c)
+d4 = dhash(c) # a, b, c are 3. that's an odd number, so we take the c twice
+
+d5 = dhash(d1 concat d2)
+d6 = dhash(d3 concat d4)
+
+d7 = dhash(d5 concat d6)
+
+where
dhash(a) = sha256(sha256(a))
+
+d7 is the Merkle root of the 3 transactions in this block.
A NULS address is in fact the hash of a ECDSA public key, computed this way:
ChainId = 2 byte,The ID of the chain in which the account belongs.
+addressType = 1 byte,The type of the account,Example: 1 general account, 2 contract account……
+pkh = 20 byte , RIPEMD-160(SHA-256(public key))
+xor = 1 byte, XOR(chainId+addressType+pkh)
+address = Base58Encode(chainId+addressType+pkh+xor)
+非nuls体系的地址格式如下:
例如:比特币地址,在地址之前追加两个字节的chainId,之后跟随比特币的原始地址,地址解析方式根据链配置决定
address = Base58Encode(chainId+原始地址长度+原始地址+xor)
+Satellite-chain uses custom messaging for communication over the TCP protocol.
The message consists of a 24-byte header and payload.
*---------------------------------------------------------------*
+| Header(24 Byte) | Payload |
+*---------------------------------------------------------------*
+The main role of the header is to indicate the payload length, verify data integrity, and solve TCP sticky packets.
| Len | Fields | Data Type | Remark |
|---|---|---|---|
| 4 | MagicNumber | uint32 | Packet valid flag |
| 12 | command | char[12] | ASCII string identifying the packet content, NULL padded |
| 4 | PayloadLength | uint32 | Length of payload in number of bytes |
| 4 | checksum | uint32 | First 4 bytes of sha256(sha256(payload)) |
[^MagicNumber]: MagicNumber In addition to being validated as a valid check, it is also used for the division of the main network and test.
Variable-length integers that can be encoded based on the values expressed to save space.
| Value | Len | Structure |
|---|---|---|
| < 0xfd | 1 | uint8 |
| <= 0xffff | 3 | 0xfd + uint16 |
| <= 0xffffffff | 5 | 0xfe + uint32 |
| > 0xffffffff | 9 | 0xff + uint64 |
A variable-length byte stream consisting of a variable-length buffer. The string is encoded in UTF8.
| Len | Fields | Data Type | Remark |
|---|---|---|---|
| ? | length | VarInt | Length of the string |
| length | value | uint8[length] | The string itself |
Variable-length buffer, consistent with the VarString implementation.
| Len | Fields | Data Type | Remark |
|---|---|---|---|
| ? | length | VarInt | Length of payload in number of bytes |
| length | data | byte[length] | payload |
6-byte number.
When a network address is needed somewhere, this structure is used.
| Len | Fields | Data type | Remark |
|---|---|---|---|
| 16 | IPv6/4 | char[16] | IPv6/4 address. Network byte order. The IPv4 address is written into the message as a 16 byte |
| 2 | port1 | uint16 | port number, network byte order |
| 2 | port2 | uint16 | port number,for cross-chain module |
| Len | Fields | Data Type | Remark |
|---|---|---|---|
| 4 | version | uint32 | version bumber |
| 32 | preHash | byte[32] | |
| 32 | merkleRoot | byte[32] | |
| ? | stateRoot | VarByte | |
| 4 | time | uint32 | second |
| 2 | txCount | uint16 | |
| ? | extends | VarByte | 本字段内容不同的链可设置不同的约束 |
| ? | signature | Varbyte |
| Len | Fields | Data Type | Remark |
|---|---|---|---|
| 2 | type | uint16 | 交易类型 |
| 4 | time | uint32 | 时间,精确到秒 |
| ? | txData | VarByte | 业务数据 |
| ? | coinData | VarByte | 资产数据 |
| ? | remark | VarString | 备注 |
| ? | sig | VarByte | 只包含签名,不包含pubkey |
交易特性
多账户转出
+多账户转入
+多资产转账
+coinData结构
froms://List<CoinForm>格式,
+tos://List<CoinTo>格式
+CoinForm结构[40]
address: //byte[24] 账户地址
+assetsChainId://uint16 资产发行链的id
+assetsId: //uint16 资产id
+amount: //uint128,转出数量
+nonce : //byte[8] 交易顺序号,前一笔交易的hash的前8个字节
+locked : //byte 是否是锁定状态(locktime:-1),1代表锁定,0代表非锁定
+CoinTo结构[44]
address: //byte[24],目标地址
+assetsChainId://uint16 资产发行链的id
+assetsId: //uint16 资产id
+amount : //uint128,转账金额
+lockTime://uint32,解锁高度或解锁时间,-1为永久锁定
+手续费
forms-tos剩余的部分就是手续费(模型中支持多种资产缴纳手续费,约束条件由经济模型设计决定)
+参考各个模块
NULS2.0是一个开放的不限制语言的区块链底层平台,本文只参考区块链核心业务模块的情况,编写Java环境搭建流程。
1 环境准备
2 clone源代码
git clone git@github.com:nuls-io/nuls_2.0.git
3 IDEA导入nuls_2.0中所有maven项目
4 建立自己的maven项目
5 运行所有需要启动的模块
NULS是一个全球开源的区块链底层基础设施,让区块链更简单是NULS的使命,本文将描述如何使用NULS核心模块,快速搭建一条基础区块链。
NULS并不限制区块链的属性,使用NULS底层可以搭建私链、联盟链、公有链,可以搭建有币区块链,也可以搭建无币区块链。

NULS 2.0基于微服务架构搭建,内置了区块链核心业务模块,包括账户、交易、区块、共识等,当我们要基于NULS 2.0搭建基础区块链时,我们将基于NULS 2.0区块链通用基础功能层进行扩展。
因为NULS2.0中已经包含了区块链的基础功能,在开发自己的区块链时,只需要整理自己独有的业务功能,抽象出对应的协议,将功能开发为一个模块插入到NULS2.0中即可。举个例子:假设我们要实现一条“记事本链”,在NULS的基础上我们需要设计“记事本”的业务交易,比如记事交易、删除记事交易,我们的业务模块需要做的是,在本模块中添加业务逻辑代码,并实现两个交易的验证、处理、回滚功能,然后将交易信息上报给交易管理模块,处理交易相关逻辑。
理解了如何进行区块链功能拓展,就可以根据下面的步骤,详细设计自己的功能模块了。
一条区块链要运行起来,需要非常多的基础配置,每条区块链都要有自己的配置参数,在搭建一条新的区块链时,第一件事就是配置自己的运行参数。
NULS2.0的启动脚本支持传入配置文件的方式启动区块链,使用方式如下:sh start.sh -c modules.ncf
modules.ncf内可以配置各个模块的参数,开发者可以根据自己的链的情况自行修改运行参数,具体运行参数预设如下:
| section | param | name | remark |
|---|---|---|---|
| common | chain.id | 本链id | Uint16,NULS主网为1,测试网为2 |
| common | address.prefix | 地址前缀 | 大小字母+数字,2-5个字符 |
| common | data.root.dir | 数据存储路径 | 为了所有模块都存储在同一个目录,如有需要可以在任意模块内配置特殊的路径 |
| common | encoding | 编码方式 | 默认UTF-8,不建议修改 |
| common | asset.id | 本来主资产编码 | NULS为1 |
| common | log.root.dir | 日志根目录 | 用于存放各个模块的日志文件 |
| common | log.level | 日志级别 | 日志打印级别debug/info/warn/error. |
| block | data.folder | data子文件夹 | 用于存储block模块数据,该文件夹放在#{data.root.dir}下 |
| block | block.max.size | 区块最大size | 区块大小限制,避免太大区块太高参与门槛 |
| block | block.interval | 出块间隔 | |
| block | max.rollback | 最大回滚数量 | 当超过这个数量后,系统将停止回滚,避免出现重大问题 |
| block | header.extend.max.size | 扩展最大size | 区块头中的扩展字段的大小限制 |
| block | genesis.block.json.path | 创世块描述文件 | 创世块的描述文件 |
| consensus | data.folder | data子文件夹 | 用于存储共识模块数据,该文件夹放在#{data.root.dir}下 |
| consensus | packing.interval | 出块间隔 | |
| consensus | inflation.token.count | 每年增发数量 | 增发数量用于通过coinbase交易奖励给节点 |
| consensus | block.max.size | 区块最大size | |
| consensus | seed.addresses | 共识种子地址 | 多个地址用","分隔 |
| consensus | packing.address.pwd | 地址密码 | 用于打包的地址的密码 |
| consensus | agent.deposit.min | 创建节点时最小保证金数量 | |
| consensus | agent.deposit.max | 创建节点时最大保证金数量 | |
| consensus | commission.rate.max | 佣金比例最大值,不能大于100 | |
| consensus | commission.rate.min | 佣金比例最小值 | |
| consensus | deposit.min | 单笔委托最小金额 | |
| consensus | agent.total.deposit.max | 节点接受委托的最大金额 | |
| consensus | packing.token.min | 当节点的委托达到该值则开始出块 | |
| consensus | red.punish.lock.time | 红牌锁定时间 | |
| consensus | agent.stop.lock.time | 停止节点锁定时间 | |
| network | data.folder | data子文件夹 | |
| network | seeds | 种子节点,多个之间用","隔开 | |
| network | magic.number | 魔法数字,用于隔离其他网络 | |
| network | port | 端口 | |
| network | nuls.seed | 需要进行跨链时,配置NULS2.0种子节点 | |
| network | cross.listener.port | ||
| network | nuls.magic.number | ||
| contract | nrc20.file.path | NRC20协议描述json文件路径 | |
| tx | data.folder | data子文件夹 | |
| Ledger | data.folder | data子文件夹 | |
| api | mongodb.ip | mongodb地址 | |
| api | mongodb.port | mongodb端口 | |
| api | rpc.listener.ips | rpc监听ip | 可以配置多个 |
| api | rpc.port | rpc监听端口 | |
| api | req.allow.per.s | 并发限制 |
表格中列出的是可能比较常用的配置项,并不是全部,在经过alpha版本和beta版本后,团队会整理所有NULS2.0的可用配置清单,用于广大区块链开发者配置自己的区块链。
链的配置项修改完成后,则可直接参考本文档的第4部分:打包和启动
在使用NULS2.0的模块化基础设施搭建了自己的区块链之后,想要实现自己的独特业务,就需要自己开发一个业务模块,整合到基础链中。下面的内容可以对如何开发一个自己的业务模块做一些指导。
基于区块链底层进行扩展的带有自定义业务的功能模块,该模块可以是遵循NULS2.0模块协议、可以与其他模块通信的微服务模块,也可以是一个独立的、只通过RPC接口与基础模块通信的外部应用。
业务模块不进行协议的增加和修改,只对基础协议进行扩展,通过协议的扩展,实现自身业务。
NULS提供了两种方式可以对协议进行扩展,两种方式比较类似,具体方式如下:
将想要上链的数据,序列化为字节数组,放入转账交易的remark字段。在字节数组的最前面放置自己的魔法数字,用于区别其他的转账交易。在自己的应用中监听所有区块中的转账交易,当发现以自己的魔法数字开头的remark时,进行解析和业务处理。
NULS为业务扩展提供了特定的交易类型,该交易可以自由填写txData,将想要上链的数据,序列化为字节数组,放入转账交易的txData中。在字节数组的最前面放置自己的魔法数字,用于区别不关心的交易。在自己的应用中监听所有区块中的业务扩展交易,当发现以自己的模块数字开头的txData,进行解析和业务处理。
示例:
假设现在要实现一个应用,该应用的业务是:私密记事本,核心业务就是每个地址可以将加密后的记事文本存储到区块链上,在任意时候可以解密查看。
1 功能设计
1. 新增记事:对记事内容进行加密,将加密后的数据发送到链上;
+
+2. 解析区块数据提取记事数据:从区块链上获取本应用的数据,并将数据存储到本地数据库;
+
+3. 解密查看:从数据库中获取记录,解密,展示解密结果
+
+4. 删除记事:app本地删除,不删除区块链中数据
+2 区块链交互
以上功能设计需要和区块链进行交互的就是1新增记事和2解析区块数据提取记事数据。
首先设计数据格式,如下
+
+{
+
+ address:"",//记事所属人
+
+ time:"",//记事时间点
+
+ content:""//加密后的记事内容
+
+}
+
+根据数据格式,组装上链数据:address+time+content;
+
+确定应用的魔法数字,假设为12345678.
+
+则组装DataTransaction(业务扩展交易),将txData的值设置为12345678、address、time、content的拼接字节数组,支付足够的手续费后,对交易进行签名,将交易广播到网络中。
+监听所有的区块,发现'业务扩展交易'则进行解析,首先解析到txData时,先判断是否是已12345678开始的,
+如果不是则丢弃该交易,如果是则继续解析,判断是否成功获取了address+time+content(避免魔法数字重复导致数据混乱)
+如果成功解析了数据,则将数据存储到本地数据库中
+3 其他业务实现
所有不需要与区块链交互的业务,就可以通过常规的应用方式进行设计了,这样一个简单的区块链应用就完成了。
使用业务扩展的方式开发应用,是一个简单快捷高效的方式,NULS对业务扩展的支持是充分而友好的,希望越来越多的人加入到NULS生态建设中来。
在动手开发模块之前,首先要确定几个问题:
在确定了自己的需求后,需要对自己的模块进行设计。模块设计依存于NULS2.0的整体设计,在设计自己的模块时,可以着重设计自己的业务,其他部分依照基础模块实现。
那么如何设计自己的业务?举例说明:
第Ⅰ种情况:我们的需求只是需要将一些关键信息存储上链,没有复杂的逻辑处理。
+比如我们只是想存储一份合同的相关信息在链上,且能够在链上随时查询到。这个时候实际上我们是没有必要去开发任何模块的。nuls2.0提供了一种专门用于存储数据的交易(DataTransaction),用户只需要将数据转换成字节数组存放在交易的txData字段或者remark字段中,广播交易到全网后,数据即可成功上链。再通过nuls2.0提供的查询交易接口,就能随时查询到交易和交易的相关数据。这样其他的业务功能可以以通用软件的方式进行设计和开发。
+
+第Ⅱ种情况:我们的需求需要将一些关键信息存储上链,并且需要有简单逻辑处理。
+一般这种情况,我们会推荐用户考虑使用智能合约做DAPP的开发,例如做简单的竞猜类游戏等。
+如果我们的需求比较复杂,且有相关的逻辑流程处理,必须要通过添加新的协议来完成。
+这里我们就用nuls的poc共识机制来举例
+功能设计:先根据需求整理要提供的功能,根据功能设计新的协议。
+nuls的poc共识机制的业务功能有:
+1. 用户可以通过发送申请共识节点的交易,锁定2-20万的nuls来新建共识节点,待节点满足出块条件后,可参与打包出块,获得出块奖励。
+2. 用户可以通过发送加入委托共识的交易,至少锁定2000个nuls来参与共识,获得出块奖励。
+3. 用户可以通过发送取消委托共识的交易解锁委托共识时锁定的nuls,取消委托后,不再继续得到奖励。
+4. 用户可以通过发送交易让节点退出共识,退出后委托在节点上的所有nuls都会解锁,节点不再参与出块。
+
+协议设计:包括协议的序列化和反序列化、交易验证器、交易确认处理器、交易回滚处理器,需要注意和基础协议避免冲突。
+poc共识机制的4个协议:创建共识节点交易、委托交易、取消委托交易、节点退出共识交易
+交易验证器:每个协议都会有相关的业务验证器,在节点收到新的交易或者在收到新的区块时,便会执行验证器,验证失败的交易直接拒绝。
+例如创建共识节点:
+ 1)创建节点的账户不能重复多次创建共识节点;
+ 2)保证金在2-20万nuls之间;
+ 3)账户是否有过红牌记录;
+存储设计:将协议中的业务数据,存储为格式化数据,用于提供用户功能。
+例如创建共识节点后,底层会存储创建节点的交易数据,还会存储节点的相关信息,例如共识节点名称,共识节点当前的委托总量,共识节点的信用值等
+
+接口设计:需要对外提供的RPC接口
+例如:查询共识节点信息,查询共识委托信息等
+
+其他:其他的内部处理机制则根据不同的业务需求,在模块自己内部实现,例如poc共识的核心处理都在ConsensusProcess里
+本方式与方式二区别只在于涉及对基础链的修改,在修改时需要先对基础链的业务进行充分的理解,对自己的业务进行适配后需要进行充分的测试。
+修改的方法可以是替换模块的方式:获取基础链模块的源代码,对其进行修改,然后发布自己的模块替换原始的基础模块。
+首先模块由下面两部分组成,对于第一部分,目前官方只提供了Java版本的lib,后续会陆续提供C++,Go等其他语言版本。
1、nuls-service-base-lib(baselib):
通用的、所有模块中功能都一样的依赖包,提供基础的通信、接口格式、通用代码等内容,如果开发者使用未提供baselib的语言,则需要自己开发baselib。
2、module-self:
模块本身,在一下几方面需要做出自己的实现:
模块管理
1、启动、停止脚本:在自己的模块中,提供模块的启动和停止脚本,并且保证任何时机执行启动和停止脚本不会对业务和数据造成重大影响。
2、启动后进行状态管理,首先通过启动参数连接到Nulstar(微服务管理器),上报自己模块的信息,同时获取到依赖模块的信息,尝试与依赖模块通信,在此期间完成自己模块的初始化,并变更自己模块的状态。在依赖的所有模块都ready后,开始运行自己模块的业务。
3、当依赖的模块状态变更后,本模块要根据变更的状态进行处理
协议相关
当模块中创建了新的交易后,需要在每次模块启动时向交易管理模块注册自己的协议信息,同时上报交易的验证器、确认处理器、回滚处理器信息。
网络消息
当新模块增加了网络协议后,需要向网络模块订阅自己需要的网络的消息,让网络模块接到消息后可以把消息发送到模块的消息处理器中。
数据存储
NULS2.0不对数据存储做任何限制,可以根据自己的业务需要自由的设计、实现自己的数据存储功能。
功能实现
如果有其他功能需要实现,可以按照自己的习惯或者行业的标准规范进行开发,NULS2.0不做任何限制。
功能接口
根据产品设计进行功能接口的实现,NULS2.0底层会提供统一的接口调用方式,会支持JSONRPC2.0/restFul/CMD/WebSocket等访问方式。
日志记录
NULS2.0原则上不对扩展模块的日志记录方式进行限制,但建议参考基础链的方式将所有日志归集到一个根目录中,便于备份和查看。
总结:业务模块的扩展可以参考底层基础链,所有的模块在NULS2.0的架构中都是平等的,遇到不清楚的地方可以通过查看基础模块代码的方式借鉴或者复制基础模块的解决方式,后续会陆续开源一些项目的扩展模块,让广大开发者借鉴,使开发模块变得越来越简单。
设计协议的原则:数据精简,不要再协议中增加冗余数据,尽可能减小数据大小。
网络消息: 消息格式,序列化方法、反序列化方法,计算数据大小方法、订阅接口和逻辑处理器。
交易:交易格式,序列化方法、反序列化方法,计算数据大小方法、验证器、处理器、回滚处理器等。
完成了设计和开发工作后,不可避免的要进行测试,本部分内容不包含开发过程中的单元测试部分,这里只讲解集成测试的方法和注意事项。
1、首先通过NULSTAR启动所有模块,查看自己的新增模块是否可以正常启动和停止;
+
+2、测试新增模块的交易是否可以发送,各种接口是否可以正常调用;
+
+3、主网测试,是否可以正常打包区块,新增交易是否可以被确认、回滚;
+
+4、检查交易验证逻辑是否严谨,不要出现安全漏洞;
+
+5、测试自身模块的业务是否正确、完整。
+全部测试都完成后,便可进入打包和启动阶段了
NULS2.0有自己的代码打包机制,因为涉及不同语言和不同开发环境,我们制定了一套独有的打包规范,请确保新开发模块遵循打包规范,已经提供了规范中要求的依赖、脚本等组件,并对打包流程进行测试
cd /home/nuls2/nuls_2.0
+./package.sh -m
+确认没有问题后,完成区块链的开发工作,可以将打包后的程序包交给相关方进行公开测试,在测试一段时间后没有发现问题,就可以正式组件区块链网络,开始自己的业务。
/home/nuls2/nuls_2.0/RELEASE/bin
+cd /home/nuls2/nuls_2.0/RELEASE/bin
+./start.sh -c ./moudle.json(指定moudle.json配置文件启动)
+ ./start.sh --jre $JAVA_HOME --managerurl 192.168.1.124:8887/ws
+./checkstatus.sh
+kill 进程号(进程号对应jps显示出来的 mykernel 模块的进程)
+{
+ "cmd": "nuls_accounts",
+ "params": ["param1", "param2"],
+ "min_version": 1.0,
+}
+| parameter | required | type | description |
|---|---|---|---|
| cmd | true | string | The command to call |
| params | true | array | parameters |
| min_version | false | float | The minimum version of the interface to call |
{
+ "code":0,
+ "msg": "Success",
+ "result": {}
+}
+| parameter | required | type | description |
|---|---|---|---|
| code | ture | int | The result status of the request, 0 means success. Otherwise return an error code |
| msg | true | string | User-friendly request execution result description |
| result | true | object | Method return value |
| Code | Possible Return message | Description |
|---|---|---|
| 0 | Success | Operation success |
| 1 | Parse error | Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text. |
| 2 | Invalid Request | The JSON sent is not a valid Request object. |
| 3 | Method not found | The method does not exist / is not available. |
| 4 | Invalid params | Invalid method parameter(s). |
| 5 | Internal error | Internal JSON-RPC error. |
| 6 | Unauthorized | Should be used when some action is not authorized, e.g. sending from a locked account. |
| 7 | Action not allowed | Should be used when some action is not allowed, e.g. preventing an action, while another depending action is processing on, like sending again when a confirmation popup is shown to the user (?). |
| 8 | Timeout | Should be used when an action timedout. |
| 9 | Conflict | Should be used when an action conflicts with another (ongoing?) action. |
| 10 | Execution error | Will contain a subset of custom errors in the data field. See below. |
| 11 to 100 | Server error | Reserved for implementation-defined server-errors. |
Custom error 10 can contain custom error(s) to further explain what went wrong.
{
+ code: 10,
+ msg: 'Execution error',
+}
+[TOC]
The ledger module is the data hub of the blockchain. The balances and transactions of all accounts are saved in the ledger module. + A network-wide account ledger is saved on each network node to ensure complete, open and transparent data, while ensuring that data cannot be tampered and traceable.
Provide data support for assembly transactions, mainly accounting and auditing, verify the legality of the transaction, such as: whether there is sufficient balance, whether to repeat payment (double flower)
The ledger module is the data hub, which stores the result data of all existing transactions in the system. It does not depend on any business modules, and other modules depend on it as needed.
The core of the Ledger is assets management and ledger management.



The RPC interface call provided by the ledger module. For detailed interface, please refer to the interface design section.
Only rely on the core system, the core system can start, stop, modify parameters, etc. of the event module system,
Module internal work mainly includes asset management, obtaining account address balance and nonce, and verifying transaction coinData.
A cold wallet is an unconnected wallet, also called an offline wallet. A hot wallet is a wallet that keeps online, that is, an online wallet. Cold wallets are not more secure than hot wallets.
Since the cold wallet only signs the transaction information, the signed hex string is transmitted to the server through the hot wallet, and then the server performs unified transaction processing, so the client needs to perform the offline signature function. +The offline transaction system maintains the storage information of the nonce. After using a nonce, the nonce is saved in the business system.


cmd: getBalance
| Field | Required or not | type | desc |
|---|---|---|---|
| chainId | Y | int | Chain id of the interface call chain |
| address | Y | String | The address to check the balance |
| assetChainId | Y | int | Asset-initiated chain ID |
| assetId | Y | int | Asset ID |
{
+
+ "chainId":5,
+ "address":"0x407d73d8a49eeb85d32cf465507dd71d507100c1",
+ "assetChainId":34,
+ "assetId":5,
+}
+{
+ "available": "10000000000",
+ "freeze": "200000000",
+ "total": "12000000000"
+}
+remarks: 1NULS=10^8Na
| Field | type | DESC |
|---|---|---|
| available | BigInteger | Available Balance |
| freeze | BigInteger | freeze |
| total | BigInteger | total = available+freeze |
cmd: getNonce
| Field | Required or not | type | desc |
|---|---|---|---|
| chainId | Y | int | Chain id of the interface call chain |
| address | Y | String | The address to check the balance |
| assetChainId | Y | String | Asset-initiated chain ID |
| assetId | Y | int | Asset ID |
{
+
+ "chainId":5,
+ "address":"0x407d73d8a49eeb85d32cf465507dd71d507100c1",
+ "assetChainId":34,
+ "assetId":5,
+}
+{
+ "nonce":"xxxxxxxxxxx",
+ "nonceType":1
+}
+| Field | Type | Desc |
|---|---|---|
| nonce | String | Spending transaction hash |
| nonceType | int | 1The last transaction has been confirmed, 0 the transaction has not been confirmed |
cmd: getBalanceNonce
| Field | Required or not | type | desc |
|---|---|---|---|
| chainId | Y | int | Chain id of the interface call chain |
| address | Y | String | The address to check the balance |
| assetChainId | Y | String | Asset-initiated chain ID |
| assetId | Y | int | Asset ID |
{
+
+ "chainId":5,
+ "address":"0x407d73d8a49eeb85d32cf465507dd71d507100c1",
+ "assetChainId":"34",
+ "assetId":"5",
+}
+{
+ "available": "10000000000",
+ "nonce": "xxxxx"
+}
+| Field | Type | Desc |
|---|---|---|
| available | BigInteger | User available balance |
| nonce | String | A random value of the account that holds the hash of the user's last transaction. |
cmd: validateCoinData
| Field | Required or not | Type | desc |
|---|---|---|---|
| chainId | Y | int | Chain id of the interface call chain |
| txHex | Y | String | Transaction hex stream |
{
+ "chainId": 458,
+ "txHex": "xxxxxxxx"
+}
+{
+ "validateCode":1,
+ "validateDesc":"success"
+}
+| Field | Type | Desc |
|---|---|---|
| validateCode | int | 1 check pass, 2 orphan trade 3 double flower 4 other abnormalities |
| validateDesc | String | Check return description |
cmd: commitUnconfirmedTx
| Field | Required or not | Type | desc |
|---|---|---|---|
| chainId | Y | int | Chain id of the interface call chain |
| txHex | Y | String | Transaction hex stream |
{
+ "chainId": 21,
+ "txHex": "xxxxxxxx"
+}
+{
+ "value":1
+}
+| Field | Type | Desc |
|---|---|---|
| value | int | 1 submission passed, 0 submission failed |
cmd: bathValidateBegin
| Field | Required or not | Type | desc |
|---|---|---|---|
| chainId | Y | int | 接口调用链的链Id |
{
+ "chainId": 21
+}
+{
+ "value":1
+}
+| Field | Type | Desc |
|---|---|---|
| result | int | 1成功,0失败 |
cmd: bathValidatePerTx
| Field | Required or not | Type | Desc |
|---|---|---|---|
| chainId | Y | int | Chain id of the interface call chain |
| txHex | Y | String | Transaction hex stream |
{
+ "chainId": 21,
+ "txHex": "xxxxxxxx"
+}
+{
+ "result":1
+}
+| Field | Type | Desc |
|---|---|---|
| result | int | 1 success, 0 failed |
cmd: commitConfirmTx
| Field | Required or not | Type | Desc |
|---|---|---|---|
| chainId | Y | int | Chain id of the interface call chain |
| txHex | Y | String | Transaction hex stream |
{
+ "chainId": 21,
+ "txHex": "xxxxxxxx"
+}
+{
+ "value":1
+}
+| Field | Type | Desc |
|---|---|---|
| result | int | 1Success,0 failed |
cmd: rollBackConfirmTx
| Field | Required or not | Type | desc |
|---|---|---|---|
| chainId | Y | int | Chain id of the interface call chain |
| txHex | Y | String | Transaction hex stream |
{
+ "chainId": 21,
+ "txHex": "xxxxxxxx"
+}
+{
+ "value":1
+}
+| Field | Type | Desc |
|---|---|---|
| result | int | 1Success,0 failed |
cmd: getAsset
| Field | Required or not | type | desc |
|---|---|---|---|
| chainId | Y | int | Chain id of the interface call chain |
| assetChainId | Y | String | Asset-initiated chain ID |
| assetId | Y | int | Asset ID |
{
+ "chainId": 5,
+ "assetChainId": 12,
+ "assetId": 41
+}
+{
+ "chainId": 5,
+ "assetChainId": 12,
+ "assetId": 41,
+ "balance" : {
+ "available": "10000000000",
+ "freeze": "200000000",
+ "total": "12000000000"
+ }
+}
+| Field | Type | Desc |
|---|---|---|
| chainId | int | The chain ID of the initiating call |
| assetChainId | int | Asset-initiated chain id |
| assetId | int | Asset ID |
| balance.available | BigInteger | Available Balance |
| balance.freeze | BigInteger | Freeze balance |
| balance.total | BigInteger | total = available+freeze |
does not depend on any events
NA
Core object class definition, storing data structures, ...
+This section is a guide for the use of the full node wallet for Linux version of the NULS2.0-alpha test network. We suppose you have basic operation capability of Linux system. This paper introduces how to use NULS wallet to create accounts, import accounts, transfer, and create nodes or stake, etc. in the Linux system. We recommend users to use the Linux system server to create stable NULS nodes.
| Versions | Date | Contents |
|---|---|---|
| V1.0.0 | 2018-03-18 | alpha |
The server for NULS node should be not lower than the following configuration:
| CPU | Memory | Disk space | Bandwidth |
|---|---|---|---|
| 4-Core 3.0 GHz | 16GB | 128GB | 20Mbps uplink |
Recommended configuration:
| CPU | Memory | Disk space | Bandwidth |
|---|---|---|---|
| 8-core 3.0 GHz | 32GB | 256GB | 100Mbps uplink |
Linux system
The Linux kernel version is recommended to use 2.6.32 and above
To download v2.0.0-alpha-1 wallet via Linux system, you can type the following command:
$wget https://media.githubusercontent.com/media/nuls-io/nuls-wallet-release/master/NULS-Wallet-linux64-1.0.0.tar.gz
+Note: the download address may be different if there are subsequent versions.
$ tar -zxf NULS-Wallet-linux64-2.0.0-alpha-1.tar.gz
+ $ cd NULS-Wallet-linux64-2.0.0-alpha-1
+ $ ./start.sh
+Enter the cmdclient/1.0.0 directory and execute the following command:
$ cd cmdclient/1.0.0
+ $ ./cmd.sh
+At this point, you can see the input prompt nuls>>>, now you can directly type NULS wallet command to operate.
+For example, to create an account you can do like this:
nuls>>> create
+ Please enter the password (password is between 8 and 20 inclusive of numbers and letters), If you do not want to set a password, return directly.
+ Enter your password:*********
+ Please confirm new password:*********
+ [ "Nse9EtaRwgVgN42pxURgZjUR33LUx1j1" ]
+ nuls>>>
+Command create means to create a single account, next enter your password, and once again confirm the new password. If successful, the address of the account will be returned.
Print all valid commands,
| Parameter | Description |
|---|---|
| -a | format the printed command, optional |
| command | view instructions for the specific command |
| group | view all instructions for the commands in the specific command group |
Return: help
getaccount <address> --get account information
+Return: help-a
getaccount <address> --get account information
+ OPTIONS:
+ <address> the account address - Required
+Example
nuls>>> help
+nuls>>> help -a
+nuls>>> help account
+nuls>>> help create
+Create an account and return the set of account addresses
| Parameter | Description |
|---|---|
| [number] the number of accounts you want to create, optional |
When creating an account, you are required to enter the password for the account. The password must be set to ensure the security of the assets.
Return: accounts set
[ "5MR_2CkDZtZRHGLD43JreUc8LsFBertsc9r", "5MR_2CXCCU89fj9RyQj9MgZVE7Pq3Mmk77p" ]
+Example
Create a single account
nuls>>> create
+Please enter the new password(8-20 characters, the combination of letters and numbers).
+Enter your new password:**********
+Please confirm new password:**********
+[ "5MR_2CetN1KeWAVsaUsqD7JwMBwjGuRGpGW" ]
+Create multiple accounts at once
nuls>>> create 3
+Please enter the new password(8-20 characters, the combination of letters and numbers).
+Enter your new password:**********
+Please confirm new password:**********
+["5MR_2CWdfU2VDERgQbWS1quGYAGD1iDDM4N", "5MR_2CcYq7fqrvKagReBmzG3qEz8qGkifCr", "5MR_2Cd6E2vAGZQxkqeXbeqThRxDGTFiLei" ]
+To back up an account, a file named as account address with the extension .keystore is generated, which is the backup file for the account
| Parameter | Description |
|---|---|
| <address> | account address, required |
| [path] | the directory where the generated backup file is included, current directory by default, optional |
Return
The path to the backup file is /nuls/bin/NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy.keystore
+Example: backup an account with password
shell
+nuls>>> backup 5MR_2CetN1KeWAVsaUsqD7JwMBwjGuRGpGW /Users/zlj
+Enter account password
+***************
+The path to the backup file is /Users/zlj/5MR_2CetN1KeWAVsaUsqD7JwMBwjGuRGpGW.keystore
+ Enter the password to remove a local account based on the account address
| Parameter | Description |
|---|---|
| <address> | account address, required |
Return
Success
+Example
nuls>>> remove 5MR_2CetN1KeWAVsaUsqD7JwMBwjGuRGpGW
+Enter your password for account**********
+Success
+Set a new password according to the account address and password.
| Parameter | Description |
|---|---|
| <address> | account address, required |
Return
Success
+Example
nuls>>> resetpwd 5MR_2CWdfU2VDERgQbWS1quGYAGD1iDDM4N
+Enter your old password:**********
+Enter new password**********
+Please confirm new password:**********
+Success
+Set an alias to the account. If a node is created with this account, its alias will be displayed as the node source
| Parameter | Description |
|---|---|
| <address> | account address, required |
| <alias> | alias name, required |
Return: transaction hash
txHash:0020f94f36aefd59f9cca9bff3c018fc287dc6c0bcd7fbeb047133cadb5747e7d98d"
+Example
nuls>>> setalias 5MR_2CXrzwoCoP4vnUxHJ5gdUUXZJhCpjq9 zlj
+Enter your account password**********
+txHash:0020830971e02527f18f8f9e32f974d8c73ce6bd249de859cae170476b87d0ec9582
+Import the account keystore file to generate a local account. The operation is not accessible if the local account already exists locally.
| Parameter | Description |
|---|---|
| <path> | path of the keystore file to be imported, required |
Note: the original password is required to import the keystore file to generate the account
Return: address of the imported account
"NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy"
+Example
nuls>>>importkeystore /Users/zhoulijun/5MR_2CetN1KeWAVsaUsqD7JwMBwjGuRGpGW.keystore
+Please enter the password (password is between 8 and 20 inclusive of numbers and letters), If you do not want to set a password, return directly.
+Enter your password:**********
+5MR_2CetN1KeWAVsaUsqD7JwMBwjGuRGpGW
+Import the account private key to generate a local account, overwritten if the local account already exists. You are required to set a password for the account when importing. This function can be used to retrieve the account through the private key if you forget the account password.
| Parameter | Description |
|---|---|
| <privatekey> | account's private key, required |
"NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy"
+Example
nuls>>> import 1c2b9fd4417c1aad8ae9f24c982ff294eb50a6462b873b79a879e805a9990346
+Please enter the password (password is between 8 and 20 inclusive of numbers and letters), If you do not want to set a password, return directly.
+Enter your password:**********
+Please confirm new password:**********
+5MR_2CeG11nRqx7nGNeh8hTXADibqfSYeNu
+Query account information with the account address
| Parameter | Description |
|---|---|
| <address> | account address, required |
Return
{
+ "encryptedPrikeyHex" : "724d68268849f3680d480c9257f33229c0fac88890d5355c0e4d9c457af5c6e8b8f9f7ca9fd52fbd8079fbce1782052d", // the encrypted private key
+ "alias" : "zlj", // alias
+ "baglance" : {
+ "freeze" : 0, // frozen assets
+ "total" : 997999999800000, // total assets
+ "available" : 997999999800000 // usable assets
+ },
+ "address" : "5MR_2CeG11nRqx7nGNeh8hTXADibqfSYeNu", // account address
+ "pubkeyHex" : "0211c45f28710cd26a2c45fb790895a0ff2e095a290f1825b31d80ebc30913c486" //public key
+}
+Example
nuls>>> getaccount 5MR_2CeG11nRqx7nGNeh8hTXADibqfSYeNu
+{
+ "encryptedPrikeyHex" : "724d68268849f3680d480c9257f33229c0fac88890d5355c0e4d9c457af5c6e8b8f9f7ca9fd52fbd8079fbce1782052d", //encrypted private key
+ "alias" : "zlj", //alias
+ "baglance" : {
+ "freeze" : 0, // frozen assets
+ "total" : 997999999800000, // total assets
+ "available" : 997999999800000 // usable assets
+ },
+ "address" : "5MR_2CeG11nRqx7nGNeh8hTXADibqfSYeNu", // account address
+ "pubkeyHex" : "0211c45f28710cd26a2c45fb790895a0ff2e095a290f1825b31d80ebc30913c486" // encrypted public key
+}
+Query the account list with the paging parameters and return all accounts in descending order by creation time.
| Parameter | Description |
|---|---|
| <pageNumber> | page number indicating the page to query, required |
| <pageSize> | number of rows displayed per page, required |
Return: accounts set
[ {
+ "address" : "5MR_2CeG11nRqx7nGNeh8hTXADibqfSYeNu", //address
+ "alias" : null, //alias
+ "pubkeyHex" : "0211c45f28710cd26a2c45fb790895a0ff2e095a290f1825b31d80ebc30913c486", //public key
+ "encryptedPrikeyHex" : "724d68268849f3680d480c9257f33229c0fac88890d5355c0e4d9c457af5c6e8b8f9f7ca9fd52fbd8079fbce1782052d" //private key
+}, {
+ "address" : "5MR_2CetN1KeWAVsaUsqD7JwMBwjGuRGpGW",
+ "alias" : null,
+ "pubkeyHex" : "0205a70731e7653eca328ba7d71f0a789f8cfb1ced32f5a00d4fc3fb2ad8b9f7c1",
+ "encryptedPrikeyHex" : "e38d2dd08154a0eedf8298f5fe50b86723e521522f38aba5c68072bad365c3e8c57d7ac3ae83f8d646a17f845a38bc57"
+}, {
+ "address" : "5MR_2CXrzwoCoP4vnUxHJ5gdUUXZJhCpjq9",
+ "alias" : "zlj",
+ "pubkeyHex" : "03021a46a7e5ea59ae8884340568e9e79511fbd352b4ba28db39f15856918cdbeb",
+ "encryptedPrikeyHex" : "bfbfdad874f74215e241ad15152d8648925c497b6a826965f5c06c46fd9b008313e6918ebcfcb56f2cdf8d1b9f088f77"
+} ]
+Example: get accounts list
nuls>>> getaccounts
+[ {
+ "address" : "5MR_2CeG11nRqx7nGNeh8hTXADibqfSYeNu", //address
+ "alias" : null, //alias
+ "pubkeyHex" : "0211c45f28710cd26a2c45fb790895a0ff2e095a290f1825b31d80ebc30913c486", //encrypted public key
+ "encryptedPrikeyHex" : "724d68268849f3680d480c9257f33229c0fac88890d5355c0e4d9c457af5c6e8b8f9f7ca9fd52fbd8079fbce1782052d" //encrypted private key
+}, {
+ "address" : "5MR_2CetN1KeWAVsaUsqD7JwMBwjGuRGpGW",
+ "alias" : null,
+ "pubkeyHex" : "0205a70731e7653eca328ba7d71f0a789f8cfb1ced32f5a00d4fc3fb2ad8b9f7c1",
+ "encryptedPrikeyHex" : "e38d2dd08154a0eedf8298f5fe50b86723e521522f38aba5c68072bad365c3e8c57d7ac3ae83f8d646a17f845a38bc57"
+}, {
+ "address" : "5MR_2CXrzwoCoP4vnUxHJ5gdUUXZJhCpjq9",
+ "alias" : "zlj",
+ "pubkeyHex" : "03021a46a7e5ea59ae8884340568e9e79511fbd352b4ba28db39f15856918cdbeb",
+ "encryptedPrikeyHex" : "bfbfdad874f74215e241ad15152d8648925c497b6a826965f5c06c46fd9b008313e6918ebcfcb56f2cdf8d1b9f088f77"
+} ]
+Query the account’s private key with the account address and password
| Parameter | Description |
|---|---|
| <address> | account address, required |
Return: the private key of the imported account (unencrypted)
00a166d10c2cc4cd8f76449ff699ab3eee44fe4f82b4bb866f7bba02751a6fd655
+Example
nuls>>> getprikey 5MR_2CXrzwoCoP4vnUxHJ5gdUUXZJhCpjq9
+Enter your account password**********
+7b4d3ec971fc01ea813b52f6c35091d43beac4a68550bae2db63975149244678
+Query account balance with the account address
| Parameter | Description |
|---|---|
| <address> | account address, required |
Return: the address of the imported account
{
+"total": "9999998.99",// balance
+"freeze": "0", // locked balance
+"available": "9999998.99"// usable balance
+}
+Example
nuls>>> getbalance Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT
+{
+ "total" : "9999998.99",
+ "freeze" : "0",
+ "available" : "9999998.99"
+}
+Transfer NULS to the specific account with the account address
| Parameter | Description |
|---|---|
| <fromAddress> | sender address(Select any item with the fromAlias) |
| <fromAlias> | sender address alias(Select any item with the fromAddress) |
| <toAddress> | receiver address(Select any item with the toAlias) |
| <toAlias> | receiver address(Select any item with the toAddress) |
| <amount> | transfer amount, required |
| [remark] | remark, optional |
Return: transfer transaction hash
"00200bef73ad728c48146c8a5eb0d76fe7325b85803c61d8357c16dba09ea33b3596"
+Example
nuls>>> transfer Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT NsdtmV5XkgSdpBXi65ueTsrv2W5beV2T 100 transfer
+Please enter the password.
+Enter your password: *********
+"00200bef73ad728c48146c8a5eb0d76fe7325b85803c61d8357c16dba09ea33b3596"
+Query the transaction details with the transaction hash
| Parameter | Description |
|---|---|
| <hash> | transaction hash, optional |
Return: transaction details
{
+ "type" : 2, //transaction type (refer to the table below for Enumeration type description [Enumeration type])
+ "coinData" : "ARc5MAGYBT3XNVp+BIuhGvGcejuTev8DODkwAQCgZ/cFAAAAAAAAAAAAAAAACO/WnDT4pvmsAAEXOTABL/80LO1f8vxvfNXc5l9eeIDTGKM5MAEAAOH1BQAAAAAAAAAAAAAAAAA=",
+ "txData" : null,
+ "time" : 1552979783918,
+ "transactionSignature" : "IQIRxF8ocQzSaixF+3kIlaD/LglaKQ8YJbMdgOvDCRPEhgBGMEQCICdnNr3HqEg/UZZ6RLBHyGuPChoLdMtcOHXT3Xlb5SC3AiBGAWSPGH3yjtEkaVbLsI5n9UcqDvOfG3Ui1jf672IDCg==",
+ "remark" : "6L2s6LSm",
+ "hash" : {
+ "digestAlgType" : 0,
+ "digestBytes" : "CivAIHpVyqNr/h87/FWk7vXsXqBekHJ+3kQc5mZp+H8=",
+ "digestHex" : "00200a2bc0207a55caa36bfe1f3bfc55a4eef5ec5ea05e90727ede441ce66669f87f"
+ },
+ "blockHeight" : 341, //block height
+ "status" : "CONFIRMED", //confirmation state
+ "size" : 225,
+ "inBlockIndex" : 0,
+ "coinDataInstance" : {
+ "from" : [ {
+ "address" : "OTABmAU91zVafgSLoRrxnHo7k3r/Azg=",
+ "assetsChainId" : 12345,
+ "assetsId" : 1,
+ "amount" : 100100000,
+ "nonce" : "79acNPim+aw=",
+ "locked" : 0
+ } ],
+ "to" : [ {
+ "address" : "OTABL/80LO1f8vxvfNXc5l9eeIDTGKM=",
+ "assetsChainId" : 12345,
+ "assetsId" : 1,
+ "amount" : 100000000,
+ "lockTime" : 0
+ } ]
+ },
+ "fee" : 100000, //fee
+ "multiSignTx" : false
+}
+Example: query transfer transaction
nuls>>> gettx 00200a2bc0207a55caa36bfe1f3bfc55a4eef5ec5ea05e90727ede441ce66669f87f
+{
+ "type" : 2, //transaction type (refer to the table below for Enumeration type description [Enumeration type])
+ "coinData" : "ARc5MAGYBT3XNVp+BIuhGvGcejuTev8DODkwAQCgZ/cFAAAAAAAAAAAAAAAACO/WnDT4pvmsAAEXOTABL/80LO1f8vxvfNXc5l9eeIDTGKM5MAEAAOH1BQAAAAAAAAAAAAAAAAA=",
+ "txData" : null,
+ "time" : 1552979783918,
+ "transactionSignature" : "IQIRxF8ocQzSaixF+3kIlaD/LglaKQ8YJbMdgOvDCRPEhgBGMEQCICdnNr3HqEg/UZZ6RLBHyGuPChoLdMtcOHXT3Xlb5SC3AiBGAWSPGH3yjtEkaVbLsI5n9UcqDvOfG3Ui1jf672IDCg==",
+ "remark" : "6L2s6LSm",
+ "hash" : {
+ "digestAlgType" : 0,
+ "digestBytes" : "CivAIHpVyqNr/h87/FWk7vXsXqBekHJ+3kQc5mZp+H8=",
+ "digestHex" : "00200a2bc0207a55caa36bfe1f3bfc55a4eef5ec5ea05e90727ede441ce66669f87f"
+ },
+ "blockHeight" : 341, //block height
+ "status" : "CONFIRMED", //confirmation state
+ "size" : 225,
+ "inBlockIndex" : 0,
+ "coinDataInstance" : {
+ "from" : [ {
+ "address" : "OTABmAU91zVafgSLoRrxnHo7k3r/Azg=",
+ "assetsChainId" : 12345,
+ "assetsId" : 1,
+ "amount" : 100100000,
+ "nonce" : "79acNPim+aw=",
+ "locked" : 0
+ } ],
+ "to" : [ {
+ "address" : "OTABL/80LO1f8vxvfNXc5l9eeIDTGKM=",
+ "assetsChainId" : 12345,
+ "assetsId" : 1,
+ "amount" : 100000000,
+ "lockTime" : 0
+ } ]
+ },
+ "fee" : 100000, //fee
+ "multiSignTx" : false
+}
+/** coinbase transaction*/
+ int TX_TYPE_COINBASE = 1;
+ /** transfer */
+ int TX_TYPE_TRANSFER = 2;
+ /** set alias */
+ int TX_TYPE_ALIAS = 3;
+ /** create consensus node */
+ int TX_TYPE_REGISTER_AGENT = 4;
+ /** agent (join consensus) */
+ int TX_TYPE_JOIN_CONSENSUS = 5;
+ /** cancel agent (cancel consensus)*/
+ int TX_TYPE_CANCEL_DEPOSIT = 6;
+ /** yellow punish */
+ int TX_TYPE_YELLOW_PUNISH = 7;
+ /** red punish */
+ int TX_TYPE_RED_PUNISH = 8;
+ /** stop node (stop consensus node)*/
+ int TX_TYPE_STOP_AGENT = 9;
+ /** cross-chain transfer */
+ int TX_TYPE_CROSS_CHAIN_TRANSFER = 10;
+ /** register chain */
+ int TX_TYPE_REGISTER_CHAIN_AND_ASSET = 11;
+ /** destroy chain*/
+ int TX_TYPE_DESTROY_CHAIN_AND_ASSET = 12;
+ /** add asset to chain*/
+ int TX_TYPE_ADD_ASSET_TO_CHAIN = 13;
+ /** remove asset from chain*/
+ int TX_TYPE_REMOVE_ASSET_FROM_CHAIN = 14;
+ /** create contract */
+ int TX_TYPE_CREATE_CONTRACT = 100;
+ /** call contract */
+ int TX_TYPE_CALL_CONTRACT = 101;
+ /** delete contract*/
+ int TX_TYPE_DELETE_CONTRACT = 102;
+Transfer to an external address with an account alias
| Parameter | Description |
|---|---|
| <address> | sender address, required |
| <toAddress> | receiver address, required |
| <amount> | transfer amount, required |
| [remark] | remark, optional |
Return: transaction hash
00205315329f62824b3fae1675ef9419ae7dd097d6609d61df4b1345f9481f7c8be3
+Example: transfer 10,000 NULS to external address through alias "zlj"
nuls>>> transferbyalias zlj 5MR_2CeG11nRqx7nGNeh8hTXADibqfSYeNu 10000
+Enter your account password**********
+00205315329f62824b3fae1675ef9419ae7dd097d6609d61df4b1345f9481f7c8be3
+To create a node through account address, it is required to provide two addresses. The first one is the node address, and you need to input the password for the node account. The other is the package address, and no password is required. Meanwhile, you’re required to offer no less than 20,000 NULS as deposit.
| Parameter | Description |
|---|---|
| <agentAddress> | account address to create a node, required |
| <packingAddress> | account address of the packaging node, required (note: the account should be password-less, otherwise the node cannot package to generate blocks) |
| <commissionRate> | agent commission ratio with a range from 10 to 100, required |
| <deposit> | deposit to create a node, no less than 2000 NULS, required |
Return: agent hash of the node
"002006a5b7eb1d32ed6d7d54e24e219b112d4fdb8530db5506ee953b6f65a0fdb55e"
+Example: create a node with a commission rate of 10% and a deposit of 20,000 NULS.
nuls>>> createagent Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT NsdvAnqc8oEiNiGgcp6pEusfiRFZi4vt 10 20000
+Please enter the password.
+Enter your password: **********
+"002006a5b7eb1d32ed6d7d54e24e219b112d4fdb8530db5506ee953b6f65a0fdb55e"
+Join consensus by account address and node agentHash, which requires at least 2,000NULS
| Parameter | Description |
|---|---|
| <address> | account address, required |
| <agentHash> | agentHash of the node, optional |
| <deposit> | deposit required to join consensus, no less than 2000NULS, required |
Return: the hash of the transaction to join consensus, which is needed to cancel the consensus.
"0020d349b7ad322ff958e3abfa799d9ac76341afa6e1fb4d3857353a5adc74ba3fd0"
+Example
nuls>>> deposit NsdtmV5XkgSdpBXi65ueTsrv2W5beV2T 002006a5b7eb1d32ed6d7d54e24e219b112d4fdb8530db5506ee953b6f65a0fdb55e 5000
+"0020d349b7ad322ff958e3abfa799d9ac76341afa6e1fb4d3857353a5adc74ba3fd0"
+Cancel consensus (agent) according to account address and the hash of the transaction for joining consensus. When a single account agents nodes for multiple times, each agent transaction is independent. So to cancel consensus, the agent can only be cancelled by the corresponding transaction hash of the single agent, rather than cancel all the agents at one time.
| Parameter | Description |
|---|---|
| <address> | account address, required |
| <txHash> | hash of the agent transaction, required |
Return: transaction hash to cancel consensus
"00201d70ac37b53d41c0e813ad245fc42e1d3a5d174d9148fbbbaed3c18d4d67bdbf"
+Example
nuls>>> withdraw NsdtmV5XkgSdpBXi65ueTsrv2W5beV2T 0020d349b7ad322ff958e3abfa799d9ac76341afa6e1fb4d3857353a5adc74ba3fd0
+"00201d70ac37b53d41c0e813ad245fc42e1d3a5d174d9148fbbbaed3c18d4d67bdbf"
+Stop the node and all NULS delegated to the node will be refunded, and the deposit of the node creator will be locked for 72 hours.
| Parameter | Description |
|---|---|
| <address> | account address, required |
Return: transaction hash to stop a node
"0020f15eecd7c85be76521ed6af4d58a3810f7df58e536481cff4a96af6d4fddec5f"
+Example
nuls>>> stopagent Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT
+Please enter the password.
+Enter your password:**********
+"0020f15eecd7c85be76521ed6af4d58a3810f7df58e536481cff4a96af6d4fddec5f"
+Get the latest block header’s information
Return
{
+ "hash" : "0020b446a0244e4e46f8736f1ab56c33616facb836bc8344367f2f048b703f0c8f57", //block hash
+ "preHash" : "0020c0dcf9209f66ee7e7778c817ba7c04d67b5e6a056b42dec7fbfe44eb5f91bdfc", //previous block hash
+ "merkleHash" : "00200511ced5779c54aa2170b941a1f9a7ae08dfd009b1dfaacc3679d15da9fb9c3e", //merkle hash
+ "time" : "2019-03-19 18:26:20.020", //packing time
+ "height" : 1479, //block height
+ "txCount" : 1, // number of transactions included in the block
+ "blockSignature" : "00473045022100b1a07f6da3d4ce46cab278967d76875483527e3fc749a460afdf0c375f2ec2ae022053e40e8b4d8bf4e571284e45f18c46c31163ed640a2328f3ba90ac7708808365", //block singnature
+ "size" : 0, //block size
+ "packingAddress" : null, // packing address
+ "roundIndex" : 155299118,
+ "consensusMemberCount" : 100,
+ "roundStartTime" : "2019-03-19 18:26:10.010",
+ "packingIndexOfRound" : 1,
+ "mainVersion" : 1,
+ "blockVersion" : 0,
+ "stateRoot" : null
+}
+Example
nuls>>> getbestblockheader
+{
+ "hash" : "0020b446a0244e4e46f8736f1ab56c33616facb836bc8344367f2f048b703f0c8f57",
+ "preHash" : "0020c0dcf9209f66ee7e7778c817ba7c04d67b5e6a056b42dec7fbfe44eb5f91bdfc",
+ "merkleHash" : "00200511ced5779c54aa2170b941a1f9a7ae08dfd009b1dfaacc3679d15da9fb9c3e",
+ "time" : "2019-03-19 18:26:20.020",
+ "height" : 1479,
+ "txCount" : 0,
+ "blockSignature" : "00473045022100b1a07f6da3d4ce46cab278967d76875483527e3fc749a460afdf0c375f2ec2ae022053e40e8b4d8bf4e571284e45f18c46c31163ed640a2328f3ba90ac7708808365",
+ "size" : 0,
+ "packingAddress" : null,
+ "roundIndex" : 155299118,
+ "consensusMemberCount" : 100,
+ "roundStartTime" : "2019-03-19 18:26:10.010",
+ "packingIndexOfRound" : 1,
+ "mainVersion" : 1,
+ "blockVersion" : 0,
+ "stateRoot" : null
+}
+Query block information with the block height or block hash, and exactly only one of them can be used as the query condition.
| Parameter | Description |
|---|---|
| <hash> | block hash |
| <height> | block height |
Return
{
+ "hash" : "0020b446a0244e4e46f8736f1ab56c33616facb836bc8344367f2f048b703f0c8f57", //block hash
+ "preHash" : "0020c0dcf9209f66ee7e7778c817ba7c04d67b5e6a056b42dec7fbfe44eb5f91bdfc", //previous block hash
+ "merkleHash" : "00200511ced5779c54aa2170b941a1f9a7ae08dfd009b1dfaacc3679d15da9fb9c3e", //merkle hash
+ "time" : "2019-03-19 18:26:20.020", //packing time
+ "height" : 1479, //block height
+ "txCount" : 1, // number of transactions included in the block
+ "blockSignature" : "00473045022100b1a07f6da3d4ce46cab278967d76875483527e3fc749a460afdf0c375f2ec2ae022053e40e8b4d8bf4e571284e45f18c46c31163ed640a2328f3ba90ac7708808365", //block signature
+ "size" : 0, //block size
+ "packingAddress" : null, //packing address
+ "roundIndex" : 155299118,
+ "consensusMemberCount" : 100,
+ "roundStartTime" : "2019-03-19 18:26:10.010",
+ "packingIndexOfRound" : 1,
+ "mainVersion" : 1,
+ "blockVersion" : 0,
+ "stateRoot" : null
+}
+Example: get block with block height
nuls>>> getblock 28115
+{
+ "hash" : "0020b446a0244e4e46f8736f1ab56c33616facb836bc8344367f2f048b703f0c8f57", //block hash
+ "preHash" : "0020c0dcf9209f66ee7e7778c817ba7c04d67b5e6a056b42dec7fbfe44eb5f91bdfc", //previous block hash
+ "merkleHash" : "00200511ced5779c54aa2170b941a1f9a7ae08dfd009b1dfaacc3679d15da9fb9c3e", //merkle hash
+ "time" : "2019-03-19 18:26:20.020", //packing time
+ "height" : 1479, //block height
+ "txCount" : 1, // number of transactions included in the block
+ "blockSignature" : "00473045022100b1a07f6da3d4ce46cab278967d76875483527e3fc749a460afdf0c375f2ec2ae022053e40e8b4d8bf4e571284e45f18c46c31163ed640a2328f3ba90ac7708808365", //block signature
+ "size" : 0, //block size
+ "packingAddress" : null, //packing address
+ "roundIndex" : 155299118,
+ "consensusMemberCount" : 100,
+ "roundStartTime" : "2019-03-19 18:26:10.010",
+ "packingIndexOfRound" : 1,
+ "mainVersion" : 1,
+ "blockVersion" : 0,
+ "stateRoot" : null
+}
+This interface is called to create a smart contract on the chain
| Parameter | Description |
|---|---|
| <sender> | Create the account address for the smart contract |
| <gaslimt> | Consumes of the gas for creating the contract |
| <price> | Unit price, how much Na is each Gas value.Na is the minimum unit for NULS, 1 NULS = 100 million Na, and the minimum unit price of the system is 25Na/Gas |
| <contractCode> | Hex code of the contract code |
| [remark] | remark |
Returns the transaction hash for which the contract was created and the address of the contract
{
+ "txHash" : "00205fb44fd0924a57857e71d06ec0549366b5d879b2cbd68488ed88a2dbf96c130f", //transaction hash
+ "contractAddress" : "tNULSeBaN6ofkEqsPJmWVaeMpENTgmC5ifWtz9" //contract address
+}
+The example creates a contract (contractCode omits the middle)
nuls>>> createcontract tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD 200000 25 504b03040a........000000800080051020000b31600000000 remarkdemo
+The arguments structure:
+[ {
+ "type" : "String",
+ "name" : "name",
+ "required" : true
+}, {
+ "type" : "String",
+ "name" : "symbol",
+ "required" : true
+}, {
+ "type" : "BigInteger",
+ "name" : "initialAmount",
+ "required" : true
+}, {
+ "type" : "int",
+ "name" : "decimals",
+ "required" : true
+} ]
+Please enter the arguments you want to fill in according to the arguments structure(eg. "a",2,["c",4],"","e" or "'a',2,['c',4],'','e'").
+Enter the arguments:"KQB","KQB",10000,2
+{
+ "txHash" : "0020ec1d68eaed63e2db8649b0a39f16b7c5af24f86b787233f6ba6d577d7d090587",
+ "contractAddress" : "tNULSeBaNBYK9MQcWWbfgFTHj2U4j8KQGDzzuK"
+}
+Gets the description of the intelligent contract and the argument list of the constructor and the calling method
| Parameter | Description |
|---|---|
| <contract address> | contract address |
Return
Skip
+example
+nuls>>> getcontractinfo tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L
+getcontractinfo tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L
+{
+ "createTxHash" : "00203a48dcfc26426152805be49830c72005b4648d0182bbf6c2e8980380364eb59f",
+ "address" : "tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L",
+ "creater" : "tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD",
+ "createTime" : 1553563706022,
+ "blockHeight" : 46,
+ "isNrc20" : true,
+ "nrc20TokenName" : "QKB",
+ "nrc20TokenSymbol" : "QKB",
+ "decimals" : 2,
+ "totalSupply" : "200000000",
+ "status" : "normal",
+ "method" : [ {
+ "name" : "<init>",
+ "desc" : "(String name, String symbol, BigInteger initialAmount, int decimals) return void",
+ "args" : [ {
+ "type" : "String",
+ "name" : "name",
+ "required" : true
+ }, {
+ "type" : "String",
+ "name" : "symbol",
+ "required" : true
+ }, {
+ "type" : "BigInteger",
+ "name" : "initialAmount",
+ "required" : true
+ }, {
+ "type" : "int",
+ "name" : "decimals",
+ "required" : true
+ } ],
+ "returnArg" : "void",
+ "view" : false,
+ "event" : false,
+ "payable" : false
+ },{
+ "name" : "transfer",
+ "desc" : "(Address to, BigInteger value) return boolean",
+ "args" : [ {
+ "type" : "Address",
+ "name" : "to",
+ "required" : true
+ }, {
+ "type" : "BigInteger",
+ "name" : "value",
+ "required" : true
+ } ],
+ "returnArg" : "boolean",
+ "view" : false,
+ "event" : false,
+ "payable" : false
+ }]
+}
+
+Call the functions provided by the smart contract
| Parameter | Description |
|---|---|
| <senderAddress> | The account address of the invocation contract |
| <gasLimit> | This contract is the largest consumption of Gas |
| <price> | Unit price, how much Na is each Gas value.Na is the minimum unit for NULS, 1 NULS = 100 million Na, and the minimum unit price of the system is 25Na/Gas |
| <contractAddress | The contract address of the call |
| <methodName> | The method name of the contract |
| <value> | If transfer is to be made to the contract, the amount of transfer |
| [-d methodDesc] | Use this method to describe the parameter list if there is a method with the same name in the contract |
| [-r remark] | remark |
Returns: transaction hash
"0020c9079e0f0454103adceed798d40171c41a8db04586dba966fbe7f2ab722583ad" //transaction hash
+The example calls the nrc20-token transfer function for a specified contract, Example tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L NRC20 contract address, number of input parameters for receiving address and account transfer
nuls>>> callcontract tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD 200000 25 tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L transfer 0 -r call
+callcontract tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD 200000 25 tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L transfer 0 -r call
+Please Enter your account passwordzhoujun172
+**********
+Please enter the arguments according to the arguments structure(eg. "a",2,["c",4],"","e" or "'a',2,['c',4],'','e'"),
+If this method has no arguments(Refer to the command named "getcontractinfo" for the arguments structure of the method.), return directly.
+Enter the arguments:"tNULSeBaMvEtDfvZuukDf2mVyfGo3DdiN8KLRG",2
+"0020c9079e0f0454103adceed798d40171c41a8db04586dba966fbe7f2ab722583ad"
+Stop an available smart contract
| Parameter | Description |
|---|---|
| <senderAddress> | The account address of the invocation contract |
| <contractAddress> | The contract address of the call |
Returns: trading hash
"0020c55e885dd910dad0b2c49f5b71b62691b57884ca21fd47668f1f5cadc84daad6" //交易hash
+example
nuls>>> deletecontract tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L
+deletecontract tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L
+Please enter your account passwordzhoujun172
+**********
+"0020c55e885dd910dad0b2c49f5b71b62691b57884ca21fd47668f1f5cadc84daad6"
+Calling the contract view method immediately returns the result and no transaction is generated
| Parameter | Description |
|---|---|
| <contractAddress> | The contract address of the call |
| <methodName> | Method called |
| [-d methodDesc] | Use this method to describe the parameter list if there is a method with the same name in the contract |
The return value
The return value varies depending on the function being called
+The example calls the nrc20-token contract's query Token balance function to query the Token balance of the specified address
nuls>>> viewcontract tNULSeBaN6pwyVwXjfpm5BMH5eiirvthoZDVEc balanceOf
+viewcontract tNULSeBaN6pwyVwXjfpm5BMH5eiirvthoZDVEc balanceOf
+Please enter the arguments according to the arguments structure(eg. "a",2,["c",4],"","e" or "'a',2,['c',4],'','e'"),
+If this method has no arguments(Refer to the command named "getcontractinfo" for the arguments structure of the method.), return directly.
+Enter the arguments:"tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD"
+"tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD"
+{
+ "result" : "20000000"
+}
+To the specified contract address into the main network currency
| Parameter | Description |
|---|---|
| <senderAddress> | Transfer out account address |
| <contractAddress | transfer into the contract address |
| <amount> | transfer amount |
| [remark] | remark |
Returns: trading hash
"0020f5d6b87c246595d1b060a3fa8bac6a2992490e38fdfcad40db2a3908297e7979"
+Example passes two NULS to the specified contract
nuls>>> transfertocontract tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD tNULSeBaN1NRtaj1ZPAmEmTqcpkyCLqv64PR7U 2 remark
+Please enter your account password
+**********
+"0020f5d6b87c246595d1b060a3fa8bac6a2992490e38fdfcad40db2a3908297e7979"
+NRC20 token transfer
| Parameter | Description |
|---|---|
| <formAddress> | sender address |
| <toAddress | receiver address |
| <contractAddress> | contract address |
| <amount> | transfer amount |
| [remark] | remark |
Returns: trading hash
"002022dffd96026b493945d2cf9ad276c4bc9655c735b72e6fcc85a2d19f6cbe25e8"
+example token transfer:
nuls>>> tokentransfer tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD tNULSeBaNBh9RUsVrVmMy8NHcZJ2BhNVsM1Vta tNULSeBaN6pwyVwXjfpm5BMH5eiirvthoZDVEc 200000 25 10000
+Please enter your account password
+**********
+"002022dffd96026b493945d2cf9ad276c4bc9655c735b72e6fcc85a2d19f6cbe25e8"
+Gets the transaction information of the contract, including the transaction details, the contract invocation parameters, and the contract execution results
| Parameter | Description |
|---|---|
| <hash> | transaction hash |
return value
skip
+example
nuls>>> getcontracttx 00203a48dcfc26426152805be49830c72005b4648d0182bbf6c2e8980380364eb59f
+getcontracttx 00203a48dcfc26426152805be49830c72005b4648d0182bbf6c2e8980380364eb59f
+{
+ "hash" : "00203a48dcfc26426152805be49830c72005b4648d0182bbf6c2e8980380364eb59f",
+ "type" : "100",
+ "time" : "2019-03-26 09:28:26",
+ "blockHeight" : 46,
+ "fee" : 0.0,
+ "value" : 0.0,
+ "remark" : null,
+ "scriptSig" : "210318f683066b45e7a5225779061512e270044cc40a45c924afcf78bb7587758ca0004630440220112a446b2a684510b4016fa97b92d2f3fead03128f0f658c99a6a8d230d05d4e02201e23a2f6e68aacdff2d117bd5bbe7ce2440babfe4211168eafbae41acad5d505",
+ "status" : "confirm",
+ "confirmCount" : 0,
+ "size" : 6686,
+ "inputs" : [ {
+ "address" : "tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD",
+ "assetsChainId" : 2,
+ "assetsId" : 1,
+ "amount" : "5700000",
+ "nonce" : "ffffffff",
+ "locked" : 0,
+ "value" : 0.0
+ } ],
+ "outputs" : [ ],
+ "txData" : {
+ "data" : {
+ "sender" : "tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD",
+ "contractAddress" : "tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L",
+ "value" : 0.0,
+ "hexCode" : "504b03040a0000080...........31600000000",
+ "gasLimit" : 200000,
+ "price" : "0.00000025",
+ "args" : [ [ "QKB" ], [ "QKB" ], [ "2000000" ], [ "2" ] ]
+ }
+ },
+ "contractResult" : {
+ "success" : true,
+ "errorMessage" : null,
+ "contractAddress" : "tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L",
+ "result" : null,
+ "gasLimit" : 200000,
+ "gasUsed" : 14029,
+ "price" : "0.00000025",
+ "totalFee" : 0.0,
+ "txSizeFee" : 0.0,
+ "actualContractFee" : 0.0,
+ "refundFee" : 0.0,
+ "stateRoot" : "be76399c41a8cb4be5ecf80e04dab36830b124cb1c43fea6ca69ae62259899ba",
+ "value" : 0.0,
+ "stackTrace" : null,
+ "balance" : 0.0,
+ "transfers" : [ ],
+ "events" : [ "{\"contractAddress\":\"tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L\",\"blockNumber\":46,\"event\":\"TransferEvent\",\"payload\":{\"from\":null,\"to\":\"tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD\",\"value\":\"200000000\"}}" ],
+ "tokenTransfers" : [ {
+ "contractAddress" : "tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L",
+ "from" : null,
+ "to" : "tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD",
+ "value" : "200000000",
+ "name" : "QKB",
+ "symbol" : "QKB",
+ "decimals" : 2
+ } ],
+ "remark" : "create"
+ }
+}
+
+
+Gets the execution result of a contract
| Parameter | Description |
|---|---|
| <hash> | transaction hash |
return value
skip
+example
nuls>>> getcontractresult 00203a48dcfc26426152805be49830c72005b4648d0182bbf6c2e8980380364eb59f
+{
+ "success" : true,
+ "errorMessage" : null,
+ "contractAddress" : "tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L",
+ "result" : null,
+ "gasLimit" : 200000,
+ "gasUsed" : 14029,
+ "price" : "0.00000025",
+ "totalFee" : 0.0,
+ "txSizeFee" : 0.0,
+ "actualContractFee" : 0.0,
+ "refundFee" : 0.0,
+ "stateRoot" : "be76399c41a8cb4be5ecf80e04dab36830b124cb1c43fea6ca69ae62259899ba",
+ "value" : 0.0,
+ "stackTrace" : null,
+ "balance" : 0.0,
+ "transfers" : [ ],
+ "events" : [ "{\"contractAddress\":\"tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L\",\"blockNumber\":46,\"event\":\"TransferEvent\",\"payload\":{\"from\":null,\"to\":\"tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD\",\"value\":\"200000000\"}}" ],
+ "tokenTransfers" : [ {
+ "contractAddress" : "tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L",
+ "from" : null,
+ "to" : "tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD",
+ "value" : "200000000",
+ "name" : "QKB",
+ "symbol" : "QKB",
+ "decimals" : 2
+ } ],
+ "remark" : "create"
+}
+
+Gets the list of parameters that need to be passed in to create the specified contract
| Parameter | Description |
|---|---|
| <contractCode> | Hex code of the contract code |
return value
skip
+example
nuls>>> getcontractcontructor 504b03040a000008000.........20000b31600000000
+{
+ "constructor" : {
+ "name" : "<init>",
+ "desc" : "(String name, String symbol, BigInteger initialAmount, int decimals) return void",
+ "args" : [ {
+ "type" : "String",
+ "name" : "name",
+ "required" : true
+ }, {
+ "type" : "String",
+ "name" : "symbol",
+ "required" : true
+ }, {
+ "type" : "BigInteger",
+ "name" : "initialAmount",
+ "required" : true
+ }, {
+ "type" : "int",
+ "name" : "decimals",
+ "required" : true
+ } ],
+ "returnArg" : "void",
+ "view" : false,
+ "event" : false,
+ "payable" : false
+ },
+ "isNrc20" : true
+}
+
+Gets the list of contracts created by the specified account address
| Parameter | Description |
|---|---|
| <createAddress> | account address |
return value
{
+ "contractAddress" : "tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L",
+ "createTime" : "2019-03-26 09:28:26.026",
+ "height" : 46,
+ "confirmCount" : 402,
+ "remarkName" : null,
+ "status" : 2,
+ "msg" : null,
+ "create" : true
+}
+example
nuls>>> getaccountcontracts tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD
+[ {
+ "contractAddress" : "tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L",
+ "createTime" : "2019-03-26 09:28:26.026",
+ "height" : 46,
+ "confirmCount" : 402,
+ "remarkName" : null,
+ "status" : 2,
+ "msg" : null,
+ "create" : true
+}, {
+ "contractAddress" : "tNULSeBaMzsHrbMy2VK23RzwjkXS1qo2ycG5Cg",
+ "createTime" : "2019-03-25 16:08:25.025",
+ "height" : 253,
+ "confirmCount" : 195,
+ "remarkName" : null,
+ "status" : 0,
+ "msg" : null,
+ "create" : true
+}, {
+ "contractAddress" : "tNULSeBaNBYK9MQcWWbfgFTHj2U4j8KQGDzzuK",
+ "createTime" : "2019-03-25 15:33:54.054",
+ "height" : 46,
+ "confirmCount" : 402,
+ "remarkName" : null,
+ "status" : 0,
+ "msg" : null,
+ "create" : true
+} ]
+Query network basic information
Return
{
+ "localBestHeight" : 35317,//latest block height locally
+ "netBestHeight" : 35317,//latest block height of the network
+ "timeOffset" : "0ms",//network time offset
+ "inCount" : 0,//number of in-nodes
+ "outCount" : 1//number of out-nodes
+}
+Example
nuls>>> network info
+{
+ "localBestHeight" : 35317,
+ "netBestHeight" : 35317,
+ "timeOffset" : "0ms",
+ "inCount" : 0,
+ "outCount" : 1
+}
+Query the network node IP
Return information
[" 192.168.1.223 "]
+Example: get a block with the block height
nuls>>> network nodes
+[ "192.168.1.223" ]
+Exit the command line that operates the wallet, while it won’t stop the launched wallet node.
Example
nuls>>> exit
+[TOC]
The network module guarantees the communication between the decentralized nodes and +provides the lowest level of network communication and node discovery services for one of the NULS basic modules. The network foundation of the blockchain is Peer to Peer, or P2P. All participants in the P2P network can be either a server or a client. Features of P2P networks: decentralization, scalability, robustness, cost-effectiveness, privacy protection, and load balancing.
The network module is the basic module of the entire system, which is used to manage the connection between nodes, nodes and connections, and the transmission and reception of data. Network modules do not involve complex business logic.

The network module has functions in the business: node management, node group management, p2p network connection management, and message transmission and management.
The internal infrastructure functions include: state management of the module (including startup and shutdown management), and management of external interfaces. Thread task management, data storage management, etc. 。

Peer Nodes Management
Manage all connectable, connected node information, status, and provide node operation interfaces
Node Groups Management
Manage different network nodes, divide nodes into different collections, and manage each collection separately. The magic parameters of the nodes connected in each set are the same and are different from the magic parameters of other sets.
Each NodeGroup is initialized according to the information registered in the chain or the network information configured by itself (magic parameters, number of nodes, etc.) .Every time a NodeGroup is initialized, the network service listens for more than one MagicNumber.
Connection Management
Message Management
Receiving the message sent by the network node, making a simple judgment on the message +(judging command), and sending the message to the module service of interest +according to the message cmd field.
[^ps]: RPC API Service interface information (url) is periodically obtained and cached from the kernel module.
Message receiver
Module Management
RPC Api Management
Register your own interface into the kernel module
Synchronize module information and status to the kernel module
Get the list of RPC services to the local module
Open external interface call
Thread task management
heartbeat thread
Node discovery/elimination mechanism thread
Interface information synchronization thread
Function Description:
Receiving the message sent by the (external) network node, making a simple judgment on +the message (determining the magic parameter), and sending the message to the module service of interest according to the command field contained in the message header.
Process description

Message verification :
payload validate :First 4 bytes of sha256(sha256(payload))
magicNumbe :Determine if the nodegroups collection contains the magicNumber
External module network message receiving interface constraint
method : *** //Same as the CMD instruction in the message header, constraining 12 bytes
Interface description: The network module transparently forwards the message to the external module.
params
0:chainId
+ 1:nodeId
+ 2:messageBody
+ ......
+
+Dependent service
Parsing the command parameter in the message header, relying on the remote service interface data provided by the kernel module when calling the remote interface processing.
Forwards messages encapsulated by other or own modules, including broadcast messages and designated nodes to send messages.
Function Description:
Forwarding messages encapsulated by other or its own modules, and providing interfaces for forwarding calls to external modules have the following two cases:
a> Broadcast a message to a NodeGroup (specify a network).
b> Broadcast messages to the NodeGroup (specify a network) and exclude certain nodes.

Interface definition
method : nw_broadcast
Other modules can broadcast messages through this interface
Request example
{
+ "method":"nw_broadcast",
+ "minVersion":1.1,
+ "params":[
+ 1234,
+ "10.13.25.36:5003,20.30.25.65:8009",
+ "03847ABDFF303847ABDFF303847ABDFF303847ABDFF303847ABDFF303847ABDFF3",
+ "getBlock"
+
+ ]}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | int | chainId |
| 1 | excludeNodes | true | String | Exclude nodes, comma separated |
| 2 | message | true | String | Object hexadecimal character |
| 3 | command | true | String | message command,12 byte |
Return example
Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+Success
{
+ "version": 1.2,
+ "code":0,
+ "result":{
+
+ }
+}
+Dependent service
nothing
Function Description:
Forwarding messages encapsulated by other or its own modules, you can specify that +certain nodes (which can be 1 node) send messages.
Process description

Interface definition
Interface Description
External modules can broadcast messages through this interface
method : nw_sendPeersMsg
Request example
{
+ "method":"nw_sendPeersMsg",
+ "minVersion":1.1,
+ "params":[
+ 1234,
+ "10.13.25.36:5003,20.30.25.65:8009",
+ "03847ABDFF303847ABDFF303847ABDFF303847ABDFF303847ABDFF303847ABDFF3",
+ "getBlock"
+ ]}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | int | chainId |
| 1 | nodes | true | String | Send node, comma split |
| 2 | message | true | String | Object hexadecimal character |
| 3 | command | true | String | message command,12 byte |
Return example
Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+Success
{
+ "version": 1.2,
+ "code":0,
+ "result":{
+
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
Dependent service
nothing
In addition to its own satellite network, the satellite chain also has n cross-chain networks. In addition to its own network, there is also a cross-chain network.
Node groups are used to manage different network information. The network module isolates and maintains different networks through node groups.
Node group type: 1> own network 2> cross-chain network (satellite chain cross-chain network & friend chain cross-chain network)
The network module is a call to receive an external module to create a node group. The basic network configuration information of the cross-chain is mainly obtained through two ways:
1> The own configuration file is loaded to create its own network group.
2> Cross-chain network:
As a satellite chain node, after the registration is registered by the chain management module, the system generates a transaction verification confirmation and then calls to generate a cross-chain network group.
As a friend chain node, when started by the cross-chain protocol module, the cross-chain protocol module obtains cross-chain configuration information from the module configuration, and notifies the network module,The network module triggers a cross-chain connection.
Process description
The actual creation of a NodeGroup also has two kinds of logic:
1> Generate your own network group (or data load call) by loading the configuration file.
2> Call by external module: Create a network group as confirmed by registering cross-chain transactions.
Function Description:
The own network corresponds to its own chainId, and a magic parameter, through the configuration initialization to create a node group.
Process description
Create a node group by loading the configuration file
Interface definition
Created internally, no external interface。
none
Function Description:
The cross-chain node group on the satellite chain is triggered by the cross-chain registration of the friend chain in the satellite chain. The friend chain obtains cross-chain configuration information, and the cross-chain status of the own network group is updated by the cross-chain protocol.
Process description
1> The satellite chain is triggered by the chain management module to trigger the creation of a cross-link node group.
2> The friend chain updates the cross-chain status of its own network group through the cross-chain protocol module.

interface definition
Interface Description
Receive a call to an external module to create a node group
method : nw_createNodeGroup
Request example
{
+ "method":"nw_createNodeGroup",
+ "minVersion":1.1,
+ "params":[
+ 1234,
+ 232342,
+ 10,
+ 100,
+ 20,
+ "10.20.30.10:8002,48.25.32.12:8003,52.23.25.32:9003",
+ 0
+ ]}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | int | chainId |
| 1 | magicNumber | true | long | magicNumber |
| 2 | maxOut | true | int | Maximum active connections |
| 3 | maxIn | true | int | Maximum number of passive connections |
| 4 | minAvailableCount | true | int | Minimum number of links in the friend chain |
| 5 | seedIps | true | String | Seed section group comma segmentation |
| 6 | isMoonNode | true | int | Whether satellite chain node, default 0 |
Return example
Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+Success
{
+ "version": 1.2,
+ "code":0,
+ "result":{
+
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
Dependent service
Relies on remote service interface data provided by the kernel module.
Function Description:
The cross-chain node group on the satellite chain is triggered by the cross-chain registration of the friend chain in the satellite chain. The friend chain obtains cross-chain configuration information, and the cross-chain status of the own network group is updated by the cross-chain protocol.
Process description
The friend chain updates the cross-chain status of its own network group through the cross-chain protocol module.
Interface definition
Interface Description
Receive calls from cross-chain modules, activate friend chain cross-chain
method : nw_activeCross
Request example
{
+ "method":"nw_activeCross",
+ "minVersion":1.1,
+ "params":[
+ 1234,
+ 10,
+ 100,
+ "10.20.30.10:8002,48.25.32.12:8003,52.23.25.32:9003"
+ ]}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | int | Chain identification |
| 1 | maxOut | true | int | Maximum active connections |
| 2 | maxIn | true | int | Maximum number of passive connections |
| 3 | seedIps | true | String | Seed node, comma segmentation |
Return example
Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+Success
{
+ "version": 1.2,
+ "code":0,
+ "result":{
+
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
Dependent service
Relies on remote service interface data provided by the kernel module.
Function Description:
Receive a call from an external module and unregister the cross-chain node group.
As a satellite chain node, the chain management module performs deregistration, and the system generates a transaction verification confirmation and then calls it.
Process description

Interface definition
Interface Description
Receive calls from external modules, delete node groups
method : nw_delNodeGroup
Request example
{
+ "method":"nw_delNodeGroup",
+ "minVersion":1.1,
+ "params":[
+ 1234
+ ]}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | int | chainId |
Return example
Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+Success
{
+ "version": 1.2,
+ "code":0,
+ "result":{
+
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
Dependent service
Relies on remote service interface data provided by the kernel module.
Function Description:
The seed node is a node used to provide peer connection information when the network is initialized. When the chain management module performs chain registration, it needs to +obtain the seed node information on the satellite chain for initializing +the connection.
Process description
no
Interface definition
Interface Description
Obtain satellite chain seed node
method : nw_getSeeds
Request example
{
+ "method":"nw_getSeeds",
+ "minVersion":1.1,
+ "params":[
+ 1234
+ ]}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | int | chainId |
Return example
Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+Success
{
+ "version": 1.2,
+ "code":0,
+ "result":{
+ seedsIps:"101.132.33.140:8003,116.62.135.185:8003,47.90.243.131:8003"
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| seedsIps |
Dependent service
Relies on remote service interface data provided by the kernel module.
Function Description:
Add a peer connection information to a network under the cmd command.
Process description
The added node triggers the network connection process。
Interface definition
Interface Description
Add network peer node
method : nw_addNodes
Request example
{
+ "method":"nw_addNodes",
+ "minVersion":1.1,
+ "params":[
+ 1234,
+ 1,
+ "10.20.23.02:5006,53.26.65.58:8003"
+ ]}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | int | chainId |
| 1 | isCross | true | int | 0 false 1 true |
| 2 | nodes | true | String | nodes |
Return example
Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+Success
{
+ "version": 1.2,
+ "code":0,
+ "result":{
+
+ }
+}
+Return field description
| parameter |
|---|
Dependent service
none
Function Description:
Under the cmd command, the peer connection information is deleted for a network.
Process description
Deleting a node triggers the disconnection of the network node。
Interface definition
Interface Description
Delete network peer nodes
method : nw_delNodes
Request example
{
+ "method":"nw_addNodes",
+ "minVersion":1.1,
+ "params":[
+ 1234,
+ "10.20.23.02:5006,53.26.65.58:8003"
+ ]}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | int | chainId |
| 1 | nodes | true | String | peer nodes |
Return example
Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+Success
{
+ "version": 1.2,
+ "code":0,
+ "result":{
+
+ }
+}
+Return field description
| parameter |
|---|
Dependent service
none
Function Description:
Network reconnection of the specified nodeGroup under the cmd command
Process description
After receiving the command, disconnect all the peers under the specified nodeGroup and reconnect to the network.
Refresh the peer connection under nodegroup and restart the network connection.
If the peer connection is owned by multiple network services, you only need to cancel the association. If only the service is used by itself, you can disconnect.
Interface definition
Interface Description
Obtain satellite chain seed node
method : nw_reconnect
Request example
{
+ "method":"nw_reconnect",
+ "minVersion":1.1,
+ "params":[
+ 1234
+ ]}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | int | 链标识 |
Return example
Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+Success
{
+ "version": 1.2,
+ "code":0,
+ "result":{
+
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
Dependent service +none
Function Description:
Get a list of all networks managed by the node。
Process description
none
Interface definition
Interface Description
Get node group information
method : nw_getGroups
Request example
{
+ "method":"nw_getGroups",
+ "minVersion":1.1,
+ "params":[
+ 1,
+ 10
+ ]}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | startPage | true | int | page of starts |
| 1 | pageSize | true | int | Number of records per page |
Return example
Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+Success
{
+ "version": 1.2,
+ "code":0,
+ "result":{
+ list:[{
+ chainId:1212,
+ magicNumber:324234,
+ totalCount:2323,
+ inCount:22,
+ outCount:33,
+ isActive:1,
+ isCrossChain:1
+ },{}
+ ]
+ }
+}
+Return field description
| parameter | type | description |
|---|---|---|
| chainId | int | chainId |
| magicNumber | int | magicNumber |
| totalCount | int | Total number of connections |
| inCount | int | Passive connection number |
| outCount | int | ctive connections |
| isActive | int | 0 is not activated, 1 is activated |
| isCrossChain | int | 0 is not a cross-chain network, 1 cross-chain network |
Dependent service
none
Function Description:
Get information about all nodes under the specified network id
Process description
none
Interface definition
Get node information
method : nw_getNodes
Request example
{
+ "method":"nw_reconnect",
+ "minVersion":1.1,
+ "params":[
+ 1598,
+ 0,
+ 1,
+ 50
+ ]
+}
+
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | int | chainId |
| 1 | state | true | int | 0 all connected, 1 working connected |
| 2 | startPage | true | int | page of starts |
| 3 | pageSize | true | int | Number of records per page |
Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+
+
+
+Success
{
+ "version": 1.2,
+ "code":0,
+ "result":{
+ list:[{
+ chainId:122,
+ nodeId:"20.20.30.10:9902"
+ magicNumber:134124,
+ version:2,
+ blockHeight:6000, //区块高度
+ blockHash:"0020ba3f3f637ef53d025d3a8972462c00e84d9
+ ea1a960f207778150ffb9f2c173ff", //区块Hash值
+ ip:"200.25.36.41",
+ port:54,
+ state:"已连接",
+ isOut:"1",
+ time:"6449878789",
+ },{}
+ ]
+ }
+}
+
+| parameter | type | description |
|---|---|---|
| chainId | int | chainId |
| nodeId | String | nodeId |
| magicNumber | int | magicNumber |
| version | int | protocol version |
| blockHeight | long | latest block height |
| blockHash | String | latest block hash |
| ip | String | peer Ip address |
| port | int | Server port |
| state | String | connect state |
| isOut | int | 0 passive connection, 1 active connection |
| time | long | Recent connection time |
Dependent service
none
Function Description:
Gets the network information of the specified chainId.
Process description
none
Interface definition
Gets the network information of the specified chainId.
method : nw_getNodes
Request example
{
+ "method":"nw_getGroupByChainId",
+ "minVersion":1.1,
+ "params":[
+ 103
+ ]}
+| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | int | chainId |
Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+
+Success
{
+ "version": 1.2,
+ "code":0,
+ "result":{
+
+ chainId:1212,
+ magicNumber:324234,
+ totalCount:2323,
+ inCount:22,
+ outCount:33,
+ blockHeight:6000,
+ blockHash:"0020ba3f3f637ef53d025d3a8972462c00e84d9
+ ea1a960f207778150ffb9f2c173ff",
+ isActive:1,
+ isCrossActive:1,
+ isMoonNet:0
+ }
+}
+
+| parameter | type | description |
|---|---|---|
| chainId | int | chainId |
| magicNumber | int | magicNumber |
| totalCount | int | total connect |
| blockHeight | long | latest block height |
| blockHash | String | latest block hash |
| isActive | int | 0 is not activated, 1 is activated |
| isCrossActive | int | 0 is not a cross-chain network, 1 cross-chain network |
| outCount | int | active connection count |
| inCount | int | passive connection count |
| isMoonNet | int | 0 not moon node,1 moon node |
Dependent service
none
Function Description:
The network connection has the height and hash value of the peer node when the +handshake connection is made, and the height and hash value of the subsequent peer connection node are called and updated by the external module (block management module).
Process description
1> Wait for the block management interface after the node starts Initialization, and then call the block management interface to get the latest block height and hash value.
2> When the handshake is performed, the node related information is placed in the Verion information and sent to the peer.
3> After the connection is established, the block management module will call the interface to update the latest block height and hash value.
Interface definition
The block management module calls to update the height of the node and the hash value.
method : nw_updateNodeInfo
Request example
{
+ "method":"nw_updateNodeInfo",
+ "minVersion":1.1,
+ "params":[
+ 1598,
+ "10.20.30.20:8856",
+ 10,
+ "0020ba3f3f637ef53d025d3a8972462c00e84d9ea1a960f207778150ffb9f2c173ff"
+ ]
+}
+Request parameter description
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | chainId | true | int | 网络id |
| 1 | nodeId | true | String | 网络节点id |
| 2 | blockHeight | true | long | 区块高度 |
| 3 | blockHash | true | Sting | 区块最新hash |
返回示例
Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+
+Success
{
+ "version": 1.2,
+ "code":0,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{
+
+ }
+}
+
+
+返回字段说明
| parameter | type | description |
|---|---|---|
Dependent service
none
Function Description:
When the module is started, the configuration information is initialized, the +registration service is initialized, and the initialization of each internal function management database information is performed.
Process description

1> load local configuration data, database node group and node information data loading.
2 > When the status of the listening block management module is initialized and the interface is callable, the call obtains the block height and Hash value of the latest local node.
3> initialization completes and enters peer node connection.
4 > The network module notifies the block management module of the maximum block height and hash value after the connection is stable. The block management module provides interfaces for network module calls.
The criteria for the stability of network module start-up connection are: no new handshake connection occurs in X seconds, and no height increase in X seconds. X=10
5 > After network stabilization, the network is in a working state, and the business state of each chain is released to other modules in an event manner.
Dependent service
none
Function Description:
When the module is closed, the connection is closed, the thread management is +closed, the resources are released, and the status is notified to the core interface.。
Process description

Dependent service
none
Function Description:
After the network module is started, the peer node is managed.
The ways for node acquisition are:
1> Connect to the seed node and request address acquisition.
2> Receive the broadcasted node message.
2> The connection of a cross-chain network, for example, as a connection between a node and a sub-chain on a satellite chain, or a connection between a node on a sub-chain and a satellite chain.
Process description

none
Function Description:
A node acts as the client, actively connecting to a known peer node, and is also a server, waiting for the peer node to connect.
A connection can work normally, and it needs to send a version protocol message to each other through a handshake protocol. For the specific definition of the protocol, see the following.
"Protocol - Network Communication Protocol Part".
Process description
After the TCP connection is complete with the server, the client needs to handshake through the rervice version protocol. Only the connection with successful handshake can forward the service. The state in the connection cannot be transitioned to connected after X minutes, and the connection is actively disconnected.

PS: In order to meet the requirements of one process carrying multiple-chain services at the same time, after a node peer connection is established, multiple NodeGroup services should be satisfied.
That is, the node peer connection and the nodeGroup object are many-to-many, n:n relationships.
Dependent service
none
Function Description:
Check if the connection is still connected. Maintain the keep-alive by ping-pong message from client and server. Refer to the "Protocol - Network Communication Protocol" section for the definition of the ping-pong protocol involved.
Process description

none
Function Description:
When a node connection is established, the number of connections is made, and +if the maximum is reached, the connection is actively disconnected.。
Process description

none
A node may have multiple network cards, or it may be in a local area network. Therefore, when establishing a connection, it does not know its own external network IP address.
The node needs to know its own external network IP address to broadcast its own address for the external network peers to connect. In our design, the external network of the node is carried by the version protocol message.
Process description
When the client receives the version message, it can know its own IP address information.

none
When a node establishes a connection, it can broadcast its own external network IP+port to other nodes. However, if a node is in a local area network, the IP address of the external network cannot be directly connected. Therefore,in order to detect whether the external network IP of the node is +available, you can connect to your own server through your own client. If the connection is successful, the IP can be used for broadcasting. If it is unsuccessful, the external network IP of the node cannot be +broadcast to other nodes.
Process description
Self-connection +may succeed or fail. If it is successful, the external network IP is reachable, and it can be broadcasted to other nodes in the network when the connection is established. If it is unreachable, the connection +cannot be established.。

Dependent service
none
Function Description:
Broadcast +its own nodes to other nodes in the network. In the design, we will +broadcast through the self-connection established above。
Process description
Constraint: The address broadcast is not carried out between peers in the cross-chain +network, that is, the nodes in the satellite chain are not broadcast to the sub-chain, and the nodes in the same sub-chain are found not to be broadcast to the satellite chain. The satellite chain and the sub-chain need to establish a connection. The initial peer node can send a getAdrr message to request the connection address.

none
Function Description:
Request an address protocol message for more network connections
Process description
Request getaddr:
1> When a connection in a nodeGroup does not reach the network service required threshold minAvailableCount, the address list is requested from the seed node.
2> The cross-chain nodeGroup in the satellite chain node can directly request the obtained address from the connected peer node.
Reply getaddr:
1>peer cross-link connection, node reply address list (IP+cross-chain port)
2>peer own network connection, the node will reply to the address list (IP+ own chain port)
Dependent service
Function Description:
Send & Receive network protocol addr protocol message processing logic
Process description
Send addr:
1> When a new node is accessed, an addr message is broadcast to other peers of the same nodegroup.
2> When the getaddr message is requested, the addr message will be replied.
Receive addr:
1> Determine whether the address is already owned locally. If you do not forward it, get the new addr.
2>PEER is not cross-chain network forwarding
3> Own network, add addr>0, store and broadcast forwarding (except receiving peer)
Dependent service
none
[^remark]: Here is the topic of the event, the format protocol of the event (accurate to byte), and the occurrence of the event.
Description: The NodeGroup reaches the lower limit of the number of nodes and the event is advertised.
event_topic : "evt_nw_inNodeLimit",
+ data:{
+ chainId
+ magicNumber
+ nodeCount
+ nodeLimit
+ time
+ }
+
+
+Description: The NodeGroup is less than the lower limit of the number of nodes. The event is advertised.
event_topic : "evt_nw_lessNodeLimit",
+ data:{
+ chainId
+ magicNumber
+ nodeCount
+ nodeLimit
+ time
+ }
+
+
+Description: The node handshake is successful and the event is advertised.
event_topic : "evt_nw_connectSuccess",
+ data:{
+ chainId
+ magicNumber
+ nodeId
+ time
+ version
+ }
+
+
+Description: The node is disconnected and the event is published
event_topic : "evt_nw_nodeDisconnect",
+ data:{
+ chainId
+ magicNumber
+ nodeId
+ time
+ version
+ }
+
+
+ none
+ Used to establish a connection (handshake)
| Length | Fields | Type | Remark |
|---|---|---|---|
| 4 | version | uint32 | Protocol version identifier used by the node |
| 20 | addr_you | byte[20] | The peer network address [IP+PORT1+PORT2] PORT2 is a cross-chain server port. For example: [10.32.12.25 8003 9003] 16byte+2byte+2byte |
| 20 | addr_me | byte[20] | The self network address [IP+PORT1+PORT2] PORT2 is a cross-chain server port. For example: [20.32.12.25 8003 9003] 16byte+2byte+2byte |
| 4 | block_height | uint32 | node latest block height |
| ? | block_hash | varInt | node latest block hash |
| 6 | network_time | uint48 | Network time |
| ?? | extend | VarByte | extended field, no more than 10 bytes |
Used to answer version
| Length | Fields | Type | Remark |
|---|---|---|---|
| 1 | ack_code | uint8 | Return code, 1 means normal, 2 means the connection is full |
Used to maintain the connection. After receiving a message for a certain node for a
+ period of time, the message is sent. If the pong message is received, the node remains connected. Otherwise, the connection is closed and the node is deleted.
| Length | Fields | Type | Remark |
|---|---|---|---|
| 4 | randomCode | uint32 | random number |
reply for ping
+ | Length | Fields | Type | Remark |
|---|---|---|---|
| 4 | randomCode | uint32random number |
Used to obtain connection information of available nodes in the network, no message body
Used to reply getaddr, or announce the existence of itself to the network. After receiving the message, the node determines whether the node is known. If it is an unknown node, it propagates the message to the network.
| Length | Fields | Type | Remark |
|---|---|---|---|
| ?? | addr_list | network address | 18 bytes per node (16 bytes IP + 2 bytes port) |
Used for peer connection to disconnect actively, rejecting service message connection
| Length | Fields | Type | Remark |
|---|---|---|---|
| 1 | byeCode | uint8 | 预留字段 |
none
+ [network]
+ network.self.server.port=8003
+ network.self.chainId=9861
+ network.self.magic=68866996
+ network.self.max.in=100
+ network.self.max.out=10
+ network.self.seed.ip=127.0.0.1:8003
+ #Satellite chain configuration information
+ network.moon.node=true
+ network.moon.server.port=8004
+ network.moon.max.in=100
+ network.moon.max.out=10
+ network.moon.seed.ip=215.159.216.58:8003,215.159.69.140:8003,223.206.200.74:8003
+
+
+[^remark]: Core object class definition, storing data structures,......
[^remark]: Required content not covered above
The random seed you get is a big number, and notice, it could be a negative number
URL:/random/seeds/height
Method:GET
Prams:
| parameter | type | Required | remark |
|---|---|---|---|
| startHeight | Long | True | Initial height of interval |
| endHeight | Long | True | Interval cutoff height, cannot exceed startHeight+1000 |
Returns:
| field | type | Remark |
|---|---|---|
| success | boolean | Successful or not |
| data | array | The seed array |
Example:
Request:
curl -X GET "http://127.0.0.1:8001/api/random/seeds/height?startHeight=500&endHeight=510" -H "accept: application/json"
+Response:
{
+ "success": true,
+ "data": [
+ "8486473738212806059384942122915964966516544811115122625378589706648696927875",
+ "5763677830362183770819418466587054532227472729077319516033962399030101482330",
+ "-21576822359476915572374120992682286995340746526938743512234391635989859550499",
+ "21657748356022199241379814087980601843534504184851063250908405386419429001546",
+ "-31320197741848993348465901825403870475226356831977749494101003161293910010564",
+ "16054257794265746474880657765642725318937086559191102027715411501558318980478",
+ "39222628335763902261547055653161137231901517785016195993008289217415793052023",
+ "28759812140738813907858073405869390691919557824743093132519210315994120629868",
+ "26779511442264535228335930919961858598639368721086477781863239801135250744386",
+ "-23481782415506504277094909296039579696138464413290902597168011374639343982630"
+ ]
+}
+URL:/random/seeds/count
Method:GET
Prams:
| parameter | type | Required | remark |
|---|---|---|---|
| height | Long | True | Gets the maximum height of the seed list |
| count | Long | True | Random seed count, no more than 128 |
Returns:
| field | type | Remark |
|---|---|---|
| success | boolean | Successful or not |
| data | array | The seed array |
Example:
Request:
curl -X GET "http://127.0.0.1:8001/api/random/seeds/count?height=500&count=10" -H "accept: application/json"
+Response:
{
+ "success": true,
+ "data": [
+ "8486473738212806059384942122915964966516544811115122625378589706648696927875",
+ "5763677830362183770819418466587054532227472729077319516033962399030101482330",
+ "-21576822359476915572374120992682286995340746526938743512234391635989859550499",
+ "21657748356022199241379814087980601843534504184851063250908405386419429001546",
+ "-31320197741848993348465901825403870475226356831977749494101003161293910010564",
+ "16054257794265746474880657765642725318937086559191102027715411501558318980478",
+ "39222628335763902261547055653161137231901517785016195993008289217415793052023",
+ "28759812140738813907858073405869390691919557824743093132519210315994120629868",
+ "26779511442264535228335930919961858598639368721086477781863239801135250744386",
+ "-23481782415506504277094909296039579696138464413290902597168011374639343982630"
+ ]
+}
+URL:/random/seed/height
Method:GET
Prams:
| parameter | type | Required | remark |
|---|---|---|---|
| startHeight | Long | True | Initial height of interval |
| endHeight | Long | True | Interval cut-off height,endHeight-startHeight<=1000 |
| algorithm | String | false | The default is sha3 algorithm, supporting sha3, KECCAK, merkle algorithm |
Returns:
| field | type | Remark |
|---|---|---|
| success | boolean | Successful or not |
| data | Object | The result object |
| seed | String | Calculate the random seed result |
| algorithm | String | Computational algorithm |
| count | int | Number of original random seeds |
Example:
Request:
curl -X GET "http://192.168.1.123:8001/api/random/seed/height?startHeight=600&endHeight=610&algorithm=sha3" -H "accept: application/json"
+Response:
{
+ "success": true,
+ "data": {
+ "seed": "49349273589710891971526183625401126395677304794754035539210022261211357904457",
+ "algorithm": "sha3",
+ "count": 10
+ }
+}
+URL:/random/seed/count
Method:GET
Prams:
| parameter | type | Required | remark |
|---|---|---|---|
| height | Long | True | Gets the maximum height of the seed list |
| count | Long | True | Random seed count, no more than 128 |
| algorithm | String | false | The default is sha3 algorithm, supporting sha3, KECCAK, merkle algorithm |
Returns:
| field | type | Remark |
|---|---|---|
| success | boolean | Successful or not |
| data | Object | The result object |
| seed | String | Calculate the random seed result |
| algorithm | String | Computational algorithm |
| count | int | Number of original random seeds |
Example:
Request:
curl -X GET "http://192.168.1.123:8001/api/random/seed/count?height=600&count=10&algorithm=merkle" -H "accept: application/json"
+Response:
{
+ "success": true,
+ "data": {
+ "seed": "49349273589710891971526183625401126395677304794754035539210022261211357904457",
+ "algorithm": "merkle",
+ "count": 10
+ }
+}
+Similar to the above RPC interface, the smart contract SDK supports the same method to obtain the random number seed provided by the underlying blockchain, such as the following code.
+Take one of these methods as an exampleUtils.getRandomSeed(long endHeight, int seedCount, String algorithm) Shows how to generate random Numbers using random number seeds.
/**
+ * [Testnet]According to the cutoff height and the number of original seeds, a specific algorithm is used to generate a random seed
+ *
+ * @param endHeight End height
+ * @param seedCount Number of original seeds
+ * @param algorithm Hash algorithm identification
+ * @return After the original seed byte array is merged, the 32-bit hash byte array is obtained using the hash algorithm and converted to BigInteger(new BigInteger(byte[] bytes))
+ */
+public static native BigInteger getRandomSeed(long endHeight, int seedCount, String algorithm);
+
+/**
+ * [Testnet]According to the height and the original seed number, use the ` SHA3-256 ` hash algorithm to generate a random seed
+ *
+ * @param endHeight End height
+ * @param seedCount Number of original seeds
+ * @return After the original seed byte array is merged, the 32-bit hash byte array is obtained using the hash algorithm and converted to BigInteger(new BigInteger(byte[] bytes))
+ */
+public static BigInteger getRandomSeed(long endHeight, int seedCount) {
+ return getRandomSeed(endHeight, seedCount, "SHA3");
+}
+
+/**
+ * [Testnet]According to the height range, a specific algorithm is used to generate a random seed
+ *
+ * @param startHeight Start height
+ * @param endHeight Number of original seeds
+ * @param algorithm Hash algorithm identification
+ * @return After the original seed byte array is merged, the 32-bit hash byte array is obtained using the hash algorithm and converted to BigInteger(new BigInteger(byte[] bytes))
+ */
+public static native BigInteger getRandomSeed(long startHeight, long endHeight, String algorithm);
+
+/**
+ * [Testnet]According to height, use ` SHA3-256 ` hash algorithm to generate a random seed
+ *
+ * @param startHeight Start height
+ * @param endHeight End height
+ * @return After the original seed byte array is merged, the 32-bit hash byte array is obtained using the hash algorithm and converted to BigInteger(new BigInteger(byte[] bytes))
+ */
+public static BigInteger getRandomSeed(long startHeight, long endHeight){
+ return getRandomSeed(startHeight, endHeight, "SHA3");
+}
+
+/**
+ * [Testnet]According to the cutoff height and the number of original seeds, the collection of original seeds was obtained
+ *
+ * @param endHeight End height
+ * @param seedCount Number of original seeds
+ * @return Returns a collection of original seeds, whose elements are BigInteger converted from byte arrays(new BigInteger(byte[] bytes))
+ */
+public static native List<BigInteger> getRandomSeedList(long endHeight, int seedCount);
+
+/**
+ * [Testnet]Get the set of original seeds according to the height range
+ *
+ * @param startHeight Start height
+ * @param endHeight End height
+ * @return Returns a collection of original seeds, whose elements are BigInteger converted from byte arrays(new BigInteger(byte[] bytes))
+ */
+public static native List<BigInteger> getRandomSeedList(long startHeight, long endHeight);
+example shaking at the same time NUtils.getRandomSeed(long endHeight, int seedCount, String algorithm)Refer to the following code
public List<Integer> dice(long endHeight, int count, int range, int times) {
+ BigInteger orginSeed = getRandomSeed(endHeight, count, "sha3");
+ if (orginSeed.equals(BigInteger.ZERO)) {
+ return null;
+ }
+ BigInteger wrapperRange = BigInteger.valueOf((long) range);
+ List<Integer> resultList = new ArrayList<Integer>(times);
+ for (int i = 0; i < times; i++) {
+ if(i == 0) {
+ BigInteger mod = orginSeed.mod(wrapperRange);
+ resultList.add(mod.intValue());
+ } else {
+ BigInteger multiply = orginSeed.multiply(BigInteger.valueOf(i + 1));
+ String s = sha3(multiply.toByteArray());
+ byte[] decode = decode(s);
+ BigInteger bigInteger = new BigInteger(decode);
+ BigInteger mod = bigInteger.mod(wrapperRange);
+ resultList.add(mod.intValue());
+ }
+ }
+ return resultList;
+}
+
+public byte[] decode(String hexString) {
+ byte[] bts = new byte[hexString.length() / 2];
+ for (int i = 0; i < bts.length; i++) {
+ bts[i] = (byte) Integer.parseInt(hexString.substring(2 * i, 2 * i + 2), 16);
+ }
+ return bts;
+}
+Utils.getRandomSeed(long endHeight, int seedCount, String algorithm)Refer to the following code
public List<Integer> diceAnother(long endHeight, int count, int range, int times) {
+ BigInteger orginSeed = getRandomSeed(endHeight, count, "sha3");
+ if (orginSeed.equals(BigInteger.ZERO)) {
+ return null;
+ }
+ BigInteger wrapperRange = BigInteger.valueOf((long) range);
+ List<Integer> resultList = new ArrayList<Integer>(times);
+ BigInteger mod = orginSeed.mod(wrapperRange);
+ resultList.add(mod.intValue());
+ String orginStr = orginSeed.toString();
+ int length = orginStr.length();
+ for (int i = 1; i < times; i++) {
+ int c = orginStr.charAt(length - i);
+ BigInteger multiply = orginSeed.multiply(BigInteger.valueOf(c));
+ String s = sha3(multiply.toByteArray());
+ byte[] decode = decode(s);
+ BigInteger bigInteger = new BigInteger(decode);
+ mod = bigInteger.mod(wrapperRange);
+ resultList.add(mod.intValue());
+ }
+ return resultList;
+}
+
+public byte[] decode(String hexString) {
+ byte[] bts = new byte[hexString.length() / 2];
+ for (int i = 0; i < bts.length; i++) {
+ bts[i] = (byte) Integer.parseInt(hexString.substring(2 * i, 2 * i + 2), 16);
+ }
+ return bts;
+}
+[TOC]
Data interaction between modules is done through RPC-TOOL
RPC-TOOL is the underlying application, and any module will depend on RPC-TOOL.
Interface description +Kernel will periodically push the status of the current system to each module, which is used for receiving
Request example
{
+ "cmd":"status",
+ "minVersion":1,
+ "params":[
+ {
+ "service":[
+ "a",
+ "b",
+ "c"
+ ],
+ "available":true,
+ "modules":{
+ "moduleABC":{
+ "name":"moduleABC",
+ "status":"READY",
+ "available":false,
+ "addr":"127.0.0.1",
+ "port":19722,
+ "rpcList":[
+ {
+ "cmd":"shutdown",
+ "version":1
+ },
+ {
+ "cmd":"cmd1",
+ "version":1
+ },
+ {
+ "cmd":"conf_reset",
+ "version":1
+ },
+ {
+ "cmd":"terminate",
+ "version":1
+ }
+ ],
+ "dependsModule":[
+ "m2",
+ "m3"
+ ]
+ }
+ }
+ }
+ ]
+}
+Request parameter specification
| index | parameter | required | type | description |
|---|---|---|---|---|
| 0 | modules_information | true | map | All module information |
modules_information
| parameter | required | type | description |
|---|---|---|---|
| service | true | string[] | The dependent modules |
| available | true | boolean | can start service? |
| modules | true | map<name, module> | All module information |
module
| parameter | required | type | description |
|---|---|---|---|
| name | true | string | name |
| status | true | string | status |
| available | true | boolean | can start service? |
| addr | true | string | ip address/host name |
| port | true | int | port |
| rpcList | true | list | cmd list |
| dependsModule | true | string[] | The dependent modules |
Response example +Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+Success
{
+"version": 1.2,
+ "code":0,
+ "result":{}
+}
+Response field specification +N/A
Interface description +Kernel calls the interface to close the module (waiting for all the processing of the current business to complete)
Request example
{
+ "cmd":"shutdown",
+ "minVersion":1,
+ "params":[]
+}
+Request parameter specification
N/A
Response example +Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+Success
{
+ "version": 1.2,
+ "code":0,
+ "result":{}
+}
+Response field specification +N/A
Interface description +Kernel calls the interface to close the module (immediately terminates).
Request example
{
+ "cmd":"terminate",
+ "minVersion":1,
+ "params":[]
+}
+Request parameter specification
N/A
Response example +Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+Success
{
+ "version": 1.2,
+ "code":0,
+ "result":{}
+}
+Response field specification +N/A
Interface description +Kernel gets module configuration items
Request example
{
+ "cmd":"confGet",
+ "minVersion":1,
+ "params":[]
+}
+Request parameter specification
N/A
Response example +Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+Success
{
+ "version": 1.2,
+ "code":0,
+ "result":{
+ "key1": "value1",
+ "key2": "value2"
+ }
+}
+Response field specification +N/A
Interface description +Kernel sets module configuration items
Request example
{
+ "cmd":"confSet",
+ "minVersion":1,
+ "params":[
+ {
+ "key1":"value1",
+ "key2":"value2"
+ }
+ ]
+}
+Request parameter specification
N/A
Response example +Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+Success
{
+ "version": 1.2,
+ "code":0,
+ "result":{}
+}
+Response field specification +N/A
Interface description +Kernel restore template is configured as initial value.
Request example
{
+ "cmd":"confReset",
+ "minVersion":1,
+ "params":[]
+}
+Request parameter specification
N/A
Response example +Failed
{
+ "version": 1.2,
+ "code":1,
+ "msg" :"xxxxxxxxxxxxxxxxxx",
+ "result":{}
+}
+Success
{
+ "version": 1.2,
+ "code":0,
+ "result":{}
+}
+Response field specification +N/A
Start server
// Port is not necessary. If no port is specified, the system is allocated randomly
+BaseRpcServer server = new GrizzlyServer(RpcConstant.KERNEL_PORT);
+
+// Scan the package in which the CMD command is located
+server.scanPackage("io.nuls.rpc.mycmd");
+
+// Initialization
+server.init("moduleName", "dependsModule, type is List<String>");
+
+// start
+server.start();
+Custom CMD
// extends BaseCmd
+public class SomeCmd extends BaseCmd
+
+// Custom method to add annotation CmdInfo
+@CmdInfo(cmd = "cmd1", version = 1.0, preCompatible = true)
+public Object methodName(List params) {
+ System.out.println("I'm version 1");
+ return success();
+}
+
+Note: rpc-tool automatically transfers the Object[] transferred from client to List<Object>.
+There must be and only one CMD class to implement the KernelCmd interface.
// Implement interface
+public class SomeCmd extends BaseCmd implements KernelCmd
+
+/**
+ * Receive all module information from kernel
+ */
+public Object status(List params);
+
+/**
+ * Shut down service: after the existing business is completed
+ */
+public Object shutdown(List params);
+
+/**
+ * Shut down service: close immediately, whether or not the business is completed.
+ */
+public Object terminate(List params);
+
+/**
+ * Provide local configuration information
+ */
+public Object confGet(List params);
+
+/**
+ * Update local configuration information
+ */
+public Object confSet(List params);
+
+/**
+ * Reset local configuration information
+ */
+public Object confReset(List params);
+Provide module information to kernel
RpcClient.versionToKernel();
+call rpc
// CMD corresponds to one interface.
+String jsonStr = RpcClient.callSingleRpc("shutdown", params, minVersion);
+
+// CMD corresponds to multiple interfaces.
+String jsonStr = RpcClient.callMultiplyRpc("shutdown", params, minVersion);
+
+note:
+params is instance of Object[]
+Request
{
+ "cmd": "shutdown",
+ "minVersion": 1.0, //根据自己需要传最低版本号
+ "params": [],
+}
+Response(success and failure are the same)
{
+ "code":0,
+ "msg": " This property is only available when failed",
+ "version": "Actually called version",
+ "result": {}
+}
+BaseCmd has a default implementation of the status method, so if you don't have a specific requirement, you just need to do the following:
@Override
+@CmdInfo(cmd = RpcConstant.STATUS, version = 1.0, preCompatible = true)
+public Object status(List params){
+ return super.status(params);
+}
+There are ways to return to success and failure in BaseCmd.
+success:
protected Object success(double version) {
+ return success(version, null);
+}
+
+protected Object success(double version, Object result) {
+ Map<String, Object> map = new HashMap<>(16);
+ map.put("code", 0);
+ map.put("msg", SUCCESS);
+ map.put("version", version);
+ map.put("result", result);
+ return map;
+}
+fail:
protected Object fail(String code, String msg, double version, Object result) {
+ Map<String, Object> map = new HashMap<>(16);
+ map.put("code", code);
+ map.put("msg", msg);
+ map.put("version", version);
+ map.put("result", result);
+ return map;
+}
+[TOC]
In the NULS 2.0 ecosystem, transactions are traded within the blockchain or between chains and chains. The nodes of each chain not only deal with transactions within the chain, but also deal with cross-chain transactions. So each node needs to process more and more transactions, and more complex, so we need a single but separate module to handle various transactions. And from the architectural design of NULS 2.0, we need a separate module to collecting transactions, verification, storage and forwarding of transactions. For all transactions, these functions are shared and unified,so we designed the transaction management as a separate module.
The core work of transaction management has the following two points:
一、Handling of ordinary transactions
二、Processing cross-chain transactions
The transaction management module needs to perform cross-chain verification on cross-chain transactions, while cross-chain verification involves interaction between different nodes in different chains. There are mainly three types of cross-chain transactions that need to be processed.

The friend chain node initiates a new cross-chain transaction, which is confirmed inside the friend chain. When the friend chain reaches a certain number of confirmation blocks, the friend chain node will send the cross-chain transaction to the NULS mainnet nodes. For example, the friend chain node A sends the cross-chain transaction to the NULS mainnet node S, and the node S sends the transaction to the node other than the node A in the friend chain for verification. The NULS mainnet node S will receive the verification result of multiple friend chain nodes, and then calculate the node S's own cross-chain verification result, and then broadcast it to other nodes of the NULS mainnet, so each node of the NULS mainnet will The verification result of all other nodes is received, and finally the final verification result of the NULS mainnet is calculated.

The NULS main-net node initiates a new cross-chain transaction. When a certain number of confirmation blocks is reached in the NULS mainnet, the transaction management module will take out the cross-chain transaction and send it to the target chain. For example, the NULS mainnet node S sends the transaction to the target chain node A, and the target chain node A will send the transaction to the NULS mainnet except the node S for verification. After the A node obtains the results of multiple NULS mainnet nodes, it calculates the final cross-chain verification result of the A node and broadcasts it to the target chain. The nodes of the target chain will receive the results of all other nodes, and then calculate the final verification result of the target chain.
Since the transaction protocol between the friends chain may be incompatible, the transaction between them needs to be transferred by the NULS mainnet. The process of sending a friend chain to another friend chain is actually to complete the transaction of the friend chain to the NULS mainnet, and the NULS mainnet sends the transaction to the friend chain. The transaction management module plays the same role.
Transaction management controls the verification and circulation of all transactions throughout the system.
The following modules need to be used during normal operation.


The module is divided into three parts: interface, implementation layer, local storage
The implementation layer contains 4 parts:

The basic data of other modules needs to be obtained when the module starts
Maintain the basic data of all chains in the chain management module
The way to get the data is:
Maintain a collection correspondence between transaction and its validator, processor submission interface, and rollback interface with the transaction type as the key.
The way to get the data is:
After each module starts, it calls the transaction management module registration transaction interface to register itself.
Collect new transactions created by each module of this node
Newly created transactions for each module (including cross-chain transactions), collected via the interface newTx provided by the transaction management module, When a new transaction is received, basic verification is performed first, then placed in the local transaction queue to be verified, waiting for the verification process.
Note: There are also cross-chain transactions in the pending local trading queue, which is the local verification process for all transactions.
Collect cross-chain transactions broadcast by other nodes
Cross-chain transactions broadcast by other nodes (provided that the cross-chain transaction has been packaged to confirm a certain height in the chain in which the transaction was created), will be sent by means of network messages, first sent the transaction hash, transaction management module Once received, send a message requesting a full transaction before receiving a full cross-chain transaction. After receiving, the basic verification will also be carried out, and then placed in the cross-chain transaction queue to be verified, waiting for the verification process.
For example: initiate a transaction atx from the a address of the A chain, and transfer aCoin to the B chain b address (A --> NULS mainnet --> B)
That is: other chain addresses cannot initiate transactions in this chain.
(1) Local process of cross-chain Transaction in the A chain
The ledger module create the transfer transaction atx . If the cross-chain transaction is generated, the cross-chain module needs to be called to create the atx_trans of the NULS mainnet protocol and sign.
According to the NULS mainnet protocol, the type, time, remark, and txData are extracted from the atx into the newly generated atx_trans.
Extract the CoinData data. If it is a UTXO model, calculate the actual payment amount based on the assets, input, output, and fee, and generate the NULS mainnet protocol (account balance model) "from"
from_total = input_utxo_total - output_utxo(not change) - fee
Recalculate the "to" of the NULS mainnet protocol
to = output_utxo(not change)
Note: Consider multi-address transfer. Calculate "from" to the owner of UTXO in input. If it is utxo of multiple addresses, calculate the multiple inputs and the output as the utxo owner.
For example: input has 3 addresses of utxo, transferred to 2 different addresses (not change),and the "from" of the three account balance models is calculated
from_1 = input_utxo1
from_2 = input_utxo2
from_3 = from_total - input_utxo1 - input_utxo2
to_1 = output(not change)_addr_1
to_2 = output(not change)_addr_2
The end result must be:from_total <= input_utxo_total、to_total = output_utxo(total except for change)。
If it is the account balance model, extract the corresponding "from" and "to", and generate CoinData of the NULS mainnet protocol.
The txData of the atx_trans transaction contains the hash of the atx transaction.
Finally, sign the atx_trans transaction and set up scriptSig
The atx_trans cross-chain transaction is sent to the transaction management module via the interface newCrossTx for broadcast. After the atx transfer transaction is generated in the A chain, it is sent to the transaction management module, and the basic format and legality of the transaction data are basically verified by the newTx interface, and then stored in the local transaction queue to be verified.
Receive transaction to deserialize data
Verify the basic format, legality, and integrity of Transaction data
Check the basic format, legality, and integrity of the chain and asset in coinData
The task that validates the transaction will take the transaction from the queue. First, the coinData is verified by the ledger module. After the verification, the corresponding transaction validator is found from the cache with the transaction type, and then the verification interface is called to verify. The verified transaction is broadcasted to other nodes in the chain through newHash, and the transaction atx_trans of the mainnet protocol is broadcasted through newCrossHash, and will be placed in the transaction management module to be packaged in the transaction memory pool, waiting for the consensus package.
Check out the pending transaction at regular intervals
CoinData is verified by calling the account module interface
Verify the transaction by calling the validator interface of the transaction
Verify that the passed transaction is placed in the transaction memory pool to be packaged
When the consensus needs to be packaged, the tx_packableTxs interface is called to obtain the packageable transaction set according to the chain id, the specified end packing time, and the maximum capacity value of the transaction data. At this time, the transaction management module obtains the transaction from the transaction memory pool to be packaged, and then performs the transaction. verification.
First, take a transaction from the transaction memory pool to be packaged, and then perform a separate verification process (which is basically the same as step 2), and then put the corresponding collection by module.
This process is repeated until the specified end packing time or transaction maximum capacity value is reached.
According to the unified verifier of the ledger module, the CoinData of all transactions is verified at one time, the unverified transaction is obtained, and the unverified transaction is filtered out. and the transaction set of each module is verified according to each module unified transaction validator, and the unverified verification is obtained. The transaction then summarizes the results and then returns a packageable transaction set to the consensus module.
After the packaged block is verified, the block management module will call the tx_commit submission interface corresponding to the transaction, call the account module interface to update the balance and other book data, and finally call the save transaction interface tx_save, which means that the transaction is blocked. Chain confirmation.
PS: If a transaction is a non-cross-chain transaction, the normal transaction process is completed by this step.
(2) Cross-chain transactions enter the cross-chain process
The transaction management module of the A-chain node will always scan the cross-chain transactions in the blockchain. When the atx transaction is confirmed by the blockchain to confirm n heights, the A-chain node transaction management module sends a message to send the atx_trans transaction to the connected NULS mainnet nodes
Send cross-chain transaction process:
The NULS mainnet node transaction management module deserializes the atx_trans transaction and then performs a check.
For cross-chain verification, the NULS primary network node Mn will send atx_hash (transaction hash before protocol conversion) and atx_trans_hash (complete transaction hash after protocol conversion received by NULS mainnet) through the message interface verifyFc to the node except the Anode1 in the node connected to the A chain to verify the atx_trans transaction.
Verification logic of node Anode2 performing verification in A chain:
After the above two verifications, the node Anode2 will send the atx_trans_hash and the acknowledgement height to the NULS mainnet node Mn through verifyResult.
Note : When the NULS mainnet node sends the cross-chain verification message verifyFc to the A-chain node group through the network module, the transaction management will cache the node information of successful transmission and failure. If the number of nodes successfully sent is less than S (the connection between Mn and A-chain) 51% of the number of nodes is resent to the failed node until S is not less than 51%.
The NULS mainnet node Mn (consensus node) receives the message that the A chain node Anode2 verifies the transaction atx_trans, and sends it to the transaction management through the transaction management verifyResult interface. The transaction management will store the verification result with the successfully sent node. After Mn receives all the verification results sent by the self, it calculates the percentage of the verification pass. If more than 51% of the nodes of all the link nodes pass the verification, the node Mn determines that the verification of the transaction atx_trans is passed, The node that failed to send is considered as failed to pass the verification.
Summary: The number of verification results received by the node Mn cannot be less than S. If it is less than S, the verifyFc is resent to the node that has not responded to the result. The ordinary node of the NULS mainnet queries any node of the A chain, and the mainnet consensus node queries all nodes of the A chain. The normal node is deemed to have passed the transaction and forwarded the transaction if it is confirmed by any three nodes.
The consensus node Mn signs the cross-chain transaction atx_trans_hash and broadcasts the hash and signature data to the NULS mainnet through the crossNodeRs.
The NULS mainnet consensus nodes receive messages sent by all other consensus nodes, and are collected and summarized by the transaction management module interface crossNodeRs. When the signer of a transaction exceeds 80% of the total number of consensus nodes, it is determined that the cross-chain transaction passed the verification of the mainnet, put in the transaction memory pool to be packaged, and wait for the package confirmation.
When the NULS mainnet node consensus module is to be packaged, the transaction module first takes the transaction (similar to step 4) and verifies the number of signatures of the cross-chain transaction atx_trans again (PS: Since the extracted transaction set contains transactions created by the NULS mainnet, such transactions do not have the step of verifying the number of signatures). CoinData is then verified by the ledger module, and if the transaction meets the requirements, the consensus module is sent into the block.
(3) Cross-chain transactions into the process of the B chain
The transaction management module of the NULS mainnet node will always scan the cross-chain transactions in the blockchain. When the atx_trans transaction is found to be n heights by the blockchain, the atx_trans transaction is sent out to the connected B-chain nodes
Send a cross-chain transaction process (similar to step 7):
The B-node node Bnode1 transaction management module sends the atx_trans transaction hash (which has been obtained in step 14-2) through verifyMn to the node other than Mn in the node connected to the NULS mainnet to verify the atx_trans transaction.
Verification logic of node Mn2 performing verification in NULS mainnet:
After verification, node Mn2 will send the atx_trans_hash and the acknowledgement height to the B-chain node Bnode1 via verifyResult.
When the B-chain node sends the cross-chain verification message verifyMn to the NULS mainnet node group through the network module, the transaction management will cache the node information of the successful transmission and the failure. If the number of successfully sent nodes is smaller than S (S is 51% of the number of nodes connected to the NULS mainnet by Node Bnode1), the information is resent to the failed node. Until S is not less than 51%.
(Similar to step 10) The B-chain node Bnode1 receives the message that the mainnet node Mn verifies the transaction atx_trans, and sends it to the transaction management through the transaction management verifyResult interface, Transaction management caches the verification results against the successful nodes that were sent. After receiving all the verification results sent by the self, Bnode1 calculates the percentage of the verification pass. If more than 51% of the nodes pass the verification, the node Bnode1 determines that the verification of the transaction atx_trans is passed (The node that failed to send is considered as not passing).
After the verification is passed, the transaction management module calls the cross-chain module to convert the atx_trans transaction through the protocol to generate the B-chain protocol transaction btx and broadcast it to the B-chain network through the crossNodeRs. If the Bnode1 node is the B-chain nearest x-block outperger (POW needs Adaptation), the transaction needs to be signed and broadcast to the B-chain network via the crossNodeRs.
The B-chain node receives the messages sent by other nodes, collects and summarizes the transaction management module interface crossNodeRs, and counts the signature of the transaction. When the signer reaches 80% of the latest 20 blockers, the transaction is verified and placed. Enter the packaged transaction memory pool and wait for the package confirmation (The packager also confirms the transaction and the packaged transaction contains all signatures).
(Similar to step 13)When the B-chain node consensus module is packaged, the transaction module first takes out the transaction consistently, verifies the signature number of the transaction btx again, and then verifies the CoinData through the account book module. If the requirements are met, the transaction transmission consensus module is packaged into the block.
When the new block verification is finalized, the entire cross-chain transaction process is completed.
Function description
The transaction type of each module, the corresponding transaction validator and the processor interface are cached.
Process description
When the NULS mainnet is started, each module needs to register its transaction type, validator and other information with the transaction management module. The transaction management module will cache each transaction and the corresponding validator and processor interface. When a new transaction needs to be verified by the validator, the transaction management module will take out the corresponding validator interface name and call the validator interface for verification.
Interface definition
method: tx_register
Interface description:The registration transaction needs to pass the transaction type, the verifier name, and the processor name to return whether the registration is successful.
Request
{
+ "cmd": "tx_register",
+ "minVersion": "1.0",
+ "params":[
+ "moduleCode",
+ "moduleValidateCmd",
+ [
+ [
+ "txType",
+ "validateCmd",
+ "commitCmd",
+ "rollbackCmd",
+ "systemTx",
+ "unlockTx",
+ "verifySignature"
+ ],
+ [
+ "txType",
+ "validateCmd",
+ "commitCmd",
+ "rollbackCmd",
+ "systemTx",
+ "unlockTx",
+ "verifySignature"
+ ]
+ ]
+ ]
+}
+Request parameter
| index | type | description |
|---|---|---|
| 0 | String | Module code |
| 1 | String | Module unified verifier interface name |
| 2 | Array | Module transaction registration information list |
Object of the module transaction registration information list
| index | type | description |
|---|---|---|
| 0 | int | Transaction Type |
| 1 | String | Single transaction validator interface name |
| 2 | String | Transaction processor submit interface name |
| 3 | String | Transaction processor rollback interface name |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "value":true
+ }
+}
+Return
| parameter | type | description |
|---|---|---|
| value | boolean | Success |
Module unified transaction verifier interface specification
Request
{
+ "cmd": "",
+ "minVersion": "1.0",
+ "params":["chianId", ["txHex","txHex","txHex"]]
+}
+Request parameter
| index | type | description |
|---|---|---|
| 0 | chianId | Chian Id |
| 1 | array | Transaction serialization data array |
Response
{
+ "version": 1.0,
+ "code":0,
+ "result":{
+ "list":["txHex", "txHex", "txHex"]
+ }
+}
+| parameter | type | description |
|---|---|---|
| list | jsonArray | Verify the failed transaction serialization data array |
Transaction validator interface uniform specification
Request
{
+ "cmd": "",
+ "minVersion": "1.0",
+ "params":["chainId","txHex"]
+}
+Request parameter
| index | type | description |
|---|---|---|
| 0 | int | chainId |
| 1 | String | Transaction serialization data |
Response
{
+ "version": 1.0,
+ "code":0,
+ "result":{
+ "value":true
+ }
+}
+| parameter | type | description |
|---|---|---|
| value | boolean | Verification passed return true |
Transaction processor commit interface uniform specification
Request
{
+ "cmd": "",
+ "minVersion": "1.0",
+ "params":["chainId","txHex","secondaryDataHex"]
+}
+Request parameter
| index | type | description |
|---|---|---|
| 0 | int | Chain Id |
| 1 | String | Transaction serialization data |
| 2 | String | Block header hash, height, time serialization data |
Response
{
+ "version": 1.0,
+ "code":0,
+ "result":{
+ "value":true
+ }
+}
+| parameter | type | description |
|---|---|---|
| value | boolean | Commit successfully returns true |
Transaction processor rollback interface uniform specification
Request
{
+ "cmd": "",
+ "minVersion": "1.0",
+ "params":["txHex","secondaryDataHex"]
+}
+Request parameter
| index | type | description |
|---|---|---|
| 0 | int | Chain Id |
| 1 | String | Transaction serialization data |
| 2 | String | Block header hash, height, time serialization data |
Response
{
+ "version": 1.0,
+ "code":0,
+ "result":{
+ "value":true
+ }
+}
+| parameter | type | description |
|---|---|---|
| value | boolean | Rollback successfully returns true |
Function description:
Collect newly created transactions from other modules of this node
Process description
When other modules in a node have new transactions, you need to call this interface for unified collection and processing. The transaction management module will place the new transaction in the unconfirmed queue and wait for the transaction thread to process it.
Basic verification of transactions, removal of duplicate transactions, illegally discarding
Put in pending verification local transation queue
Interface definition
method: newTx
Interface description:Receive a new transaction serialization data
Requset
{
+ "cmd": "newTx",
+ "minVersion": "1.0",
+ "params": ["chainId", "txHex"]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | int | Chain Id |
| 1 | String | Transaction serialization data |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "value":true
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| value | boolean | Success |
Function description:
Extract a packaged transaction list based on the packaging end time and transactions total size
Process description
When the node needs to be packaged, the packaged transaction is obtained according to the chain id, the specified end packing time and transactions total size. The transaction management module will take out the corresponding transaction set from the transaction memory pool to be packaged, and then verify the coinData of all transactions in the collection from the account module at one time, filter out the unverified transaction, obtain the verified collection, and then unify through each module. The transaction validator verifies the transaction set of the respective module and then summarizes the results back to the packageable transaction list.
Interface definition
method: tx_packableTxs
Interface description:Return a packaged transaction list
Requset
{
+ "cmd": "tx_packableTxs",
+ "minVersion": "1.0",
+ "params": ["chainId", "endtimestamp", "maxTxDataSize"]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | int | Chain Id |
| 1 | long | End packaging timestamp |
| 2 | int | Transactions total size |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "list":[]
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| list | Transaction | Transaction list |
Function description:
Execute the transaction processor commit
Process description
The transaction commit interface is invoked when the transaction is packaged into a block and the block validation passes
Interface definition
method: tx_commit
Interface description:Call the transaction handler commit interface
Requset
{
+ "cmd": "tx_commit",
+ "minVersion": "1.0",
+ "params": ["chainId", "txHex", "secondaryData"]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | int | Chain Id |
| 1 | String | Transaction serialization data |
| 2 | String | Block header hash, height, time serialization data |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "value":true
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| value | boolean | Success |
Function description:
Execute transaction processor rollback
Process description
The transaction rollback interface is invoked when the transaction is packaged into a block and the block verification fails, or the block is rolled back and the transaction is not a cross-chain transaction.
Interface definition
method: tx_rollback
Interface description:Call the transaction handler rollback interface
Requset
{
+ "cmd": "tx_rollback",
+ "minVersion": "1.0",
+ "params": ["chainId", "txHex", "secondaryData"]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | int | Chain Id |
| 1 | String | Transaction serialization data array |
| 2 | String | Block header hash, height, time serialization data |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "value":true
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| value | boolean | Success |
Function description:
Save the transaction in the new block that was verified to the database
Process description
When the block management saves the block, the transaction is sent to the transaction management module for saving.
Interface definition
method: tx_save
Requset
{
+ "cmd": "tx_save",
+ "minVersion": "1.0",
+ "params": ["chainId", ["txHex", "txHex"]]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | int | Chain Id |
| 1 | array | Transaction serialization data array |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "value":true
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| value | boolean | Success |
Function description:
Get the transaction that have been packaged into the block from the database
Interface definition
method: tx_getTx
Interface description:return transaction serialization data
Requset
{
+ "cmd": "tx_getTx",
+ "minVersion": "1.0",
+ "params": ["chainId", "txHash"]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | int | Chain Id |
| 1 | String | Transaction hash |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "tx":"txHex"
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| tx | String | Transaction serialization data |
Function description:
Delete transactions that have been packaged into blocks from the database, block rollback, etc.
Interface definition
method:tx_delete
Interface description:return execution result
Requset
{
+ "cmd": "tx_delete",
+ "minVersion": "1.0",
+ "params": ["chainId", "txHash"]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | int | Chain Id |
| 1 | String | Transaction hash |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "value":true
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| value | boolean | Success |
Function description:
Local validation of transactions (including cross-chain transactions), including calling the validator, verifying the coinData. Cross-chain verification of cross-chain transactions is not included.
Interface definition
method:tx_verify
Interface description:return execution result
Requset
{
+ "cmd": "tx_verify",
+ "minVersion": "1.0",
+ "params": ["chainId", "txHex"]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | int | Chain Id |
| 1 | String | Transaction serialization data |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "value":true
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| value | boolean | Success |
Function description:
Receive a message of a new transaction hash broadcast by other nodes in the chain
Interface definition
method:newHash Receive new transaction hash message
Interface description:Receive transaction hash serialization data
Requset
{
+ "cmd": "newHash",
+ "minVersion": "1.0",
+ "params": ["chainId", "txHashHex"]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | int | Chain Id |
| 1 | String | Transaction hash hex data |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "value":true
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| value | boolean | Success |
Function description:
Receive messages for new cross-chain transaction hashes sent by other chains
Process description
When a cross-chain transaction has been confirmed to a certain height within the chain, it will be sent by the transaction module to the target chain (NULS mainnet or the friend chain), and the target chain will receive the transaction for verification. The hash of the transaction is sent first before the transaction is sent, and the interface will receive the hash.
Interface definition
method: newCrossHash Receive new cross transaction hash
Interface description:Receive a new transaction hash hex
Requset
{
+ "cmd": "newCrossHash",
+ "minVersion": "1.0",
+ "params": ["chainId", "nodeId", "txHashhex"]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | int | Chain Id |
| 1 | int | Node Id |
| 2 | String | Transaction hash hex data |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "value":true
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| value | boolean | Success |
Function description:
Processing message for new cross-chain transactions sent from other chains to the NULS mainnet
Process description
When the NULS mainnet node receives the cross-chain transaction hash of other chain broadcasts, it will request the complete transaction from the sent hash node. At this time, the node will send the complete transaction and the original hash to the NULS mainnet node.
Interface definition
method: newFcTx Receive new cross transaction
Interface description:Receive a new full cross-chain transaction, and the original hash of the transaction (The hash value of the transaction before the conversion of the friend chain agreement).
Requset
{
+ "cmd": "newFcTx",
+ "minVersion": "1.0",
+ "params": ["chainId", "nodeId", "txHex"]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | Int | Chain Id |
| 1 | int | Node Id |
| 2 | String | Original transaction hash,and transaction serialization data of NULS mainnet protocol after protocol conversion |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "value":true
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| value | boolean | Success |
Function description:
Processing message for new cross-chain transactions sent from the NULS mainnet to the friend chain
Process description
When the friend chain node receives the cross-chain transaction hash broadcast by the NULS mainnet, it will request a complete transaction from the sent hash node, and the node will send the complete transaction partner chain node.
Interface definition
method: newMnTx Receive new mainnet cross transaction
Interface description:Transaction serialization data hex
Requset
{
+ "cmd": "newMnTx",
+ "minVersion": "1.0",
+ "params": ["chainId", "nodeId", "txHex"]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | Int | Chain Id |
| 1 | int | Node Id |
| 2 | String | Transaction serialization data |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "value":true
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| value | boolean | Success |
Function description:
Take a complete cross-chain transaction with a certain height confirmed according to the transaction hash, and then send it back by message.
Process description
NULS mainnet has new cross-chain transactions sent to the target chain (or the ordinary chain has a cross-chain transaction sent to the NULS mainnet), the hash is sent to the target chain first, and the target chain node requests a complete transaction from the NULS mainnet according to the hash, and the interface processes the message.
Interface definition
method: askCrossTx send cross transaction
Interface description:Receiving the transaction hash sent by the network node
Requset
{
+ "cmd": "askCrossTx",
+ "minVersion": "1.0",
+ "params": ["chainId", "nodeId", "txHash"]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | Int | Chain Id |
| 1 | int | Node Id |
| 2 | String | Transaction hash hex data |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "value":true
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| value | boolean | Success |
Function description:
The friend chain node receives the message of the cross-chain verification request of the NULS mainnet node
Process description
The NULS mainnet node newly receives the cross-chain transaction, and will verify the transaction to the friend chain (nodes other than the sender) that sent the transaction, and the message to be sent will be processed by the interface.
Interface definition
method: verifyFc
Interface description:Receive cross-chain transaction hash and original hash of the transaction, return confirmation result through network message
Requset
{
+ "cmd": "verifyFc",
+ "minVersion": "1.0",
+ "params": ["chainId", "nodeId", "txHashHex"]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | Int | Chain Id |
| 1 | int | Node Id |
| 2 | String | [txOriginalHash] Raw transaction hash (before protocol conversion) , [txCrossHash] Cross-chain transaction hash (after protocol conversion) |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "value":true
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| value | boolean | Success |
Function description:
The NULS mainnet node receives the message of the cross-chain verification request of the friend chain node
Process description
The friend chain node newly receives the cross-chain transaction, and will verify the transaction to the NULS mainnet node (node other than the sender) that sent the transaction, and the message to be sent during the verification is processed by the interface.
Interface definition
method: verifyMn
Interface description:receive cross-chain transaction hash, return confirmation result via network message
Requset
{
+ "cmd": "verifyMn",
+ "minVersion": "1.0",
+ "params": ["chainId", "nodeId", "txHash"]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | Int | Chain Id |
| 1 | int | Node Id |
| 2 | String | Transaction hash hex data |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "value":true
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| value | boolean | Success |
Function description:
Process messages that receive cross - chain transaction validation result
Process description
The NULS mainnet verifies cross - chain transactions to other chain nodes, which send verification results
Interface definition
method: verifyResult cross result
Interface description:receive cross-chain transaction verification results
Requset
{
+ "cmd": "verifyResult",
+ "minVersion": "1.0",
+ "params": ["chainId", "nodeId", "rsHex"]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | Int | Chain Id |
| 1 | int | Node Id |
| 2 | String | Transaction hash and confirmation of highly serialized data |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "value":true
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| value | boolean | Success |
Function description:
Receive in-chain node verification results for cross-chain transactions and statistics.
Process description
The node performs cross-chain verification on a cross-chain transaction, and obtains the cross-chain verification result of the node for the transaction. The node broadcasts the result to other nodes of the chain, and the other node will invoke the interface after receiving the message.
Interface definition
method: crossNodeRs cross tx node result
Interface description:receive sender's signature, cross-chain transaction hash, node verification result
Requset
{
+ "cmd": "crossNodeRs",
+ "minVersion": "1.0",
+ "params": ["chainId", "nodeId", "nodeRsHex"]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | Int | Chain Id |
| 1 | int | Node Id |
| 2 | String | Sender's signature, cross-chain transaction hash, node verification result Serialization data |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "value":true
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| value | boolean | Success |
Function description:
View data in the transaction memory pool
Interface definition
method: tx_getTxsInfo
Interface description:Statistics transaction memory pool data
Requset
{
+ "cmd": "tx_getTxsInfo",
+ "minVersion": "1.0",
+ "params": ["chainId"]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | Int | Chain Id |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "localTxCount":111,
+ "crossChainTxCount":111,
+ "pushingCount":111
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| localTxCount | int | Number of local transactions |
| crossChainTxCount | int | Number of cross-chain transactions |
| pushingCount | int | Number of transactions to be packaged |
Function description:
Returns the relationship list of the transaction and its corresponding commit processor and rollback processor
Interface definition
method: tx_getTxProcessors
Interface description:return Map<List<String>> jsonObject
Requset
{
+ "cmd": "tx_getTxProcessors",
+ "minVersion": "1.0",
+ "params": ["txType"]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | int | Transaction type (Fill in NULL to return all types) |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "2":["commitCmd","rollbackCmd"],
+ "3":["commitCmd","rollbackCmd"],
+ "4":["commitCmd","rollbackCmd"]
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| 0 | String | Commit interface name |
| 1 | String | Rollback interface name |
Function description:
Query the transaction list based on conditions such as account, chain, asset, and paging information.
Interface definition
method: tx_getTxs
Interface description:return Page<Transaction>
Requset
{
+ "cmd": "tx_getTxs",
+ "minVersion": "1.0",
+ "params": [
+ "ChainId",
+ "assetId",
+ "type",
+ "Nse7PfBkqtByKJ6AuxY151n1CM2xxxx",
+ "pageSize",
+ "pageNumber"
+ ]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | int | Chain Id |
| 1 | int | AssetId |
| 2 | int | Transaction type (Fill in NULL to return all types) |
| 3 | String | Address |
| 4 | int | Page size |
| 5 | int | Page number |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "pageNumber": 1,
+ "pageSize": 10,
+ "total": 31,
+ "pages": 4,
+ "list": []
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| pageNumber | int | Page number |
| pageSize | int | Page size |
| total | int | Total number of records |
| pages | int | Total page number |
| list | Page | Records |
Function description:
Collect a complete transaction for the new NULS mainnet protocol for broadcast
Interface definition
method: newCrossTx
Requset
{
+ "cmd": "newCrossTx",
+ "minVersion": "1.0",
+ "params": ["chainId", "txHex"]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | int | Chain Id |
| 1 | String | Transaction serialization data |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ value:true
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| value | boolean | Success |
Function description:
Run a new subchain locally
Interface definition
method: tx_runChain
Interface description:run a new subchain locally
Requset
{
+ "cmd": "tx_runChain",
+ "minVersion": "1.0",
+ "params": ["chainId"]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | Int | chainId |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "value":true
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| value | boolean | Success |
Function description:
Stop a running subchain locally
Interface definition
method: tx_stopChain
Interface description:Stop a running subchain locally
Requset
{
+ "cmd": "tx_stopChain",
+ "minVersion": "1.0",
+ "params": ["chainId"]
+}
+Requset parameter
| index | type | description |
|---|---|---|
| 0 | int | Chain Id |
Response
Success
{
+ "code":0,
+ "version": 1.0,
+ "msg": "Success",
+ "result": {
+ "value":true
+ }
+}
+Result
| parameter | type | description |
|---|---|---|
| value | boolean | Success |
nothing
Chain registration event
Chain information interface for sending verification tx coinData
Chain logout event
Confirmation for terminating the chain transaction
Broadcast new cross-chain trading hash
Message description:Messages sent when a cross-chain transaction needs to be broadcast to nodes of other nodes or other chains after the chain is confirmed
cmd:newCrossHash
| Length | Fields | Type | Remark |
|---|---|---|---|
| 2 | chainId | uint16 | Chain Id |
| 1 | digestAlgType | byte | Abstract algorithm identifier |
| ? | hashLength | VarInt | Hash array length |
| ? | hash | byte[] | Hash array |
Message processing
| Length | Fields | Type | Remark |
|---|---|---|---|
| 2 | chainId | uint16 | Chain Id |
| 1 | digestAlgType | byte | Abstract algorithm identifier |
| ? | hashLength | VarInt | Hash array length |
| ? | hash | byte[] | hash |
| Length | Fields | Type | Remark |
|---|---|---|---|
| 2 | chainId | uint16 | Chain Id |
| 2 | type | uint16 | Transaction type |
| 4 | time | uint32 | Transaction date |
| ? | txData | VarByte | Transaction txData |
| ? | coinData | VarByte | Transaction coinData |
| ? | remark | VarString | Remark |
| ? | scriptSig | VarByte | Digital script or transaction signature |
| 1 | originalHashDigestAlgType | byte | Abstract algorithm identifier |
| ? | originalHashLength | VarInt | Hash array length |
| ? | originalHash | byte[] | originalHash友链原始交易hash |
| Length | Fields | Type | Remark |
|---|---|---|---|
| 2 | chainId | uint16 | Chain Id |
| 1 | digestAlgType | byte | Abstract algorithm identifier |
| ? | hashLength | VarInt | Hash array length |
| ? | hash | byte[] | Transaction hash after converting NULS mainnet protocol |
| 1 | originalHashDigestAlgType | byte | Abstract algorithm identifier |
| ? | originalHashLength | VarInt | Original hash array length |
| ? | originalHash | byte[] | Friends chain original transaction hash |
| Length | Fields | Type | Remark |
|---|---|---|---|
| 2 | chainId | uint16 | Chain Id |
| 1 | digestAlgType | byte | Abstract algorithm identifier |
| ? | hashLength | VarInt | Hash array length |
| ? | hash | byte[] | hash |
| 32 | hight | uint32 | Confirm height |
| Length | Fields | Data Type | Remark |
|---|---|---|---|
| 2 | type | uint16 | Transaction type |
| 4 | time | uint32 | Transaction date |
| ? | txData | VarByte | Transaction txData |
| ? | coinData | VarByte | Transaction coinData |
| ? | remark | VarString | Remark |
| ? | scriptSig | VarByte | Digital script or transaction signature |
| Length | Fields | Type | Remark |
|---|---|---|---|
| 32 | chainId | uint16 | Chain Id |
| 1 | digestAlgType | byte | Abstract algorithm identifier |
| ? | hashLength | VarInt | Hash array length |
| ? | hash | byte[] | Converted cross-chain transaction hash |
| Length | Fields | Type | Remark |
|---|---|---|---|
| 2 | chainId | uint16 | Chain Id |
| 1 | digestAlgType | byte | Abstract algorithm identifier |
| ? | hashLength | VarInt | Hash array length |
| ? | hash | byte[] | hash |
| ? | Signature | VarByte | The verified node's signature on the transaction |
| 2 | result | boolean | Validation result |
| Length | Fields | Type | Remark |
|---|---|---|---|
| 2 | chainId | uint16 | Chain Id |
| 1 | digestAlgType | byte | Abstract algorithm identifier |
| ? | hashLength | VarInt | Hash array length |
| ? | hash | byte[] | Hash array |
| Length | Fields | Data Type | Remark |
|---|---|---|---|
| 2 | type | uint16 | Transaction type |
| 4 | time | uint32 | Transaction date |
| ? | txData | VarByte | Transaction txData |
| ? | coinData | VarByte | Transaction coinData |
| ? | remark | VarString | Remark |
| ? | scriptSig | VarByte | Digital script or transaction signature |
[tx-manager]
+bootstrap=io.module.TxManagerModuleBootstrap
+Before reading this article, please read Package Generation
NULS 2.0 is a blockchain project based on modular development. According to the characteristics of the blockchain and the unique NULS POC consensus mechanism, we have built-in accounts, ledger, network, block management, transaction management, consensus, and intelligent contract modules. These modules can meet the normality of the NULS2.0 blockchain node. run. But the underlying module is unlikely to meet all of the business needs. This article will guide developers on how to add their own modules and how to add their own protocols.
Before adding modules, we should first analyze the requirements of the business. We need to know clearly that the added modules only encapsulate and process the existing protocols, or that the existing protocols do not meet the needs of the business and must be added. The logic of the protocol and protocol handles the function.
This article uses api-module and account two developed modules to illustrate how to add their own modules (both modules are JAVA development, can be downloaded at https://github.com/nuls-io/nuls_2.0 Source code reading).
The api-module module is responsible for secondary parsing of the stored block data in the wallet, providing the wallet page and the browser with information that can be displayed. Therefore the module does not require an additional protocol.

The startup class needs to inherit the RpcModule class for easy management of the mykernel core module. After inheritance, you need to implement a unique method, as shown below:

Add dependent modules: If your module needs to call other modules' interfaces to query related data, or if you need other modules to run, your module can run normally, you need to add the dependent modules here. As shown below:

Module initialization: If the module has data that needs to be initialized, it can be implemented here. The init method must call super.init() to ensure that the dependency injection is successful. As shown below:

Start running: Start the running process to start your own service process, return true after the startup succeeds, if the startup fails, the program will return false after catching the exception, and inform the mykernel core module. As shown below:
The dependent module has been started: Going to this step, the modules you depend on have been successfully started, and you can call the interfaces of other modules at this time.
The main function of the api-module module is to query the interfaces of other modules, and then parse the data and return it to the wallet page display. Therefore, the real operation of the module is done in the scheduleManager.start() step. The internal implementation is detailed in the source code.

At this point, the api-module module has successfully joined nusl2.0. Since there is no new protocol, the module only needs to write the business functions of the module itself.
We use the alias trading of the account module to illustrate how to add a new protocol. Alias trading, as its name implies, is that the account sends a transaction with the alias information that the account wants to set. Once the transaction is successfully packaged into the block by the consensus node, it indicates that the account setting alias is successful. The page displays the account alias when the account information is displayed.
Step 1: Add a transaction type
Each transaction requires a separate set of its own transaction type. The transaction type cannot be duplicated with the transaction type of other modules. See the RPC documentation for the transaction types of other modules.
Step 2: Create a transaction logic object
The transaction logic object belongs to the business logic data stored in the transaction, such as the alias information stored in the alias transaction, and the object needs to inherit the TransactionLogicData class. As shown below:

Since the logical data is eventually serialized as a byte array to be broadcast over the network, methods for serialization and deserialization are also needed. As shown below:

Step 3: Create a transaction-related RPC interface. The interface should include creating transactions, verifying transactions, processing transactions, and rolling back transactions.
Users can successfully assemble transactions and broadcast to the entire network by creating a trading interface;
The verification transaction interface will be uniformly called by the transaction management module, and the transaction that fails verification will be discarded;
The verified transaction will be uniformly called by the consensus module to process the transaction interface and stored in the local database;
When there is a block rollback, the block management module uniformly calls the rollback transaction interface to clear the transaction related data stored locally;
For details on the implementation of the code, see: io.nuls.account.rpc.cmd.AliasCmd
Step 4: Start the module registration transaction
When the module is started, you need to register the new transaction of the module with the transaction management module in doStart(), and the corresponding validator and processor, as shown below:


Then, just like api-module, add code related to other business logic in your own module.
Finally, remember to add the module.ncf configuration file under the module's class, as shown below:


+ ← + + Package Generation + + Linux CLI Manual + + → +
NULS smart contract is developed with Java, and it operates in NULS virtual machine. Not all Java features are applicable to contract development and the relevant restrictions are specified in section 3.
NULS smart contract adopts IntelliJ IDEA as development tool
NULS smart contract plug-ins provide the following main functions:
NULS smart contract syntax is a subset of Java syntax, with some restrictions
Main classes of contracts must implement contract interfaces. A smart contract can have a class implementing contract interface only; and other classes and interfaces provide functions for such contract.
Java key words are listed as follows and those not applicable for NULS smart contract will be marked
Access control
Key words and instantiated object of definition class, interface, abstract class, implementation interface and derivative class
Key words of package
Key words of data type
Conditional loops (process control)
Error processing
Modification method, class, property and variables
other
The following syntax is the same with Java and simply listed here under, with specific details referred to the relevant documents of Java
NULS smart contract can be developed with the following class
@View type, Make sure to optimize the contract code as much as possible.a simple contract
Main classes of contract must implement contract interface, and other classes and interfaces provide functions for this contract
+package contracts.examples;
+
+import io.nuls.contract.sdk.Contract;
+import io.nuls.contract.sdk.annotation.Payable;
+import io.nuls.contract.sdk.annotation.Required;
+import io.nuls.contract.sdk.annotation.View;
+
+public class SimpleStorage implements Contract {
+
+ private String storedData;
+
+ @View
+ public String getStoredData() {
+ return storedData;
+ }
+
+ @Payable
+ public void setStoredData(@Required String storedData) {
+ this.storedData = storedData;
+ }
+
+}
+In one contract project, it requires to introduce a jar package “contract-sdk.jar” which provides the class to get block and transaction details +The project has several classes and interfaces
When compiling, packaging and deploying the prepared contract onto the NULS chain, the virtual machine will implement the construction method of this contract to initialize it, and save the contract status onto the chain. The contract status is the member variables of contract class
After the contract is deployed, all public methods of contract class can be called so as to read or modify the contract status
Explanatory comments
@View labels the method of @View. After it is called, the contract status will remain and it can be researched by such means
@Payable labels the method of @Payable. Only when it is called, the amount can be transferred in
@Required labels the parameter of @Required. When it is called, there must be transfer-in value
Go to download NULS source code on github, and get some contract examples
Contract SDK provides several classes to be convenient for contract development:
public class Address {
+
+ private final String address;
+
+ public Address(String address) {
+ valid(address);
+ this.address = address;
+ }
+
+ /**
+ * Get the balance of the address (only the balance of contract address)
+ *
+ * @return
+ */
+ public native BigInteger balance();
+
+ /**
+ * Transfer amount to the address from contract
+ *
+ * @param value transfer amount (in Na)
+ */
+ public native void transfer(BigInteger value);
+
+ /**
+ * Contract method to call the address
+ *
+ * @param Method name
+ * @param Method signature
+ * @param Parameters
+ * @param value Incidental currency (in Na)
+ */
+ public native void call(String methodName, String methodDesc, String[][] args, BigInteger value);
+
+ /**
+ * Call the contract method of this address with a return value(String)
+ *
+ * @param Method name
+ * @param Method signature
+ * @param Parameters
+ * @param value Incidental currency (in Na)
+ * @return return value after calling the contract
+ */
+ public native String callWithReturnValue(String methodName, String methodDesc, String[][] args, BigInteger value);
+
+ /**
+ * Verify the address
+ *
+ * @param address
+ * @see io.nuls.kernel.utils.AddressTool#validAddress(String)
+ */
+ private native void valid(String address);
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Address address1 = (Address) o;
+ return address != null ? address.equals(address1.address) : address1.address == null;
+ }
+
+ @Override
+ public int hashCode() {
+ return address != null ? address.hashCode() : 0;
+ }
+
+ @Override
+ public String toString() {
+ return address;
+ }
+
+}
+public class Block {
+
+ /**
+ * Given block’s head
+ *
+ * @param blockNumber
+ * @return
+ */
+ public static native BlockHeader getBlockHeader(long blockNumber);
+
+ /**
+ * Current block’s head
+ *
+ * @return
+ */
+ public static native BlockHeader currentBlockHeader();
+
+ /**
+ * Newest block’s head
+ *
+ * @return
+ */
+ public static native BlockHeader newestBlockHeader();
+
+ /**
+ * Given block’s hash
+ *
+ * @param blockNumber
+ * @return
+ */
+ public static String blockhash(long blockNumber) {
+ return getBlockHeader(blockNumber).getHash();
+ }
+
+ /**
+ *
+ * CCurrent block’s miner address
+ *
+ * @return
+ */
+ public static Address coinbase() {
+ return currentBlockHeader().getPackingAddress();
+ }
+
+ /**
+ *
+ * Current block’s No.
+ *
+ * @return
+ */
+ public static long number() {
+ return currentBlockHeader().getHeight();
+ }
+
+ /**
+ *
+ * Current block’s time stamp
+ *
+ * @return
+ */
+ public static long timestamp() {
+ return currentBlockHeader().getTime();
+ }
+
+}
+public class BlockHeader {
+
+ private String hash;
+ private long time;
+ private long height;
+ private long txCount;
+ private Address packingAddress;
+ private String stateRoot;
+
+ public String getHash() {
+ return hash;
+ }
+
+ public long getTime() {
+ return time;
+ }
+
+ public long getHeight() {
+ return height;
+ }
+
+ public long getTxCount() {
+ return txCount;
+ }
+
+ public Address getPackingAddress() {
+ return packingAddress;
+ }
+
+ public String getStateRoot() {
+ return stateRoot;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ BlockHeader that = (BlockHeader) o;
+
+ if (time != that.time) return false;
+ if (height != that.height) return false;
+ if (txCount != that.txCount) return false;
+ if (hash != null ? !hash.equals(that.hash) : that.hash != null) return false;
+ if (packingAddress != null ? !packingAddress.equals(that.packingAddress) : that.packingAddress != null)
+ return false;
+ return stateRoot != null ? stateRoot.equals(that.stateRoot) : that.stateRoot == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = hash != null ? hash.hashCode() : 0;
+ result = 31 * result + (int) (time ^ (time >>> 32));
+ result = 31 * result + (int) (height ^ (height >>> 32));
+ result = 31 * result + (int) (txCount ^ (txCount >>> 32));
+ result = 31 * result + (packingAddress != null ? packingAddress.hashCode() : 0);
+ result = 31 * result + (stateRoot != null ? stateRoot.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "BlockHeader{" +
+ "hash='" + hash + '\'' +
+ ", time=" + time +
+ ", height=" + height +
+ ", txCount=" + txCount +
+ ", packingAddress=" + packingAddress +
+ ", stateRoot='" + stateRoot + '\'' +
+ '}';
+ }
+
+}
+/**
+ * Contract interface, implemented by contract class
+ */
+public interface Contract {
+
+ /**
+ * Directly transfer to the contract, this method will be called, no action is done by default. If the contract address is to accept direct transfer, you can override this method and mark the `@Payable` annotation.
+ */
+ default void _payable() {
+ }
+
+}
+/**
+* Event interface, implemented by event class
+*/
+public interface Event {
+}
+public class Msg {
+
+ /**
+ * Remaining gas
+ *
+ * @return
+ */
+ public static native long gasleft();
+
+ /**
+ * sender of the contract
+ *
+ * @return
+ */
+ public static native Address sender();
+
+ /**
+ * The number of Nuls transferred by the contract sender to the contract address, the unit is Na, 1Nuls = 1 billion Na
+ *
+ * @return
+ */
+ public static native BigInteger value();
+
+ /**
+ * Gas price
+ *
+ * @return
+ */
+ public static native long gasprice();
+
+ /**
+ * Contract address
+ *
+ * @return
+ */
+ public static native Address address();
+
+}
+public class Utils {
+
+ private Utils() {
+ }
+
+ /**
+ * Check conditions; if conditions are not met, it will roll back.
+ *
+ * @param expression
+ */
+ public static void require(boolean expression) {
+ if (!expression) {
+ revert();
+ }
+ }
+
+ /**
+ * Check conditions; if conditions are not met, it will roll back
+ *
+ * @param expression
+ * @param errorMessage
+ */
+ public static void require(boolean expression, String errorMessage) {
+ if (!expression) {
+ revert(errorMessage);
+ }
+ }
+
+ /**
+ * Terminate implementation and restore status
+ */
+ public static void revert() {
+ revert(null);
+ }
+
+ /**
+ * Terminate implementation and restore status
+ *
+ * @param errorMessage
+ */
+ public static native void revert(String errorMessage);
+
+ /**
+ * Send events
+ *
+ * @param event
+ */
+ public static native void emit(Event event);
+
+ /**
+ * @param seed a private seed
+ * @return pseudo random number (0 ~ 1)
+ */
+ public static float pseudoRandom(long seed) {
+ int hash1 = Block.currentBlockHeader().getPackingAddress().toString().substring(2).hashCode();
+ int hash2 = Msg.address().toString().substring(2).hashCode();
+ int hash3 = Msg.sender() != null ? Msg.sender().toString().substring(2).hashCode() : 0;
+ int hash4 = Long.valueOf(Block.timestamp()).toString().hashCode();
+
+ long hash = seed ^ hash1 ^ hash2 ^ hash3 ^ hash4;
+
+ seed = (hash * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
+ return ((int) (seed >>> 24) / (float) (1 << 24));
+ }
+
+ /**
+ * @return pseudo random number (0 ~ 1)
+ */
+ public static float pseudoRandom() {
+ return pseudoRandom(0x5DEECE66DL);
+ }
+
+ /**
+ *
+ * Please note that this is the SHA-3 FIPS 202 standard, not Keccak-256.
+ *
+ * @param src source string (hex encoding string)
+ * @return sha3-256 hash (hex encoding string)
+ */
+ public static native String sha3(String hexString);
+
+ /**
+ *
+ * Please note that this is the SHA-3 FIPS 202 standard, not Keccak-256.
+ *
+ * @param bytes source byte array
+ * @return sha3-256 hash (hex encoding string)
+ */
+ public static native String sha3(byte[] bytes);
+
+ /**
+ * [Testnet]verify signature data(ECDSA)
+ *
+ * @param data(hex encoding string)
+ * @param signature(hex encoding string)
+ * @param pubkey(hex encoding string)
+ * @return verify result
+ */
+ public static native boolean verifySignatureData(String data, String signature, String pubkey);
+
+ /**
+ * [Testnet]Generate a random seed with a specific algorithm based on the cutoff block height and the number of original seeds
+ *
+ * @param endHeight the cutoff block height
+ * @param seedCount the number of original seeds
+ * @param algorithm Hash algorithm identifier
+ * @return After the original seed byte array is merged, the hash algorithm is used to get a 32-bit hash byte array, which is then converted into BigInteger(new BigInteger(byte[] bytes)).
+ */
+ public static native BigInteger getRandomSeed(long endHeight, int seedCount, String algorithm);
+
+ /**
+ * [Testnet]Generate a random seed using the `SHA3-256`hash algorithm based on the cutoff block height and the number of original seeds.
+ *
+ * @param endHeight the cutoff block height
+ * @param seedCount the number of original seeds
+ * @return After the original seed byte array is merged, the `SHA3-256` hash algorithm is used to get the 32-bit hash byte array, which is then converted into BigInteger(new BigInteger(byte[] bytes)).
+ */
+ public static BigInteger getRandomSeed(long endHeight, int seedCount) {
+ return getRandomSeed(endHeight, seedCount, "SHA3");
+ }
+
+ /**
+ * [Testnet]Generate a random seed with a specific algorithm based on the block height range
+ *
+ * @param startHeight the starting block height
+ * @param endHeight the cutoff block height
+ * @param algorithm Hash algorithm identifier
+ * @return After the original seed byte array is merged, the hash algorithm is used to get a 32-bit hash byte array, which is then converted into BigInteger(new BigInteger(byte[] bytes)).
+ */
+ public static native BigInteger getRandomSeed(long startHeight, long endHeight, String algorithm);
+
+ /**
+ * [Testnet]Generate a random seed with the `SHA3-256` hash algorithm based on the block height range
+ *
+ * @param startHeight the starting block height
+ * @param endHeight the cutoff block height
+ * @return After the original seed byte array is merged, the `SHA3-256` hash algorithm is used to get the 32-bit hash byte array, which is then converted into BigInteger(new BigInteger(byte[] bytes)).
+ */
+ public static BigInteger getRandomSeed(long startHeight, long endHeight){
+ return getRandomSeed(startHeight, endHeight, "SHA3");
+ }
+
+ /**
+ * [Testnet]Get a collection of raw seeds based on the cutoff block height and the number of original seeds
+ *
+ * @param endHeight the cutoff block height
+ * @param seedCount the number of original seeds
+ * @return returns a collection of original seeds, the element is a BigInteger (new BigInteger(byte[] bytes)))
+ */
+ public static native List<BigInteger> getRandomSeedList(long endHeight, int seedCount);
+
+ /**
+ * [Testnet]Get a collection of raw seeds based on the block height range
+ *
+ * @param startHeight the starting block height
+ * @param endHeight the cutoff block height
+ * @return returns a collection of original seeds, the element is a BigInteger (new BigInteger(byte[] bytes)))
+ */
+ public static native List<BigInteger> getRandomSeedList(long startHeight, long endHeight);
+
+}
+@Payable labels the method of @Payable. Only when it is called, the amount can be transferred in
@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Payable {
+}
+@Required labels the parameter of @Required. When it is called, there must be transfer-in value.
@Target({ElementType.PARAMETER})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Required {
+}
+@Viewlabels the method of @View. After it is called, the contract status will remain and it can be researched by such means
@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface View {
+}
+See parameter structure and simple examples hereafter. See details of other interfaces at [Swagger UI] (http://127.0.0.1:8001/docs#/)
The default port of test network’s “Swagger UI” is 8001, and that of official network is 6001
/api/contract/create| Parameter | Type | Description |
|---|---|---|
| sender* | string | transaction creator |
| password* | string | password of transaction creator |
| gasLimit* | long | max. gas consumption |
| price* | long | unit price of implementation contract |
| contractCode* | string | smart contract code (byte code’s Hex coded string) |
| remark | string | remark |
| args | string[][] | Parameter list |
{
+ "sender": "Nsdz8mKKFMehRDVRZFyXNuuenugUYM7M",
+ "gasLimit": 4687,
+ "price": 20,
+ "password": "xxx",
+ "contractCode": "504b03041400080808003b5aed4c000000000000000000000000090004004d4554412d494e462ffeca00000300504b0708000000000200000000000000504b03041400080808003b5aed4c000000000000000000000000140000004d4554412d494e462f4d414e49464553542e4d46f34dcccb4c4b2d2ed10d4b2d2acecccfb35230d433e0e5722e4a4d2c494dd175aa040958e819c41b9a982868f8172526e7a42a38e71715e417259600d56bf272f1720100504b07089e7c76534400000045000000504b03040a00000800007559ed4c0000000000000000000000000d00000074657374636f6e74726163742f504b03041400080808008359ed4c0000000000000000000000001f00000074657374636f6e74726163742f54657374436f6e74726163742e636c6173737d535d53d350103d9796a684604b2cdf20c5cf365a421110f986225a2cf040c5d1b7b40d25d0264c9232e39bbfc2f147f8a03352189df107f8a31cf7b635744a310f7befeedd73f6dcdd9bdf7f7efc023083bd2e746052801ac4948824a6453cc58c8859cc75827f9f3f7de4de331e9f0fe2b9883e2c04b1c8714bdc2c0b581111c60237ab41acf1754ec0ba800d06bfa99575063973ac9d696a49338beabe6b1b66719121e07c28e7ac12434fca321d5733dd03ad54a1ec6041cf1b65ade430b0b48f44c80c425177776b5c9158bc1d9b3f6515e83494314c7db752cee97656cb956ab5adbc563ad06c83fb8da0df3d32887e24e3ea8e9bb74cd7d6f2ae9a2527d57088b28b6aee373476d37ed393e58bc5d3a429a791863c574c10d339d46dbad592611aee4a2de78041dcb72a765edf3278d5dee60293fc12120630c83074a30c868e6c56404ac2265e08d89210c34b01af24a4312e611baf25c491a1baeb6f93b3f36f2428784cd23947d63ad14d094318943082518681d6be6d548c5241b725ec609740d144b4cec210be4addcb1deb5cc89861a966a5e4a89e50a770a25e091d6c7bbee314a9535aa160eb0e752e4ad36b9bb75ecfa0b68ffeef9ccafc9b7f59738fd40da398365dbda8db848cb48bf3e958f5eb929033fec4f60ea9e5b1ed1b798662ed4ff84003dae9a96e161812b1ebcff0facb6c74781113f4aff481a11f3edad1d4f9bbe6b3a1d830ed3b282ef33179fe1802b4bf8371b2518aa8b4325a3b95ef605f6b29136403b5a082bb64a57a02eee13ead0c0f3c70a201f6c9be56e86413d4e7411fe2512b342c7f69814eb785c6bcaa330da878097f159d55045a8bcf3531881e43dc6358265e7e16228608844b745521cadd573422adc002512c3651853c2afa1d1a5456832aa95c4052e49e733045f69de3961296cf11fa89f0bb0bf42aefa9bb55c8f26d32554428eb9b576c9854032bf05367456a51989ad48f554c61ada978d22bfea4864cfc05504b070818c1191cd20200006f050000504b010214001400080808003b5aed4c0000000002000000000000000900040000000000000000000000000000004d4554412d494e462ffeca0000504b010214001400080808003b5aed4c9e7c7653440000004500000014000000000000000000000000003d0000004d4554412d494e462f4d414e49464553542e4d46504b01020a000a00000800007559ed4c0000000000000000000000000d00000000000000000000000000c300000074657374636f6e74726163742f504b010214001400080808008359ed4c18c1191cd20200006f0500001f00000000000000000000000000ee00000074657374636f6e74726163742f54657374436f6e74726163742e636c617373504b05060000000004000400050100000d0400000000",
+ "remark": "asd",
+ "args": []
+}
+/api/contract/imputedgas/create| Parameter | Type | Description |
|---|---|---|
| sender* | string | transaction creator |
| password* | string | password of transaction creator |
| price* | long | unit price of implementation contract |
| contractCode* | string | smart contract code (byte code’s Hex coded string) |
| args | string[][] | Parameter list |
{
+ "sender": "Nsdz8mKKFMehRDVRZFyXNuuenugUYM7M",
+ "price": 20,
+ "password": "xxx",
+ "contractCode": "504b03041400080808003b5aed4c000000000000000000000000090004004d4554412d494e462ffeca00000300504b0708000000000200000000000000504b03041400080808003b5aed4c000000000000000000000000140000004d4554412d494e462f4d414e49464553542e4d46f34dcccb4c4b2d2ed10d4b2d2acecccfb35230d433e0e5722e4a4d2c494dd175aa040958e819c41b9a982868f8172526e7a42a38e71715e417259600d56bf272f1720100504b07089e7c76534400000045000000504b03040a00000800007559ed4c0000000000000000000000000d00000074657374636f6e74726163742f504b03041400080808008359ed4c0000000000000000000000001f00000074657374636f6e74726163742f54657374436f6e74726163742e636c6173737d535d53d350103d9796a684604b2cdf20c5cf365a421110f986225a2cf040c5d1b7b40d25d0264c9232e39bbfc2f147f8a03352189df107f8a31cf7b635744a310f7befeedd73f6dcdd9bdf7f7efc023083bd2e746052801ac4948824a6453cc58c8859cc75827f9f3f7de4de331e9f0fe2b9883e2c04b1c8714bdc2c0b581111c60237ab41acf1754ec0ba800d06bfa99575063973ac9d696a49338beabe6b1b66719121e07c28e7ac12434fca321d5733dd03ad54a1ec6041cf1b65ade430b0b48f44c80c425177776b5c9158bc1d9b3f6515e83494314c7db752cee97656cb956ab5adbc563ad06c83fb8da0df3d32887e24e3ea8e9bb74cd7d6f2ae9a2527d57088b28b6aee373476d37ed393e58bc5d3a429a791863c574c10d339d46dbad592611aee4a2de78041dcb72a765edf3278d5dee60293fc12120630c83074a30c868e6c56404ac2265e08d89210c34b01af24a4312e611baf25c491a1baeb6f93b3f36f2428784cd23947d63ad14d094318943082518681d6be6d548c5241b725ec609740d144b4cec210be4addcb1deb5cc89861a966a5e4a89e50a770a25e091d6c7bbee314a9535aa160eb0e752e4ad36b9bb75ecfa0b68ffeef9ccafc9b7f59738fd40da398365dbda8db848cb48bf3e958f5eb929033fec4f60ea9e5b1ed1b798662ed4ff84003dae9a96e161812b1ebcff0facb6c74781113f4aff481a11f3edad1d4f9bbe6b3a1d830ed3b282ef33179fe1802b4bf8371b2518aa8b4325a3b95ef605f6b29136403b5a082bb64a57a02eee13ead0c0f3c70a201f6c9be56e86413d4e7411fe2512b342c7f69814eb785c6bcaa330da878097f159d55045a8bcf3531881e43dc6358265e7e16228608844b745521cadd573422adc002512c3651853c2afa1d1a5456832aa95c4052e49e733045f69de3961296cf11fa89f0bb0bf42aefa9bb55c8f26d32554428eb9b576c9854032bf05367456a51989ad48f554c61ada978d22bfea4864cfc05504b070818c1191cd20200006f050000504b010214001400080808003b5aed4c0000000002000000000000000900040000000000000000000000000000004d4554412d494e462ffeca0000504b010214001400080808003b5aed4c9e7c7653440000004500000014000000000000000000000000003d0000004d4554412d494e462f4d414e49464553542e4d46504b01020a000a00000800007559ed4c0000000000000000000000000d00000000000000000000000000c300000074657374636f6e74726163742f504b010214001400080808008359ed4c18c1191cd20200006f0500001f00000000000000000000000000ee00000074657374636f6e74726163742f54657374436f6e74726163742e636c617373504b05060000000004000400050100000d0400000000",
+ "args": []
+}
+/api/contract/call| Parameter | Type | Description |
|---|---|---|
| sender* | string | transaction creator |
| password* | string | password of transaction creator |
| contractAddress* | string | address of smart contract |
| gasLimit* | long | max. gas consumption |
| price* | long | unit price of implementation contract |
| value | long | amount transferred by transaction creator to contract address (Na - 100000000Na=1NULS) |
| methodName* | string | method name |
| methodDesc | string | method signature which may be not transferred if the method name is not repeated |
| remark | string | remark |
| args | string[][] | Parameter list |
{
+ "sender": "Nsdz8mKKFMehRDVRZFyXNuuenugUYM7M",
+ "password": "",
+ "contractAddress": "NseBvPEzerLi3p5Me8Rbm7SeHThVGv1U",
+ "gasLimit": 8000,
+ "price": 20,
+ "value": 0,
+ "methodName": "balance",
+ "methodDesc": "",
+ "remark": "qwe"
+ "args": []
+}
+Swagger UI)/api/contract/imputedgas/callSwagger UI)/api/contract/imputedpriceSwagger UI)/api/contract/deleteSwagger UI)/api/contract/viewSwagger UI)/api/contract/result/{hash}Swagger UI)/api/contract/info/{address}Swagger UI)/api/contract/{address}Swagger UI)/api/contract/balance/{address}Swagger UI)/api/contract/tx/{hash}Swagger UI)/api/contract/tx/list/{address}Swagger UI)/api/contract/limit/{address}/{limit}Swagger UI)/api/contract/amount/{address}/{amount}Swagger UI)/api/contract/transfersegments are as followsFull code:
https://github.com/nuls-io/nuls-vote
package io.nuls.vote.contract;
+
+import io.nuls.contract.sdk.Address;
+import io.nuls.contract.sdk.Contract;
+import io.nuls.contract.sdk.Utils;
+import io.nuls.contract.sdk.annotation.Payable;
+import io.nuls.contract.sdk.annotation.View;
+import io.nuls.vote.contract.func.BaseVote;
+import io.nuls.vote.contract.func.VoteInterface;
+import io.nuls.vote.contract.model.VoteConfig;
+import io.nuls.vote.contract.model.VoteEntity;
+
+import java.math.BigInteger;
+import java.util.List;
+import java.util.Map;
+
+public class VoteContract implements Contract {
+
+ private VoteInterface baseVote;
+
+ public VoteContract(long minRecognizance) {
+ baseVote = new BaseVote(BigInteger.valueOf(minRecognizance));
+ }
+
+ @Payable
+ public VoteEntity create(String title, String desc, String[] items, long startTime, long endTime, boolean isMultipleSelect, int maxSelectCount, boolean voteCanModify) {
+ VoteEntity voteEntity = baseVote.create(title, desc, items);
+
+ VoteConfig config = new VoteConfig(startTime, endTime, isMultipleSelect, maxSelectCount, voteCanModify);
+ boolean success = baseVote.init(voteEntity.getId(), config);
+
+ Utils.require(success);
+
+ return voteEntity;
+ }
+
+ public boolean vote(long voteId, long[] itemIds) {
+ return baseVote.vote(voteId, itemIds);
+ }
+
+ public boolean redemption(long voteId) {
+ return baseVote.redemption(voteId);
+ }
+
+ @View
+ public boolean canVote(long voteId) {
+ return baseVote.canVote(voteId);
+ }
+
+ @View
+ public VoteEntity queryVote(long voteId) {
+ return baseVote.queryVote(voteId);
+ }
+
+ @View
+ public Map<Address, List<Long>> queryVoteResult(long voteId) {
+ return baseVote.queryVoteResult(voteId);
+ }
+
+ @View
+ public boolean queryAddressHasVote(long voteId, Address address) {
+ return baseVote.queryAddressHasVote(voteId, address);
+ }
+}
+
+If the methods of smart contract include the parameter of array type, please use the following method to transfer parameters
Refer to the
createmethod in the aforesaid voting contract code
{
+ "sender": "NsdtydTVWskMc7GkZzbsq2FoChqKFwMf",
+ "password": "",
+ "contractAddress": "NseLt14NacjTDhXaTXUdrk6VF7aEwtW4",
+ "gasLimit": 200000,
+ "price": 1,
+ "value": 10000000000,
+ "methodName": "create",
+ "methodDesc": "",
+ "remark": "",
+ "args": [
+ "Test voting 1",
+ "Voting contract 1",
+ [
+ "Option 1",
+ "Option 2",
+ "Option 3"
+ ],
+ 1536044066056, 1536184066056, false, 300, false
+ ]
+}
+segmentsFull code:
https://github.com/nuls-io/nuls-nrc20
package io.nuls.contract.token;
+
+import io.nuls.contract.sdk.Address;
+import io.nuls.contract.sdk.Contract;
+import io.nuls.contract.sdk.Msg;
+import io.nuls.contract.sdk.annotation.Required;
+import io.nuls.contract.sdk.annotation.View;
+
+import java.math.BigInteger;
+import java.util.HashMap;
+import java.util.Map;
+
+import static io.nuls.contract.sdk.Utils.emit;
+import static io.nuls.contract.sdk.Utils.require;
+
+public class SimpleToken implements Contract, Token {
+
+ private final String name;
+ private final String symbol;
+ private final int decimals;
+ private BigInteger totalSupply = BigInteger.ZERO;
+
+ private Map<Address, BigInteger> balances = new HashMap<Address, BigInteger>();
+ private Map<Address, Map<Address, BigInteger>> allowed = new HashMap<Address, Map<Address, BigInteger>>();
+
+ @Override
+ @View
+ public String name() {
+ return name;
+ }
+
+ @Override
+ @View
+ public String symbol() {
+ return symbol;
+ }
+
+ @Override
+ @View
+ public int decimals() {
+ return decimals;
+ }
+
+ @Override
+ @View
+ public BigInteger totalSupply() {
+ return totalSupply;
+ }
+
+ public SimpleToken(@Required String name, @Required String symbol, @Required BigInteger initialAmount, @Required int decimals) {
+ this.name = name;
+ this.symbol = symbol;
+ this.decimals = decimals;
+ totalSupply = initialAmount.multiply(BigInteger.TEN.pow(decimals));;
+ balances.put(Msg.sender(), totalSupply);
+ emit(new TransferEvent(null, Msg.sender(), totalSupply));
+ }
+
+ @Override
+ @View
+ public BigInteger allowance(@Required Address owner, @Required Address spender) {
+ Map<Address, BigInteger> ownerAllowed = allowed.get(owner);
+ if (ownerAllowed == null) {
+ return BigInteger.ZERO;
+ }
+ BigInteger value = ownerAllowed.get(spender);
+ if (value == null) {
+ value = BigInteger.ZERO;
+ }
+ return value;
+ }
+
+ @Override
+ public boolean transferFrom(@Required Address from, @Required Address to, @Required BigInteger value) {
+ subtractAllowed(from, Msg.sender(), value);
+ subtractBalance(from, value);
+ addBalance(to, value);
+ emit(new TransferEvent(from, to, value));
+ return true;
+ }
+
+ @Override
+ @View
+ public BigInteger balanceOf(@Required Address owner) {
+ require(owner != null);
+ BigInteger balance = balances.get(owner);
+ if (balance == null) {
+ balance = BigInteger.ZERO;
+ }
+ return balance;
+ }
+
+ @Override
+ public boolean transfer(@Required Address to, @Required BigInteger value) {
+ subtractBalance(Msg.sender(), value);
+ addBalance(to, value);
+ emit(new TransferEvent(Msg.sender(), to, value));
+ return true;
+ }
+
+ @Override
+ public boolean approve(@Required Address spender, @Required BigInteger value) {
+ setAllowed(Msg.sender(), spender, value);
+ emit(new ApprovalEvent(Msg.sender(), spender, value));
+ return true;
+ }
+
+ public boolean increaseApproval(@Required Address spender, @Required BigInteger addedValue) {
+ addAllowed(Msg.sender(), spender, addedValue);
+ emit(new ApprovalEvent(Msg.sender(), spender, allowance(Msg.sender(), spender)));
+ return true;
+ }
+
+ public boolean decreaseApproval(@Required Address spender, @Required BigInteger subtractedValue) {
+ check(subtractedValue);
+ BigInteger oldValue = allowance(Msg.sender(), spender);
+ if (subtractedValue.compareTo(oldValue) > 0) {
+ setAllowed(Msg.sender(), spender, BigInteger.ZERO);
+ } else {
+ subtractAllowed(Msg.sender(), spender, subtractedValue);
+ }
+ emit(new ApprovalEvent(Msg.sender(), spender, allowance(Msg.sender(), spender)));
+ return true;
+ }
+
+ private void addAllowed(Address address1, Address address2, BigInteger value) {
+ BigInteger allowance = allowance(address1, address2);
+ check(allowance);
+ check(value);
+ setAllowed(address1, address2, allowance.add(value));
+ }
+
+ private void subtractAllowed(Address address1, Address address2, BigInteger value) {
+ BigInteger allowance = allowance(address1, address2);
+ check(allowance, value, "Insufficient approved token");
+ setAllowed(address1, address2, allowance.subtract(value));
+ }
+
+ private void setAllowed(Address address1, Address address2, BigInteger value) {
+ check(value);
+ Map<Address, BigInteger> address1Allowed = allowed.get(address1);
+ if (address1Allowed == null) {
+ address1Allowed = new HashMap<Address, BigInteger>();
+ allowed.put(address1, address1Allowed);
+ }
+ address1Allowed.put(address2, value);
+ }
+
+ private void addBalance(Address address, BigInteger value) {
+ BigInteger balance = balanceOf(address);
+ check(value, "The value must be greater than or equal to 0.");
+ check(balance);
+ balances.put(address, balance.add(value));
+ }
+
+ private void subtractBalance(Address address, BigInteger value) {
+ BigInteger balance = balanceOf(address);
+ check(balance, value, "Insufficient balance of token.");
+ balances.put(address, balance.subtract(value));
+ }
+
+ private void check(BigInteger value) {
+ require(value != null && value.compareTo(BigInteger.ZERO) >= 0);
+ }
+
+ private void check(BigInteger value1, BigInteger value2) {
+ check(value1);
+ check(value2);
+ require(value1.compareTo(value2) >= 0);
+ }
+
+ private void check(BigInteger value, String msg) {
+ require(value != null && value.compareTo(BigInteger.ZERO) >= 0, msg);
+ }
+
+ private void check(BigInteger value1, BigInteger value2, String msg) {
+ check(value1);
+ check(value2);
+ require(value1.compareTo(value2) >= 0, msg);
+ }
+
+
+
+}
+
++ ← + + Quick Start + + IDEA Plugin + + → +
NULS2.0 is an open and non-restricted language underlying platform for blockchain. This paper only refers to the core business modules of blockchain to write the Java environment building process.
1 Environment to prepare
2 Clone source code
git clone git@github.com:nuls-io/nuls_2.0.git
3 IDEA imports all maven projects in nuls_2.0
4 Build your own maven project
5 Run all the modules that need to be started
NULS is a global open source blockchain underlying infrastructure. Making the blockchain simpler is the mission of NULS. This article will describe how to use the NULS core module to quickly build a basic blockchain.
NULS does not limit the attributes of the blockchain. Using the NULS underlying layer, you can build a private chain, a coalition chain, and a public chain. You can build a coin blockchain or build a currency-free blockchain.

NULS 2.0 is built on a micro-service architecture with built-in blockchain core business modules, including accounts, transactions, blocks, consensus, etc. When we build a basic blockchain based on NULS 2.0, we will be based on the NULS 2.0 blockchain. The basic functional layer is extended.
Because NULS2.0 already contains the basic functions of the blockchain, when developing its own blockchain, it only needs to organize its own unique business functions, abstract the corresponding protocol, and develop the function into a module inserted into NULS2. 0 can be. For example: Suppose we want to implement a "Notepad Chain". On the basis of NULS, we need to design a "Notepad" business transaction, such as a note transaction, delete a note transaction, our business module needs to do, in this The business logic code is added to the module, and the verification, processing, and rollback functions of the two transactions are implemented, and then the transaction information is reported to the transaction management module to process the transaction related logic.
Understand how to expand the blockchain function, you can design your own functional modules according to the following steps.
To run a blockchain, you need a lot of basic configuration. Each blockchain must have its own configuration parameters. When building a new blockchain, the first thing is to configure its own operating parameters.
The startup script of NULS2.0 supports the way to send configuration files to start the blockchain. The usage is as follows: sh start.sh -c modules.ncf
The modules.ncf can be configured with parameters of each module. The developer can modify the running parameters according to the situation of the own chain. The specific operating parameters are preset as follows:
| section | param | name | remark |
|---|---|---|---|
| common | chain.id | This chain id | Uint16, NULS main network is 1, test network is 2 |
| common | address.prefix | address prefix | size letters + numbers, 2-5 characters |
| common | data.root.dir | Data Storage Path | For all modules to be stored in the same directory, special paths can be configured in any module if needed |
| common | encoding | Encoding method | Default UTF-8, not recommended to modify |
| common | asset.id | Original Master Asset Code | NULS 1 |
| common | log.root.dir | Log Root | Log files for each module |
| common | log.level | log level | log print level debug/info/warn/error. |
| block | data.folder | data subfolder | used to store block module data, placed under #{data.root.dir} |
| Block | block.max.size | Block size max | Block size limit, avoid too large blocks too high to participate in the threshold |
| block | block.interval | Block Interval | |
| block | max.rollback | Maximum rollback quantity | When this number is exceeded, the system will stop rolling back to avoid major problems |
| block | header.extend.max.size | Extended Maximum size | Size Limits for Extended Fields in Block Headers |
| block | genesis.block.json.path | Genesis Block Description File | Genesis Block Description File |
| consensus | data.folder | data subfolder | used to store consensus module data, placed under #{data.root.dir} |
| consensus | packing.interval | Blocking interval | |
| consensus | inflation.token.count | Annual Issues | The number of additional issuances used to reward nodes via coinbase transactions |
| consensus | block.max.size | Block size | |
| consensus | seed.addresses | Consensus Seed Address | Multiple Addresses Separated by "," |
| consensus | packing.address.pwd | Address Password | Password for the packaged address |
| consensus | agent.deposit.min | Minimum Margin Quantity When Creating Nodes | |
| consensus | agent.deposit.max | Maximum Margin Quantity When Creating Nodes | |
| consensus | commission.rate.max | The maximum commission rate, no more than 100 | |
| consensus | commission.rate.min | Commission Ratio Minimum | |
| consensus | deposit.min | Single commission minimum amount | |
| consensus | agent.total.deposit.max | Maximum amount of nodes to accept delegates | |
| consensus | packing.token.min | When the node's delegate reaches this value, it starts to block | |
| consensus | red.punish.lock.time | Red Card Lock Time | |
| consensus | agent.stop.lock.time | Stop Node Lock Time | |
| network | data.folder | data subfolder | |
| network | seeds | Seed nodes, separated by "," | |
| network | magic.number | Magic numbers for isolating other networks | |
| network | port | port | |
| network | nuls.seed | NULS2.0 seed node configuration when cross-chaining is required | |
| network | cross.listener.port | ||
| network | nuls.magic.number | ||
| contract | nrc20.file.path | NRC20 protocol description json file path | |
| tx | data.folder | data subfolder | |
| Ledger | data.folder | data subfolder | |
| api | mongodb.ip | mongodb address | |
| api | mongodb.port | mongodbport | |
| api | rpc.listener.ips | rpc listener ip | can configure multiple |
| api | rpc.port | rpc listening port | |
| api | req.allow.per.s | Concurrency Limits |
The table lists the most common configuration items, not all. After the alpha version and the beta version, the team will sort out the list of available configurations for all NULS 2.0 for the majority of blockchain developers to configure their own areas. Blockchain.
[^Note]: Since the NULS2.0-alpha version does not complete the docking of Nulstar, the individual parameters may be modified later, which is subject to the final online version.
### 3 Packaging and booting
After the configuration items of the chain have been modified, you can directly refer to Part 4 of this document: [Packing and Booting] (#Packing and Booting)
After building your own blockchain using the modular infrastructure of NULS 2.0, you need to develop a business module and integrate it into the base chain to achieve your own unique business. The following sections can provide some guidance on how to develop a business module of your own.
A functional module with a custom service based on the bottom of the blockchain. The module can be a microservice module that can communicate with other modules according to the NULS2.0 module protocol, or can be an independent, only through the RPC interface. External application for basic module communication.
The service module does not add or modify the protocol, only extends the basic protocol, and implements its own business through the extension of the protocol.
NULS provides two ways to extend the protocol. The two methods are similar, as follows:
Serialize the data you want to wind up into a byte array and place it in the remark field of the transfer transaction. Place your own magic number at the very beginning of the byte array to distinguish other transfer transactions. Monitor the transfer transactions in all blocks in your own application, and parse and process the business when you find remarks that start with your own magic number.
NULS provides a specific transaction type for business expansion. The transaction can freely fill in txData, serialize the data to be chained, into a byte array, and put it into the txData of the transfer transaction. Place your own magic numbers in front of the byte array to distinguish between transactions that are not of interest. Monitor the business extension transactions in all blocks in your own application, and find txData with its own module number for parsing and business processing.
Example:
Suppose now that an application is to be implemented, the application's business is: private notepad, the core business is that each address can store the encrypted note text on the blockchain, and can be decrypted and viewed at any time.
1 functional design
1. Add a note: Encrypt the note content and send the encrypted data to the chain;
+
+2. Parse the block data extraction note data: obtain the data of the application from the blockchain, and store the data to the local database;
+
+3. Decrypt view: Get records from the database, decrypt, display decryption results
+
+4. Delete the note: the app is deleted locally, and the data in the blockchain is not deleted.
+2 blockchain interaction
The above function design needs to interact with the blockchain is 1 new note and 2 parsing block data extraction note data.
First design the data format as follows
+
+{
+
+ Address:"", / / note owner
+
+ Time:"", / / note time point
+
+ Content:""//Encrypted note content
+
+}
+
+According to the data format, assemble the uplink data: address+time+content;
+
+Determine the magic number of the app, assuming 12345678.
+
+Then assemble the DataTransaction (business extension transaction), set the value of txData to the spliced byte array of 12345678, address, time, content. After paying a sufficient fee, sign the transaction and broadcast the transaction to the network.
+Listen to all the blocks, find the 'business expansion transaction' to analyze, first parse to txData, first determine whether it has started 12345678,
+If not, discard the transaction. If yes, continue to parse and determine if address+time+content was successfully obtained (to avoid data confusion caused by repeated magic numbers)
+If the data is successfully parsed, store the data in a local database
+3 other business implementation
All services that do not need to interact with the blockchain can be designed through conventional application methods, so that a simple blockchain application is completed.
Developing applications using business extensions is a simple, fast and efficient way. NULS's support for business expansion is full and friendly, and it is hoped that more and more people will join the NULS ecosystem.
Before you start developing modules, you must first identify a few issues:
After you have identified your needs, you need to design your own modules. The module design depends on the overall design of NULS2.0. When designing its own module, it can focus on designing its own business, and other parts are implemented according to the basic module.
So how do you design your own business? for example:
Case I: Our need is just to store some key information in the chain without complicated logic processing.
+For example, we just want to store a contract related information in the chain, and can be queried at any time in the chain. At this time, we actually don't have to develop any modules. Nuls2.0 provides a transaction (DataTransaction) for storing data. The user only needs to convert the data into a byte array and store it in the txData field or remark field of the transaction. After the broadcast transaction to the whole network, the data can be successful. Winding up. Through the query trading interface provided by nuls2.0, you can query the relevant data of transactions and transactions at any time. Such other business functions can be designed and developed in the form of general software.
+
+Case II: Our needs need to store some key information on the chain and require simple logic processing.
+In general, we recommend users to consider using smart contracts to develop DAPP, such as simple quiz games.
+If our requirements are complex and have related logic processes, we must do so by adding new protocols.
+Here we use the nuls poc consensus mechanism to give examples
+Functional design: first organize the functions to be provided according to the requirements, and design new protocols according to the functions.
+The business functions of the nuls poc consensus mechanism are:
+1. The user can create a consensus node by sending a request for the consensus node transaction, and lock the 2-20 million nuls. After the node meets the block condition, it can participate in the package and get the block reward.
+2. Users can participate in the consensus by sending at least 2000 nuls by sending a transaction that joins the consignment consensus, and get a block reward.
+3. The user can unlock the nuls locked by the consignment consensus by sending a transaction that cancels the entrusted consensus. After canceling the entrustment, the reward will not be continued.
+4. The user can send the transaction to let the node exit the consensus. After exiting, all the nuls on the node will be unlocked, and the node will no longer participate in the block.
+
+Protocol design: including protocol serialization and deserialization, transaction validator, transaction confirmation processor, transaction rollback processor, need to pay attention to avoid conflicts with the underlying protocol.
+4 protocols of the poc consensus mechanism: create consensus node transactions, commission transactions, cancel commission transactions, node exit consensus transactions
+Transaction Verifier: Each protocol will have an associated business verifier. When the node receives a new transaction or receives a new block, it will execute the verifier, and the failed transaction will be rejected.
+For example, create a consensus node:
+1) The account that creates the node cannot create the consensus node multiple times;
+2) The margin is between 20,000 and 200,000 nuls;
+3) Whether the account has a red card record;
+Storage design: Stores business data in the protocol as formatted data for providing user functions.
+For example, after creating a consensus node, the bottom layer stores the transaction data of the created node, and also stores related information of the node, such as the name of the consensus node, the current total amount of the consensus node, the credit value of the consensus node, etc.
+
+Interface design: RPC interface that needs to be provided externally
+For example: query consensus node information, query consensus delegation information, etc.
+
+Other: Other internal processing mechanisms are implemented within the module itself according to different business needs. For example, the core processing of the poc consensus is in the ConsensusProcess.
+This method differs from the second method only in that it involves the modification of the basic chain. When modifying, you need to fully understand the services of the basic chain. After adapting your own services, you need to perform sufficient tests.
+The modified method can be the way to replace the module: get the source code of the base chain module, modify it, and then release its own module to replace the original base module.
+First of all, the module consists of the following two parts. For the first part, the official version only provides the Java version of lib, and will continue to provide C++, Go and other language versions.
1 nuls-service-base-lib (baselib):
Common, all modules have the same functionality, providing basic communication, interface format, general code, etc. If the developer uses a language that does not provide baselib, you need to develop baselib yourself.
2 module-self:
The module itself needs to make its own implementation in the following ways:
1. Start and stop the script: Provide the module's start and stop scripts in your own module, and ensure that any timing to execute the start and stop scripts will not have a significant impact on the business and data.
2. After the startup, the state management is firstly connected to the Nulstar (microservice manager) through the startup parameters, reporting the information of the module itself, obtaining the information of the dependent module, attempting to communicate with the dependent module, and completing the initialization of the module during this period. And change the state of your own module. After all the modules that are dependent are ready, start running the business of your own module.
3. After the dependent module status changes, the module should be processed according to the changed status.
After a new transaction is created in the module, it is necessary to register its own protocol information with the transaction management module each time the module is started, and report the transaction verifier, confirmation processor, and rollback processor information.
After the new module adds the network protocol, the network module needs to subscribe to the message of the network that it needs, so that the network module can send the message to the message processor of the module after receiving the message.
NULS2.0 does not impose any restrictions on data storage, and can freely design and implement its own data storage function according to its own business needs.
If there are other functions that need to be implemented, you can develop according to your own habits or industry standard specifications. NULS2.0 does not impose any restrictions.
According to the product design, the implementation of the function interface, NULS2.0 will provide a unified interface call mode, and will support access methods such as JSONRPC2.0/restFul/CMD/WebSocket.
In principle, NULS2.0 does not limit the logging mode of the expansion module. However, it is recommended to collect all the logs into one root directory by referring to the basic chain, which is convenient for backup and viewing.
Summary: The extension of the business module can refer to the underlying infrastructure chain. All modules are equal in the architecture of NULS2.0. If you are unclear, you can learn or copy the solution of the basic module by looking at the basic module code. The follow-up will continue to open up some of the project's extension modules, so that developers can learn from it, making the development module more and more simple.
The principle of the design agreement: data is streamlined, do not add redundant data in the protocol, and reduce the data size as much as possible.
Network messages: message formats, serialization methods, deserialization methods, computational data size methods, subscription interfaces, and logical processors.
Trading: transaction format, serialization method, deserialization method, calculation data size method, validator, processor, rollback processor, etc.
After the design and development work is completed, it is inevitable to test. This part does not include the unit test part of the development process. Only the methods and precautions of the integration test are explained here.
1 Start all modules through NULSTAR to see if their new modules can be started and stopped normally.
+
+2 Test whether the transaction of the newly added module can be sent, and whether various interfaces can be called normally;
+
+3 The main network test, whether the block can be packaged normally, whether the new transaction can be confirmed or rolled back;
+
+4 check the transaction verification logic is rigorous, do not appear security loopholes;
+
+5 Test whether the business of its own module is correct and complete.
+After all the tests are completed, you can enter the packaging and startup phase.
NULS2.0 has its own code packaging mechanism. Because it involves different languages and different development environments, we have developed a unique packaging specification. Please ensure that the new development module follows the packaging specification and has provided the dependencies, scripts, etc. required by the specification. Components and testing the packaging process
Cd /home/nuls2/nuls_2.0
+./package.sh -m
+After confirming that there is no problem, complete the development of the blockchain, you can hand over the packaged package to the relevant parties for public testing. After testing for a period of time, no problem can be found, you can formally assemble the blockchain network and start your own business. .
/home/nuls2/nuls_2.0/RELEASE/bin
+Cd /home/nuls2/nuls_2.0/RELEASE/bin
+./start.sh -c ./moudle.json (specify the moudle.json configuration file to start)
+ ./start.sh --jre $JAVA_HOME --managerurl 192.168.1.124:8887/ws
+ ```
+
+- View module startup status
+
+./checkstatus.sh
+- Stop Engineering Module:
+Kill process number (the process number corresponds to the process of the mykernel module displayed by jps)
+ ← + + Linux CLI Manual + + Quick Start + + → +




Input Project name, click finish

Smart contract code compilation refers to [developer document] (http://dev.nuls.io/contract/)

Click NULS plugin on the right, and call NULS plugin interface

Plugin automatically generates a node 127.0.0.1:8001, and developer adds a node to deploy the contract. +Recommendation: Start the local wallet, and add the wallet address as the node address.
Click + on the top left corner of panel, and select Add Node.

Input Node address and clock OK

Click + on the top left corner of panel, and select Add Account. Input Account address and click OK.

Click the second button on the top left corner of plugin to directly package the current Project. Two output forms after packaging: Jar package and Hex code

Click [copy code] to copy the HEX code to the [deploy contract] interface of wallet to deploy contract (optional step).

Click the third button on the plugin panel top or [Next] at the button of current package interface to access contract deploying interface


On Deploy interface, select the node and account for deploying contract from pull-down list. JarFilePath default value is the package route of the previous step.

Parameters following JarFilePath are the parameters of the contract construction function.

Click [advanced] to set gas value and price value. Gas varies from 1 to 10000000. Recommend to set a greater gas value to avoid failing in deploying contract.

Click [Test Deploy] to conduct a trial deployment of contract. In case of a success, it gives prompt of Success.

If success, click [Deploy]. After confirmation of contract creation transaction, it feeds back details of transaction, indicating a success of contract deployment.

Review the deployed contract on the top of panel

Click the deployed contract to review all method of this contract

+ ← + + Development Manual + + NRC-20 Token Standard + + → +
Dear users:
It is a great honor to announce that the NULS2.0 Alpha version has been released at 10:30 am, Beijing time: 2019-03-28. We sincerely invite you to participate in the internal test.
The NULS core team innovatively introduced micro-service thinking into the design of the underlying infrastructure of the blockchain, designed the software application as a service suite that can be independently deployed, and introduced the most advanced ideas in this architectural design into the module design, making the module as flexible as a program that can be independently started. This modular architecture with no programming language thresholds combined with microservices is what we call NULS 2.0. In this architecture, the coupling degree between modules is smaller. The development of multiple languages greatly improves the contribution of code and the convenience of users. At the same time, it is easier to expand. Meanwhile, the chain factory and cross-chain module will also be designed on this architecture.
The Alpha version test mainly includes:
3 Apply for test NULS and reply: Alpha+address
4 Access blockchain explorer: http://alpha.nulscan.io/
5 Build Blockchain based on NULS2.0
6 Submit bug:https://github.com/nuls-io/nuls_2.0/issues
To learn more about us, visit nuls.io.
This section is a guide for the use of the full node wallet for Linux version of the NULS2.0-alpha test network. We suppose you have basic operation capability of Linux system. This paper introduces how to use NULS wallet to create accounts, import accounts, transfer, and create nodes or stake, etc. in the Linux system. We recommend users to use the Linux system server to create stable NULS nodes.
| Versions | Date | Contents |
|---|---|---|
| V1.0.0 | 2018-03-18 | alpha |
The server for NULS node should be not lower than the following configuration:
| CPU | Memory | Disk space | Bandwidth |
|---|---|---|---|
| 4-Core 3.0 GHz | 16GB | 128GB | 20Mbps uplink |
Recommended configuration:
| CPU | Memory | Disk space | Bandwidth |
|---|---|---|---|
| 8-core 3.0 GHz | 32GB | 256GB | 100Mbps uplink |
Linux system
The Linux kernel version is recommended to use 2.6.32 and above
To download v2.0.0-alpha-1 wallet via Linux system, you can type the following command:
$wget https://media.githubusercontent.com/media/nuls-io/nuls-wallet-release/master/NULS-Wallet-linux64-1.0.0.tar.gz
+Note: the download address may be different if there are subsequent versions.
$ tar -zxf NULS-Wallet-linux64-2.0.0-alpha-1.tar.gz
+ $ cd NULS-Wallet-linux64-2.0.0-alpha-1
+ $ ./start.sh
+Enter the cmdclient/1.0.0 directory and execute the following command:
$ cd cmdclient/1.0.0
+ $ ./cmd.sh
+At this point, you can see the input prompt nuls>>>, now you can directly type NULS wallet command to operate.
+For example, to create an account you can do like this:
nuls>>> create
+ Please enter the password (password is between 8 and 20 inclusive of numbers and letters), If you do not want to set a password, return directly.
+ Enter your password:*********
+ Please confirm new password:*********
+ [ "Nse9EtaRwgVgN42pxURgZjUR33LUx1j1" ]
+ nuls>>>
+Command create means to create a single account, next enter your password, and once again confirm the new password. If successful, the address of the account will be returned.
Print all valid commands,
| Parameter | Description |
|---|---|
| -a | format the printed command, optional |
| command | view instructions for the specific command |
| group | view all instructions for the commands in the specific command group |
Return: help
getaccount <address> --get account information
+Return: help-a
getaccount <address> --get account information
+ OPTIONS:
+ <address> the account address - Required
+Example
nuls>>> help
+nuls>>> help -a
+nuls>>> help account
+nuls>>> help create
+Create an account and return the set of account addresses
| Parameter | Description |
|---|---|
| [number] the number of accounts you want to create, optional |
When creating an account, you are required to enter the password for the account. The password must be set to ensure the security of the assets.
Return: accounts set
[ "5MR_2CkDZtZRHGLD43JreUc8LsFBertsc9r", "5MR_2CXCCU89fj9RyQj9MgZVE7Pq3Mmk77p" ]
+Example
Create a single account
nuls>>> create
+Please enter the new password(8-20 characters, the combination of letters and numbers).
+Enter your new password:**********
+Please confirm new password:**********
+[ "5MR_2CetN1KeWAVsaUsqD7JwMBwjGuRGpGW" ]
+Create multiple accounts at once
nuls>>> create 3
+Please enter the new password(8-20 characters, the combination of letters and numbers).
+Enter your new password:**********
+Please confirm new password:**********
+["5MR_2CWdfU2VDERgQbWS1quGYAGD1iDDM4N", "5MR_2CcYq7fqrvKagReBmzG3qEz8qGkifCr", "5MR_2Cd6E2vAGZQxkqeXbeqThRxDGTFiLei" ]
+To back up an account, a file named as account address with the extension .keystore is generated, which is the backup file for the account
| Parameter | Description |
|---|---|
| <address> | account address, required |
| [path] | the directory where the generated backup file is included, current directory by default, optional |
Return
The path to the backup file is /nuls/bin/NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy.keystore
+Example: backup an account with password
shell
+nuls>>> backup 5MR_2CetN1KeWAVsaUsqD7JwMBwjGuRGpGW /Users/zlj
+Enter account password
+***************
+The path to the backup file is /Users/zlj/5MR_2CetN1KeWAVsaUsqD7JwMBwjGuRGpGW.keystore
+ Enter the password to remove a local account based on the account address
| Parameter | Description |
|---|---|
| <address> | account address, required |
Return
Success
+Example
nuls>>> remove 5MR_2CetN1KeWAVsaUsqD7JwMBwjGuRGpGW
+Enter your password for account**********
+Success
+Set a new password according to the account address and password.
| Parameter | Description |
|---|---|
| <address> | account address, required |
Return
Success
+Example
nuls>>> resetpwd 5MR_2CWdfU2VDERgQbWS1quGYAGD1iDDM4N
+Enter your old password:**********
+Enter new password**********
+Please confirm new password:**********
+Success
+Set an alias to the account. If a node is created with this account, its alias will be displayed as the node source
| Parameter | Description |
|---|---|
| <address> | account address, required |
| <alias> | alias name, required |
Return: transaction hash
txHash:0020f94f36aefd59f9cca9bff3c018fc287dc6c0bcd7fbeb047133cadb5747e7d98d"
+Example
nuls>>> setalias 5MR_2CXrzwoCoP4vnUxHJ5gdUUXZJhCpjq9 zlj
+Enter your account password**********
+txHash:0020830971e02527f18f8f9e32f974d8c73ce6bd249de859cae170476b87d0ec9582
+Import the account keystore file to generate a local account. The operation is not accessible if the local account already exists locally.
| Parameter | Description |
|---|---|
| <path> | path of the keystore file to be imported, required |
Note: the original password is required to import the keystore file to generate the account
Return: address of the imported account
"NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy"
+Example
nuls>>>importkeystore /Users/zhoulijun/5MR_2CetN1KeWAVsaUsqD7JwMBwjGuRGpGW.keystore
+Please enter the password (password is between 8 and 20 inclusive of numbers and letters), If you do not want to set a password, return directly.
+Enter your password:**********
+5MR_2CetN1KeWAVsaUsqD7JwMBwjGuRGpGW
+Import the account private key to generate a local account, overwritten if the local account already exists. You are required to set a password for the account when importing. This function can be used to retrieve the account through the private key if you forget the account password.
| Parameter | Description |
|---|---|
| <privatekey> | account's private key, required |
"NsdyM1Ls5qw8wutvAQsr93jxgq8qYAZy"
+Example
nuls>>> import 1c2b9fd4417c1aad8ae9f24c982ff294eb50a6462b873b79a879e805a9990346
+Please enter the password (password is between 8 and 20 inclusive of numbers and letters), If you do not want to set a password, return directly.
+Enter your password:**********
+Please confirm new password:**********
+5MR_2CeG11nRqx7nGNeh8hTXADibqfSYeNu
+Query account information with the account address
| Parameter | Description |
|---|---|
| <address> | account address, required |
Return
{
+ "encryptedPrikeyHex" : "724d68268849f3680d480c9257f33229c0fac88890d5355c0e4d9c457af5c6e8b8f9f7ca9fd52fbd8079fbce1782052d", // the encrypted private key
+ "alias" : "zlj", // alias
+ "baglance" : {
+ "freeze" : 0, // frozen assets
+ "total" : 997999999800000, // total assets
+ "available" : 997999999800000 // usable assets
+ },
+ "address" : "5MR_2CeG11nRqx7nGNeh8hTXADibqfSYeNu", // account address
+ "pubkeyHex" : "0211c45f28710cd26a2c45fb790895a0ff2e095a290f1825b31d80ebc30913c486" //public key
+}
+Example
nuls>>> getaccount 5MR_2CeG11nRqx7nGNeh8hTXADibqfSYeNu
+{
+ "encryptedPrikeyHex" : "724d68268849f3680d480c9257f33229c0fac88890d5355c0e4d9c457af5c6e8b8f9f7ca9fd52fbd8079fbce1782052d", //encrypted private key
+ "alias" : "zlj", //alias
+ "baglance" : {
+ "freeze" : 0, // frozen assets
+ "total" : 997999999800000, // total assets
+ "available" : 997999999800000 // usable assets
+ },
+ "address" : "5MR_2CeG11nRqx7nGNeh8hTXADibqfSYeNu", // account address
+ "pubkeyHex" : "0211c45f28710cd26a2c45fb790895a0ff2e095a290f1825b31d80ebc30913c486" // encrypted public key
+}
+Query the account list with the paging parameters and return all accounts in descending order by creation time.
| Parameter | Description |
|---|---|
| <pageNumber> | page number indicating the page to query, required |
| <pageSize> | number of rows displayed per page, required |
Return: accounts set
[ {
+ "address" : "5MR_2CeG11nRqx7nGNeh8hTXADibqfSYeNu", //address
+ "alias" : null, //alias
+ "pubkeyHex" : "0211c45f28710cd26a2c45fb790895a0ff2e095a290f1825b31d80ebc30913c486", //public key
+ "encryptedPrikeyHex" : "724d68268849f3680d480c9257f33229c0fac88890d5355c0e4d9c457af5c6e8b8f9f7ca9fd52fbd8079fbce1782052d" //private key
+}, {
+ "address" : "5MR_2CetN1KeWAVsaUsqD7JwMBwjGuRGpGW",
+ "alias" : null,
+ "pubkeyHex" : "0205a70731e7653eca328ba7d71f0a789f8cfb1ced32f5a00d4fc3fb2ad8b9f7c1",
+ "encryptedPrikeyHex" : "e38d2dd08154a0eedf8298f5fe50b86723e521522f38aba5c68072bad365c3e8c57d7ac3ae83f8d646a17f845a38bc57"
+}, {
+ "address" : "5MR_2CXrzwoCoP4vnUxHJ5gdUUXZJhCpjq9",
+ "alias" : "zlj",
+ "pubkeyHex" : "03021a46a7e5ea59ae8884340568e9e79511fbd352b4ba28db39f15856918cdbeb",
+ "encryptedPrikeyHex" : "bfbfdad874f74215e241ad15152d8648925c497b6a826965f5c06c46fd9b008313e6918ebcfcb56f2cdf8d1b9f088f77"
+} ]
+Example: get accounts list
nuls>>> getaccounts
+[ {
+ "address" : "5MR_2CeG11nRqx7nGNeh8hTXADibqfSYeNu", //address
+ "alias" : null, //alias
+ "pubkeyHex" : "0211c45f28710cd26a2c45fb790895a0ff2e095a290f1825b31d80ebc30913c486", //encrypted public key
+ "encryptedPrikeyHex" : "724d68268849f3680d480c9257f33229c0fac88890d5355c0e4d9c457af5c6e8b8f9f7ca9fd52fbd8079fbce1782052d" //encrypted private key
+}, {
+ "address" : "5MR_2CetN1KeWAVsaUsqD7JwMBwjGuRGpGW",
+ "alias" : null,
+ "pubkeyHex" : "0205a70731e7653eca328ba7d71f0a789f8cfb1ced32f5a00d4fc3fb2ad8b9f7c1",
+ "encryptedPrikeyHex" : "e38d2dd08154a0eedf8298f5fe50b86723e521522f38aba5c68072bad365c3e8c57d7ac3ae83f8d646a17f845a38bc57"
+}, {
+ "address" : "5MR_2CXrzwoCoP4vnUxHJ5gdUUXZJhCpjq9",
+ "alias" : "zlj",
+ "pubkeyHex" : "03021a46a7e5ea59ae8884340568e9e79511fbd352b4ba28db39f15856918cdbeb",
+ "encryptedPrikeyHex" : "bfbfdad874f74215e241ad15152d8648925c497b6a826965f5c06c46fd9b008313e6918ebcfcb56f2cdf8d1b9f088f77"
+} ]
+Query the account’s private key with the account address and password
| Parameter | Description |
|---|---|
| <address> | account address, required |
Return: the private key of the imported account (unencrypted)
00a166d10c2cc4cd8f76449ff699ab3eee44fe4f82b4bb866f7bba02751a6fd655
+Example
nuls>>> getprikey 5MR_2CXrzwoCoP4vnUxHJ5gdUUXZJhCpjq9
+Enter your account password**********
+7b4d3ec971fc01ea813b52f6c35091d43beac4a68550bae2db63975149244678
+Query account balance with the account address
| Parameter | Description |
|---|---|
| <address> | account address, required |
Return: the address of the imported account
{
+"total": "9999998.99",// balance
+"freeze": "0", // locked balance
+"available": "9999998.99"// usable balance
+}
+Example
nuls>>> getbalance Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT
+{
+ "total" : "9999998.99",
+ "freeze" : "0",
+ "available" : "9999998.99"
+}
+Transfer NULS to the specific account with the account address
| Parameter | Description |
|---|---|
| <fromAddress> | sender address(Select any item with the fromAlias) |
| <fromAlias> | sender address alias(Select any item with the fromAddress) |
| <toAddress> | receiver address(Select any item with the toAlias) |
| <toAlias> | receiver address(Select any item with the toAddress) |
| <amount> | transfer amount, required |
| [remark] | remark, optional |
Return: transfer transaction hash
"00200bef73ad728c48146c8a5eb0d76fe7325b85803c61d8357c16dba09ea33b3596"
+Example
nuls>>> transfer Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT NsdtmV5XkgSdpBXi65ueTsrv2W5beV2T 100 transfer
+Please enter the password.
+Enter your password: *********
+"00200bef73ad728c48146c8a5eb0d76fe7325b85803c61d8357c16dba09ea33b3596"
+Query the transaction details with the transaction hash
| Parameter | Description |
|---|---|
| <hash> | transaction hash, optional |
Return: transaction details
{
+ "type" : 2, //transaction type (refer to the table below for Enumeration type description [Enumeration type])
+ "coinData" : "ARc5MAGYBT3XNVp+BIuhGvGcejuTev8DODkwAQCgZ/cFAAAAAAAAAAAAAAAACO/WnDT4pvmsAAEXOTABL/80LO1f8vxvfNXc5l9eeIDTGKM5MAEAAOH1BQAAAAAAAAAAAAAAAAA=",
+ "txData" : null,
+ "time" : 1552979783918,
+ "transactionSignature" : "IQIRxF8ocQzSaixF+3kIlaD/LglaKQ8YJbMdgOvDCRPEhgBGMEQCICdnNr3HqEg/UZZ6RLBHyGuPChoLdMtcOHXT3Xlb5SC3AiBGAWSPGH3yjtEkaVbLsI5n9UcqDvOfG3Ui1jf672IDCg==",
+ "remark" : "6L2s6LSm",
+ "hash" : {
+ "digestAlgType" : 0,
+ "digestBytes" : "CivAIHpVyqNr/h87/FWk7vXsXqBekHJ+3kQc5mZp+H8=",
+ "digestHex" : "00200a2bc0207a55caa36bfe1f3bfc55a4eef5ec5ea05e90727ede441ce66669f87f"
+ },
+ "blockHeight" : 341, //block height
+ "status" : "CONFIRMED", //confirmation state
+ "size" : 225,
+ "inBlockIndex" : 0,
+ "coinDataInstance" : {
+ "from" : [ {
+ "address" : "OTABmAU91zVafgSLoRrxnHo7k3r/Azg=",
+ "assetsChainId" : 12345,
+ "assetsId" : 1,
+ "amount" : 100100000,
+ "nonce" : "79acNPim+aw=",
+ "locked" : 0
+ } ],
+ "to" : [ {
+ "address" : "OTABL/80LO1f8vxvfNXc5l9eeIDTGKM=",
+ "assetsChainId" : 12345,
+ "assetsId" : 1,
+ "amount" : 100000000,
+ "lockTime" : 0
+ } ]
+ },
+ "fee" : 100000, //fee
+ "multiSignTx" : false
+}
+Example: query transfer transaction
nuls>>> gettx 00200a2bc0207a55caa36bfe1f3bfc55a4eef5ec5ea05e90727ede441ce66669f87f
+{
+ "type" : 2, //transaction type (refer to the table below for Enumeration type description [Enumeration type])
+ "coinData" : "ARc5MAGYBT3XNVp+BIuhGvGcejuTev8DODkwAQCgZ/cFAAAAAAAAAAAAAAAACO/WnDT4pvmsAAEXOTABL/80LO1f8vxvfNXc5l9eeIDTGKM5MAEAAOH1BQAAAAAAAAAAAAAAAAA=",
+ "txData" : null,
+ "time" : 1552979783918,
+ "transactionSignature" : "IQIRxF8ocQzSaixF+3kIlaD/LglaKQ8YJbMdgOvDCRPEhgBGMEQCICdnNr3HqEg/UZZ6RLBHyGuPChoLdMtcOHXT3Xlb5SC3AiBGAWSPGH3yjtEkaVbLsI5n9UcqDvOfG3Ui1jf672IDCg==",
+ "remark" : "6L2s6LSm",
+ "hash" : {
+ "digestAlgType" : 0,
+ "digestBytes" : "CivAIHpVyqNr/h87/FWk7vXsXqBekHJ+3kQc5mZp+H8=",
+ "digestHex" : "00200a2bc0207a55caa36bfe1f3bfc55a4eef5ec5ea05e90727ede441ce66669f87f"
+ },
+ "blockHeight" : 341, //block height
+ "status" : "CONFIRMED", //confirmation state
+ "size" : 225,
+ "inBlockIndex" : 0,
+ "coinDataInstance" : {
+ "from" : [ {
+ "address" : "OTABmAU91zVafgSLoRrxnHo7k3r/Azg=",
+ "assetsChainId" : 12345,
+ "assetsId" : 1,
+ "amount" : 100100000,
+ "nonce" : "79acNPim+aw=",
+ "locked" : 0
+ } ],
+ "to" : [ {
+ "address" : "OTABL/80LO1f8vxvfNXc5l9eeIDTGKM=",
+ "assetsChainId" : 12345,
+ "assetsId" : 1,
+ "amount" : 100000000,
+ "lockTime" : 0
+ } ]
+ },
+ "fee" : 100000, //fee
+ "multiSignTx" : false
+}
+/** coinbase transaction*/
+ int TX_TYPE_COINBASE = 1;
+ /** transfer */
+ int TX_TYPE_TRANSFER = 2;
+ /** set alias */
+ int TX_TYPE_ALIAS = 3;
+ /** create consensus node */
+ int TX_TYPE_REGISTER_AGENT = 4;
+ /** agent (join consensus) */
+ int TX_TYPE_JOIN_CONSENSUS = 5;
+ /** cancel agent (cancel consensus)*/
+ int TX_TYPE_CANCEL_DEPOSIT = 6;
+ /** yellow punish */
+ int TX_TYPE_YELLOW_PUNISH = 7;
+ /** red punish */
+ int TX_TYPE_RED_PUNISH = 8;
+ /** stop node (stop consensus node)*/
+ int TX_TYPE_STOP_AGENT = 9;
+ /** cross-chain transfer */
+ int TX_TYPE_CROSS_CHAIN_TRANSFER = 10;
+ /** register chain */
+ int TX_TYPE_REGISTER_CHAIN_AND_ASSET = 11;
+ /** destroy chain*/
+ int TX_TYPE_DESTROY_CHAIN_AND_ASSET = 12;
+ /** add asset to chain*/
+ int TX_TYPE_ADD_ASSET_TO_CHAIN = 13;
+ /** remove asset from chain*/
+ int TX_TYPE_REMOVE_ASSET_FROM_CHAIN = 14;
+ /** create contract */
+ int TX_TYPE_CREATE_CONTRACT = 100;
+ /** call contract */
+ int TX_TYPE_CALL_CONTRACT = 101;
+ /** delete contract*/
+ int TX_TYPE_DELETE_CONTRACT = 102;
+Transfer to an external address with an account alias
| Parameter | Description |
|---|---|
| <address> | sender address, required |
| <toAddress> | receiver address, required |
| <amount> | transfer amount, required |
| [remark] | remark, optional |
Return: transaction hash
00205315329f62824b3fae1675ef9419ae7dd097d6609d61df4b1345f9481f7c8be3
+Example: transfer 10,000 NULS to external address through alias "zlj"
nuls>>> transferbyalias zlj 5MR_2CeG11nRqx7nGNeh8hTXADibqfSYeNu 10000
+Enter your account password**********
+00205315329f62824b3fae1675ef9419ae7dd097d6609d61df4b1345f9481f7c8be3
+To create a node through account address, it is required to provide two addresses. The first one is the node address, and you need to input the password for the node account. The other is the package address, and no password is required. Meanwhile, you’re required to offer no less than 20,000 NULS as deposit.
| Parameter | Description |
|---|---|
| <agentAddress> | account address to create a node, required |
| <packingAddress> | account address of the packaging node, required (note: the account should be password-less, otherwise the node cannot package to generate blocks) |
| <commissionRate> | agent commission ratio with a range from 10 to 100, required |
| <deposit> | deposit to create a node, no less than 2000 NULS, required |
Return: agent hash of the node
"002006a5b7eb1d32ed6d7d54e24e219b112d4fdb8530db5506ee953b6f65a0fdb55e"
+Example: create a node with a commission rate of 10% and a deposit of 20,000 NULS.
nuls>>> createagent Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT NsdvAnqc8oEiNiGgcp6pEusfiRFZi4vt 10 20000
+Please enter the password.
+Enter your password: **********
+"002006a5b7eb1d32ed6d7d54e24e219b112d4fdb8530db5506ee953b6f65a0fdb55e"
+Join consensus by account address and node agentHash, which requires at least 2,000NULS
| Parameter | Description |
|---|---|
| <address> | account address, required |
| <agentHash> | agentHash of the node, optional |
| <deposit> | deposit required to join consensus, no less than 2000NULS, required |
Return: the hash of the transaction to join consensus, which is needed to cancel the consensus.
"0020d349b7ad322ff958e3abfa799d9ac76341afa6e1fb4d3857353a5adc74ba3fd0"
+Example
nuls>>> deposit NsdtmV5XkgSdpBXi65ueTsrv2W5beV2T 002006a5b7eb1d32ed6d7d54e24e219b112d4fdb8530db5506ee953b6f65a0fdb55e 5000
+"0020d349b7ad322ff958e3abfa799d9ac76341afa6e1fb4d3857353a5adc74ba3fd0"
+Cancel consensus (agent) according to account address and the hash of the transaction for joining consensus. When a single account agents nodes for multiple times, each agent transaction is independent. So to cancel consensus, the agent can only be cancelled by the corresponding transaction hash of the single agent, rather than cancel all the agents at one time.
| Parameter | Description |
|---|---|
| <address> | account address, required |
| <txHash> | hash of the agent transaction, required |
Return: transaction hash to cancel consensus
"00201d70ac37b53d41c0e813ad245fc42e1d3a5d174d9148fbbbaed3c18d4d67bdbf"
+Example
nuls>>> withdraw NsdtmV5XkgSdpBXi65ueTsrv2W5beV2T 0020d349b7ad322ff958e3abfa799d9ac76341afa6e1fb4d3857353a5adc74ba3fd0
+"00201d70ac37b53d41c0e813ad245fc42e1d3a5d174d9148fbbbaed3c18d4d67bdbf"
+Stop the node and all NULS delegated to the node will be refunded, and the deposit of the node creator will be locked for 72 hours.
| Parameter | Description |
|---|---|
| <address> | account address, required |
Return: transaction hash to stop a node
"0020f15eecd7c85be76521ed6af4d58a3810f7df58e536481cff4a96af6d4fddec5f"
+Example
nuls>>> stopagent Nse2TpVsJd4gLoj79MAY8NHwEsYuXwtT
+Please enter the password.
+Enter your password:**********
+"0020f15eecd7c85be76521ed6af4d58a3810f7df58e536481cff4a96af6d4fddec5f"
+Get the latest block header’s information
Return
{
+ "hash" : "0020b446a0244e4e46f8736f1ab56c33616facb836bc8344367f2f048b703f0c8f57", //block hash
+ "preHash" : "0020c0dcf9209f66ee7e7778c817ba7c04d67b5e6a056b42dec7fbfe44eb5f91bdfc", //previous block hash
+ "merkleHash" : "00200511ced5779c54aa2170b941a1f9a7ae08dfd009b1dfaacc3679d15da9fb9c3e", //merkle hash
+ "time" : "2019-03-19 18:26:20.020", //packing time
+ "height" : 1479, //block height
+ "txCount" : 1, // number of transactions included in the block
+ "blockSignature" : "00473045022100b1a07f6da3d4ce46cab278967d76875483527e3fc749a460afdf0c375f2ec2ae022053e40e8b4d8bf4e571284e45f18c46c31163ed640a2328f3ba90ac7708808365", //block singnature
+ "size" : 0, //block size
+ "packingAddress" : null, // packing address
+ "roundIndex" : 155299118,
+ "consensusMemberCount" : 100,
+ "roundStartTime" : "2019-03-19 18:26:10.010",
+ "packingIndexOfRound" : 1,
+ "mainVersion" : 1,
+ "blockVersion" : 0,
+ "stateRoot" : null
+}
+Example
nuls>>> getbestblockheader
+{
+ "hash" : "0020b446a0244e4e46f8736f1ab56c33616facb836bc8344367f2f048b703f0c8f57",
+ "preHash" : "0020c0dcf9209f66ee7e7778c817ba7c04d67b5e6a056b42dec7fbfe44eb5f91bdfc",
+ "merkleHash" : "00200511ced5779c54aa2170b941a1f9a7ae08dfd009b1dfaacc3679d15da9fb9c3e",
+ "time" : "2019-03-19 18:26:20.020",
+ "height" : 1479,
+ "txCount" : 0,
+ "blockSignature" : "00473045022100b1a07f6da3d4ce46cab278967d76875483527e3fc749a460afdf0c375f2ec2ae022053e40e8b4d8bf4e571284e45f18c46c31163ed640a2328f3ba90ac7708808365",
+ "size" : 0,
+ "packingAddress" : null,
+ "roundIndex" : 155299118,
+ "consensusMemberCount" : 100,
+ "roundStartTime" : "2019-03-19 18:26:10.010",
+ "packingIndexOfRound" : 1,
+ "mainVersion" : 1,
+ "blockVersion" : 0,
+ "stateRoot" : null
+}
+Query block information with the block height or block hash, and exactly only one of them can be used as the query condition.
| Parameter | Description |
|---|---|
| <hash> | block hash |
| <height> | block height |
Return
{
+ "hash" : "0020b446a0244e4e46f8736f1ab56c33616facb836bc8344367f2f048b703f0c8f57", //block hash
+ "preHash" : "0020c0dcf9209f66ee7e7778c817ba7c04d67b5e6a056b42dec7fbfe44eb5f91bdfc", //previous block hash
+ "merkleHash" : "00200511ced5779c54aa2170b941a1f9a7ae08dfd009b1dfaacc3679d15da9fb9c3e", //merkle hash
+ "time" : "2019-03-19 18:26:20.020", //packing time
+ "height" : 1479, //block height
+ "txCount" : 1, // number of transactions included in the block
+ "blockSignature" : "00473045022100b1a07f6da3d4ce46cab278967d76875483527e3fc749a460afdf0c375f2ec2ae022053e40e8b4d8bf4e571284e45f18c46c31163ed640a2328f3ba90ac7708808365", //block signature
+ "size" : 0, //block size
+ "packingAddress" : null, //packing address
+ "roundIndex" : 155299118,
+ "consensusMemberCount" : 100,
+ "roundStartTime" : "2019-03-19 18:26:10.010",
+ "packingIndexOfRound" : 1,
+ "mainVersion" : 1,
+ "blockVersion" : 0,
+ "stateRoot" : null
+}
+Example: get block with block height
nuls>>> getblock 28115
+{
+ "hash" : "0020b446a0244e4e46f8736f1ab56c33616facb836bc8344367f2f048b703f0c8f57", //block hash
+ "preHash" : "0020c0dcf9209f66ee7e7778c817ba7c04d67b5e6a056b42dec7fbfe44eb5f91bdfc", //previous block hash
+ "merkleHash" : "00200511ced5779c54aa2170b941a1f9a7ae08dfd009b1dfaacc3679d15da9fb9c3e", //merkle hash
+ "time" : "2019-03-19 18:26:20.020", //packing time
+ "height" : 1479, //block height
+ "txCount" : 1, // number of transactions included in the block
+ "blockSignature" : "00473045022100b1a07f6da3d4ce46cab278967d76875483527e3fc749a460afdf0c375f2ec2ae022053e40e8b4d8bf4e571284e45f18c46c31163ed640a2328f3ba90ac7708808365", //block signature
+ "size" : 0, //block size
+ "packingAddress" : null, //packing address
+ "roundIndex" : 155299118,
+ "consensusMemberCount" : 100,
+ "roundStartTime" : "2019-03-19 18:26:10.010",
+ "packingIndexOfRound" : 1,
+ "mainVersion" : 1,
+ "blockVersion" : 0,
+ "stateRoot" : null
+}
+This interface is called to create a smart contract on the chain
| Parameter | Description |
|---|---|
| <sender> | Create the account address for the smart contract |
| <gaslimt> | Consumes of the gas for creating the contract |
| <price> | Unit price, how much Na is each Gas value.Na is the minimum unit for NULS, 1 NULS = 100 million Na, and the minimum unit price of the system is 25Na/Gas |
| <contractCode> | Hex code of the contract code |
| [remark] | remark |
Returns the transaction hash for which the contract was created and the address of the contract
{
+ "txHash" : "00205fb44fd0924a57857e71d06ec0549366b5d879b2cbd68488ed88a2dbf96c130f", //transaction hash
+ "contractAddress" : "tNULSeBaN6ofkEqsPJmWVaeMpENTgmC5ifWtz9" //contract address
+}
+The example creates a contract (contractCode omits the middle)
nuls>>> createcontract tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD 200000 25 504b03040a........000000800080051020000b31600000000 remarkdemo
+The arguments structure:
+[ {
+ "type" : "String",
+ "name" : "name",
+ "required" : true
+}, {
+ "type" : "String",
+ "name" : "symbol",
+ "required" : true
+}, {
+ "type" : "BigInteger",
+ "name" : "initialAmount",
+ "required" : true
+}, {
+ "type" : "int",
+ "name" : "decimals",
+ "required" : true
+} ]
+Please enter the arguments you want to fill in according to the arguments structure(eg. "a",2,["c",4],"","e" or "'a',2,['c',4],'','e'").
+Enter the arguments:"KQB","KQB",10000,2
+{
+ "txHash" : "0020ec1d68eaed63e2db8649b0a39f16b7c5af24f86b787233f6ba6d577d7d090587",
+ "contractAddress" : "tNULSeBaNBYK9MQcWWbfgFTHj2U4j8KQGDzzuK"
+}
+Gets the description of the intelligent contract and the argument list of the constructor and the calling method
| Parameter | Description |
|---|---|
| <contract address> | contract address |
Return
Skip
+example
+nuls>>> getcontractinfo tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L
+getcontractinfo tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L
+{
+ "createTxHash" : "00203a48dcfc26426152805be49830c72005b4648d0182bbf6c2e8980380364eb59f",
+ "address" : "tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L",
+ "creater" : "tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD",
+ "createTime" : 1553563706022,
+ "blockHeight" : 46,
+ "isNrc20" : true,
+ "nrc20TokenName" : "QKB",
+ "nrc20TokenSymbol" : "QKB",
+ "decimals" : 2,
+ "totalSupply" : "200000000",
+ "status" : "normal",
+ "method" : [ {
+ "name" : "<init>",
+ "desc" : "(String name, String symbol, BigInteger initialAmount, int decimals) return void",
+ "args" : [ {
+ "type" : "String",
+ "name" : "name",
+ "required" : true
+ }, {
+ "type" : "String",
+ "name" : "symbol",
+ "required" : true
+ }, {
+ "type" : "BigInteger",
+ "name" : "initialAmount",
+ "required" : true
+ }, {
+ "type" : "int",
+ "name" : "decimals",
+ "required" : true
+ } ],
+ "returnArg" : "void",
+ "view" : false,
+ "event" : false,
+ "payable" : false
+ },{
+ "name" : "transfer",
+ "desc" : "(Address to, BigInteger value) return boolean",
+ "args" : [ {
+ "type" : "Address",
+ "name" : "to",
+ "required" : true
+ }, {
+ "type" : "BigInteger",
+ "name" : "value",
+ "required" : true
+ } ],
+ "returnArg" : "boolean",
+ "view" : false,
+ "event" : false,
+ "payable" : false
+ }]
+}
+
+Call the functions provided by the smart contract
| Parameter | Description |
|---|---|
| <senderAddress> | The account address of the invocation contract |
| <gasLimit> | This contract is the largest consumption of Gas |
| <price> | Unit price, how much Na is each Gas value.Na is the minimum unit for NULS, 1 NULS = 100 million Na, and the minimum unit price of the system is 25Na/Gas |
| <contractAddress | The contract address of the call |
| <methodName> | The method name of the contract |
| <value> | If transfer is to be made to the contract, the amount of transfer |
| [-d methodDesc] | Use this method to describe the parameter list if there is a method with the same name in the contract |
| [-r remark] | remark |
Returns: transaction hash
"0020c9079e0f0454103adceed798d40171c41a8db04586dba966fbe7f2ab722583ad" //transaction hash
+The example calls the nrc20-token transfer function for a specified contract, Example tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L NRC20 contract address, number of input parameters for receiving address and account transfer
nuls>>> callcontract tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD 200000 25 tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L transfer 0 -r call
+callcontract tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD 200000 25 tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L transfer 0 -r call
+Please Enter your account passwordzhoujun172
+**********
+Please enter the arguments according to the arguments structure(eg. "a",2,["c",4],"","e" or "'a',2,['c',4],'','e'"),
+If this method has no arguments(Refer to the command named "getcontractinfo" for the arguments structure of the method.), return directly.
+Enter the arguments:"tNULSeBaMvEtDfvZuukDf2mVyfGo3DdiN8KLRG",2
+"0020c9079e0f0454103adceed798d40171c41a8db04586dba966fbe7f2ab722583ad"
+Stop an available smart contract
| Parameter | Description |
|---|---|
| <senderAddress> | The account address of the invocation contract |
| <contractAddress> | The contract address of the call |
Returns: trading hash
"0020c55e885dd910dad0b2c49f5b71b62691b57884ca21fd47668f1f5cadc84daad6" //交易hash
+example
nuls>>> deletecontract tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L
+deletecontract tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L
+Please enter your account passwordzhoujun172
+**********
+"0020c55e885dd910dad0b2c49f5b71b62691b57884ca21fd47668f1f5cadc84daad6"
+Calling the contract view method immediately returns the result and no transaction is generated
| Parameter | Description |
|---|---|
| <contractAddress> | The contract address of the call |
| <methodName> | Method called |
| [-d methodDesc] | Use this method to describe the parameter list if there is a method with the same name in the contract |
The return value
The return value varies depending on the function being called
+The example calls the nrc20-token contract's query Token balance function to query the Token balance of the specified address
nuls>>> viewcontract tNULSeBaN6pwyVwXjfpm5BMH5eiirvthoZDVEc balanceOf
+viewcontract tNULSeBaN6pwyVwXjfpm5BMH5eiirvthoZDVEc balanceOf
+Please enter the arguments according to the arguments structure(eg. "a",2,["c",4],"","e" or "'a',2,['c',4],'','e'"),
+If this method has no arguments(Refer to the command named "getcontractinfo" for the arguments structure of the method.), return directly.
+Enter the arguments:"tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD"
+"tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD"
+{
+ "result" : "20000000"
+}
+To the specified contract address into the main network currency
| Parameter | Description |
|---|---|
| <senderAddress> | Transfer out account address |
| <contractAddress | transfer into the contract address |
| <amount> | transfer amount |
| [remark] | remark |
Returns: trading hash
"0020f5d6b87c246595d1b060a3fa8bac6a2992490e38fdfcad40db2a3908297e7979"
+Example passes two NULS to the specified contract
nuls>>> transfertocontract tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD tNULSeBaN1NRtaj1ZPAmEmTqcpkyCLqv64PR7U 2 remark
+Please enter your account password
+**********
+"0020f5d6b87c246595d1b060a3fa8bac6a2992490e38fdfcad40db2a3908297e7979"
+NRC20 token transfer
| Parameter | Description |
|---|---|
| <formAddress> | sender address |
| <toAddress | receiver address |
| <contractAddress> | contract address |
| <amount> | transfer amount |
| [remark] | remark |
Returns: trading hash
"002022dffd96026b493945d2cf9ad276c4bc9655c735b72e6fcc85a2d19f6cbe25e8"
+example token transfer:
nuls>>> tokentransfer tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD tNULSeBaNBh9RUsVrVmMy8NHcZJ2BhNVsM1Vta tNULSeBaN6pwyVwXjfpm5BMH5eiirvthoZDVEc 200000 25 10000
+Please enter your account password
+**********
+"002022dffd96026b493945d2cf9ad276c4bc9655c735b72e6fcc85a2d19f6cbe25e8"
+Gets the transaction information of the contract, including the transaction details, the contract invocation parameters, and the contract execution results
| Parameter | Description |
|---|---|
| <hash> | transaction hash |
return value
skip
+example
nuls>>> getcontracttx 00203a48dcfc26426152805be49830c72005b4648d0182bbf6c2e8980380364eb59f
+getcontracttx 00203a48dcfc26426152805be49830c72005b4648d0182bbf6c2e8980380364eb59f
+{
+ "hash" : "00203a48dcfc26426152805be49830c72005b4648d0182bbf6c2e8980380364eb59f",
+ "type" : "100",
+ "time" : "2019-03-26 09:28:26",
+ "blockHeight" : 46,
+ "fee" : 0.0,
+ "value" : 0.0,
+ "remark" : null,
+ "scriptSig" : "210318f683066b45e7a5225779061512e270044cc40a45c924afcf78bb7587758ca0004630440220112a446b2a684510b4016fa97b92d2f3fead03128f0f658c99a6a8d230d05d4e02201e23a2f6e68aacdff2d117bd5bbe7ce2440babfe4211168eafbae41acad5d505",
+ "status" : "confirm",
+ "confirmCount" : 0,
+ "size" : 6686,
+ "inputs" : [ {
+ "address" : "tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD",
+ "assetsChainId" : 2,
+ "assetsId" : 1,
+ "amount" : "5700000",
+ "nonce" : "ffffffff",
+ "locked" : 0,
+ "value" : 0.0
+ } ],
+ "outputs" : [ ],
+ "txData" : {
+ "data" : {
+ "sender" : "tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD",
+ "contractAddress" : "tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L",
+ "value" : 0.0,
+ "hexCode" : "504b03040a0000080...........31600000000",
+ "gasLimit" : 200000,
+ "price" : "0.00000025",
+ "args" : [ [ "QKB" ], [ "QKB" ], [ "2000000" ], [ "2" ] ]
+ }
+ },
+ "contractResult" : {
+ "success" : true,
+ "errorMessage" : null,
+ "contractAddress" : "tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L",
+ "result" : null,
+ "gasLimit" : 200000,
+ "gasUsed" : 14029,
+ "price" : "0.00000025",
+ "totalFee" : 0.0,
+ "txSizeFee" : 0.0,
+ "actualContractFee" : 0.0,
+ "refundFee" : 0.0,
+ "stateRoot" : "be76399c41a8cb4be5ecf80e04dab36830b124cb1c43fea6ca69ae62259899ba",
+ "value" : 0.0,
+ "stackTrace" : null,
+ "balance" : 0.0,
+ "transfers" : [ ],
+ "events" : [ "{\"contractAddress\":\"tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L\",\"blockNumber\":46,\"event\":\"TransferEvent\",\"payload\":{\"from\":null,\"to\":\"tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD\",\"value\":\"200000000\"}}" ],
+ "tokenTransfers" : [ {
+ "contractAddress" : "tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L",
+ "from" : null,
+ "to" : "tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD",
+ "value" : "200000000",
+ "name" : "QKB",
+ "symbol" : "QKB",
+ "decimals" : 2
+ } ],
+ "remark" : "create"
+ }
+}
+
+
+Gets the execution result of a contract
| Parameter | Description |
|---|---|
| <hash> | transaction hash |
return value
skip
+example
nuls>>> getcontractresult 00203a48dcfc26426152805be49830c72005b4648d0182bbf6c2e8980380364eb59f
+{
+ "success" : true,
+ "errorMessage" : null,
+ "contractAddress" : "tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L",
+ "result" : null,
+ "gasLimit" : 200000,
+ "gasUsed" : 14029,
+ "price" : "0.00000025",
+ "totalFee" : 0.0,
+ "txSizeFee" : 0.0,
+ "actualContractFee" : 0.0,
+ "refundFee" : 0.0,
+ "stateRoot" : "be76399c41a8cb4be5ecf80e04dab36830b124cb1c43fea6ca69ae62259899ba",
+ "value" : 0.0,
+ "stackTrace" : null,
+ "balance" : 0.0,
+ "transfers" : [ ],
+ "events" : [ "{\"contractAddress\":\"tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L\",\"blockNumber\":46,\"event\":\"TransferEvent\",\"payload\":{\"from\":null,\"to\":\"tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD\",\"value\":\"200000000\"}}" ],
+ "tokenTransfers" : [ {
+ "contractAddress" : "tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L",
+ "from" : null,
+ "to" : "tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD",
+ "value" : "200000000",
+ "name" : "QKB",
+ "symbol" : "QKB",
+ "decimals" : 2
+ } ],
+ "remark" : "create"
+}
+
+Gets the list of parameters that need to be passed in to create the specified contract
| Parameter | Description |
|---|---|
| <contractCode> | Hex code of the contract code |
return value
skip
+example
nuls>>> getcontractcontructor 504b03040a000008000.........20000b31600000000
+{
+ "constructor" : {
+ "name" : "<init>",
+ "desc" : "(String name, String symbol, BigInteger initialAmount, int decimals) return void",
+ "args" : [ {
+ "type" : "String",
+ "name" : "name",
+ "required" : true
+ }, {
+ "type" : "String",
+ "name" : "symbol",
+ "required" : true
+ }, {
+ "type" : "BigInteger",
+ "name" : "initialAmount",
+ "required" : true
+ }, {
+ "type" : "int",
+ "name" : "decimals",
+ "required" : true
+ } ],
+ "returnArg" : "void",
+ "view" : false,
+ "event" : false,
+ "payable" : false
+ },
+ "isNrc20" : true
+}
+
+Gets the list of contracts created by the specified account address
| Parameter | Description |
|---|---|
| <createAddress> | account address |
return value
{
+ "contractAddress" : "tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L",
+ "createTime" : "2019-03-26 09:28:26.026",
+ "height" : 46,
+ "confirmCount" : 402,
+ "remarkName" : null,
+ "status" : 2,
+ "msg" : null,
+ "create" : true
+}
+example
nuls>>> getaccountcontracts tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD
+[ {
+ "contractAddress" : "tNULSeBaMz7vkyhgqLXVdcT75dC5udULVs1D2L",
+ "createTime" : "2019-03-26 09:28:26.026",
+ "height" : 46,
+ "confirmCount" : 402,
+ "remarkName" : null,
+ "status" : 2,
+ "msg" : null,
+ "create" : true
+}, {
+ "contractAddress" : "tNULSeBaMzsHrbMy2VK23RzwjkXS1qo2ycG5Cg",
+ "createTime" : "2019-03-25 16:08:25.025",
+ "height" : 253,
+ "confirmCount" : 195,
+ "remarkName" : null,
+ "status" : 0,
+ "msg" : null,
+ "create" : true
+}, {
+ "contractAddress" : "tNULSeBaNBYK9MQcWWbfgFTHj2U4j8KQGDzzuK",
+ "createTime" : "2019-03-25 15:33:54.054",
+ "height" : 46,
+ "confirmCount" : 402,
+ "remarkName" : null,
+ "status" : 0,
+ "msg" : null,
+ "create" : true
+} ]
+Query network basic information
Return
{
+ "localBestHeight" : 35317,//latest block height locally
+ "netBestHeight" : 35317,//latest block height of the network
+ "timeOffset" : "0ms",//network time offset
+ "inCount" : 0,//number of in-nodes
+ "outCount" : 1//number of out-nodes
+}
+Example
nuls>>> network info
+{
+ "localBestHeight" : 35317,
+ "netBestHeight" : 35317,
+ "timeOffset" : "0ms",
+ "inCount" : 0,
+ "outCount" : 1
+}
+Query the network node IP
Return information
[" 192.168.1.223 "]
+Example: get a block with the block height
nuls>>> network nodes
+[ "192.168.1.223" ]
+Exit the command line that operates the wallet, while it won’t stop the launched wallet node.
Example
nuls>>> exit
++ ← + + Develop Business Modules + + Build Chain + + → +
The Nuls2 base module is developed using java11, which uses a distributed multi-module micro-service architecture, and uses websocket for communication between modules. However, there is no language requirement between modules. The language that can support the websocket protocol for network programming can be a module of NULS2, so you need to have a certain understanding of the websocket protocol.
The source code for NULS2 is hosted on github.com and is freely available to anyone. Project address nuls_2.0, see git for how to get it.
If you want to develop or debug the source code of NULS2, you need to prepare the development environment, install JDK11.0.2, apache maven 3.3, and a development tool. We recommend IntelliJ IDEA. After the development environment and source code are ready, import the program module in IDEA by importing the maven project.

The module with the module.ncf file in the root directory of the module is defined as the nuls2 submodule, where mykernel is the core scheduling module, which is responsible for other submodule registration services. The startup class of each module is named XXXXBootstrap, and the main function of the startup class is used to start the module.

In the development environment, you first need to start the mykernel module, and then start other modules, the dependencies between modules are automatically controlled by the framework. When the "MYKELNEL STARTED. PORT:8887" is printed in the log, the mykernel module is successfully started.

Start other modules (take the ledger module as an example), find the LedgerBootstrap class, and run the main function.

When the log prints "RMB:module state : Running", the module starts successfully.

Once you have the source code, you can generate your own scripts from the source code. Run the script package.sh in the nuls2.0 root directory to execute the automatic packager (the script needs to rely on jdk11, maven3.3, git).
Execute the packager and copy the JDK in the /usr/local/java/jdk11.0.2 directory to the runtime directory to the wallet directory. The wallet can run the program output to the relative directory of ../NULS2.
./package.sh -J /usr/local/java/jdk11.0.2 -o ../NULS2
+When the log outputs XXXX PACKAGE FINISH, the packager is successfully generated.

More package.sh script parameters can be viewed with help in -h.
Lijunzhou:nuls_2.0 zhoulijun$ ./package.sh -h
+ Desc: Use this script to generate an executable submodule that conforms to the NULSTAR specification.
+ All submodules are configured according to module.ncf, packaged with the mvn command, and generate start and stop scripts.
+ Usage: ./package.sh
+ -b <branch> Synchronize the latest code before packaging. Parameter is the remote branch name for synchronization.
+ -p Synchronize the latest code before packing. Pull from the master branch
+ -o <directory> specifies the output directory
+ -h View help
+ -j JAVA_HOME
+ -J outputs the jvm virtual machine directory, the script will copy this directory to the program dependencies
+ -i skip mvn package
+ -z generates a tarball
+ Author: zlj
+Please refer to the [Command Line User Manual] (/zh/NULS2.0/linuxTutorial.html) for how to use the wallet.
+ ← + + Quick Start + + Develop Business Modules + + → +
Download JDK11 to the server and extract it.
Jdk11 download address: [jdk11 download] (https://www.oracle.com/technetwork/java/javase/downloads/jdk11-downloads-5066655.html)
Tar -zxvf jdk-11.0.2_linux-x64_bin.tar.gz
+
vi /ect/profile
Copy the following code to the file
JAVA_HOME=/home/nuls2/jdk-11.0.2
+PATH=$PATH:$JAVA_HOME/bin
+CLASSPATH=:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
+Export JAVA_HOME PATH CLASSPATH
+ps: /home/nuls2/jdk-11.0.2 is the path after jdk is pressurized, please configure according to your actual path.
source /ect/profile The configuration of this command takes effect.
View the jdk version via java -version:

Go to GitHub and download the latest version of the NULS2.0 Alpha1 wallet: [download address] (https://github.com/nuls-io/nuls_2.0/releases)
Tar -zxvf NULS-Walltet-linux64-alpha1.tar.gz
+
After the wallet is decompressed, go to the start.sh file directory: /home/nuls2/NULS-Walltet-linux64-alpha1/bin

Execute the command: ./start.sh -D
After the wallet is started, execute cmd.sh (./cmd.sh) in the same directory to enter the wallet command line. The NULS command prompts the prompt: nuls>gt;>, enter the NULS wallet operation command, and operate .

Command: create [Number]
Number: The number of account addresses created. The default is 1 and the maximum is 100.
+Command: backup <address> [Path]
Address: Account address to be backed up (required)
+Path: The directory where the backup file is generated. The default is the current directory (optional)
+Command: getprikey <address>
Address: Account address for obtaining the private key (required)
+Command: remove <address>
Address: address to be removed (required)
+Command: resetpwd <address>
Address: Account address to change the password (required)
+Command: transfer <FormAddress/FormAlias> <ToAddress/ToAlias><amount> [Remark]
FormAddress/FormAlias: Transfer the address or export the alias, choose one (required)
+ToAddress/ToAlias: Receive address or receive alias, choose one (required)
+Command: createagent <AgentAddress> <PackingAddress> <CommissionRate> <Deposit> [RewardAddress]
AgentAddress: Consensus node creation address (required)
+PackingAddress: The address of the consensus node is packed. The password must be the same as the configuration file. The default is: nuls123456 (required)
+CommissionRate: commission ratio, range: 10-100, maximum decimal place 2 digits (required) Deposit: margin, range: 20000-200000, maximum decimal place 8 digits (required) RewardAddress: reward address, default is node creation address ( Optional)
+ps: Save the hash of the consensus node (or query in [Browser] (http://alpha.nulscan.io)), join the consensus and query consensus node information needs to be used; Ensure that the consensus node creates an address and a packaged address in one wallet, and one wallet cannot create two consensus nodes at the same time.
Command: deposit<Address><AgentHash><Deposit>
Address: Account address to join the consensus (required)
+AgentHash: Create a hash of the consensus node (required)
+Deposit: Join the consensus deposit, 2000-500000, up to 8 decimal places (required)
+ps: Save the consensus hash, you need to use the exit consensus
Command: withdraw<Address><TxHash>
Address: Exit consensus address (required)
+TxHash: transaction hash at the time of delegation (required)
+Command: stopagent<Address>
Address: Consensus node creation address (required)
+Command: getagent<AgentHash>
AgentHash: Consensus node creates hash (required)
++ ← + + Introduction + + Package Generation + + → +
Background:Since the NULS Main-Net uses the UTXO model, the transaction size is also used as one of the charging standards.
In the main-net, there are now three more types of transactions: creating a smart contract, invoking a smart contract, deleting a smart contract
The difference between those three transactions and other transactions such as transfer is that the execution of smart contracts will be added. So, execution of smart contracts will also be applied to the charging standards.
public static final int COMPARISON = 1 ; //Compare bytecode
+public static final int CONSTANT = 1 ; //Simple numeric type bytecode
+public static final int LDC = 1 ; //Numeric constant, string constant (length * LDC)
+public static final int CONTROL = . 5 ; //Control bytecode
+public static final int TABLESWITCH = 2 ; //Switch bytecode (size * TABLESWITCH)
+public static final int LOOKUPSWITCH = 2 ; //Switch bytecode (size * LOOKUPSWITCH)
+public static final int CONVERSION = 1 ; //Value conversion
+public static final int EXTENDED = 1 ; //Null determine
+public static final int MULTIANEWARRAY = 1 ; //Multidimensional Array (size * MULTIANEWARRAY)
+public static final int LOAD = 1 ; / /Send the local variable to the top of the stack
+public static final int ARRAYLOAD = 5 ; / /Send an item of the array to the top of the stack
+public static final int MATH = 1 ; //Mathematical operations and shift operations
+public static final int REFERENCE = 10 ; //Object related operations
+public static final int NEWARRAY = 1 ; //One-dimensional array (size * NEWARRAY)
+public static final int STACK = 2 ; //Stack operation
+public static final int STORE = 1 ; // Save the value in the top of the stack to a local variable
+public static final int ARRAYSTORE = 5; //Save the value of the stack to an array
+public static final int TRANSFER = 1000 ; //Transfer transaction
+
+The first part is the transaction fee based on the transaction size, calculated according to the byte size -> 0.001NULS/KB, which is 0.001 NULS per 1000 bytes. If the transaction size is less than 1000 bytes, the transaction fee is set as 0.001 NULS.
The second part is the ‘Gas*Price’ consumed by executing the contract. The ‘Price’ is the unit cost, which means how much ‘Na’ there is for each Gas. ‘Na’ is the smallest unit of NULS, and 1 NULS = 100 million Na.
For example, if executing a contract consumes 20,000 Gas and the set Price is 20 Na/Gas, then the Na consumed this time would be 20,000 * 20 = 400,000 Na, which is 0.004 NULS.
Still using the previous example, if the GasLimit set for the contract is 30,000 Gas and executing the contract consumes 20,000 Gas, then 10,000 Gas will be left. The 10,000 Gas has: 10,000 * 20 = 200,000 Na, which is 0.002 NULS. This will be returned to the contract invoker in the CoinBase transaction (consensus reward) of the current packing block.
To start the contract transaction, the contract invoker pays the first, second and third part. In practical, the third part will be returned to the contract invoker in the CoinBase transaction (consensus reward) of the current packing block.
Precondition:This part of the cost is reflected in the CoinBase transaction (consensus reward) of the block.
The block packer receives the first and second parts of the service charge, and the contract invoker receives the third part.
Preparations for deployment and invocation of smart contracts
Preparations for the development of smart contract code
[Downloading JDK8] +(https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) (Installation omitted)
[Downloading IntelliJ IDEA] (https://www.jetbrains.com/idea/download/) (Installation omitted)
[Downloading NULS smart contract plug-ins] +(https://nuls-usa-west.oss-us-west-1.aliyuncs.com/plugins/Docs%26plugin.zip)
[Installing the NULS smart contract plug-ins] (https://dev.nuls.io/zh-cn/contract/IdeaPlugin.html)
_Quickly compile and deploy a smart contract with the example _
+Import io.nuls.contract.sdk.Contract;
+Import io.nuls.contract.sdk.Msg;
+Import io.nuls.contract.sdk.annotation.Payable;
+Import io.nuls.contract.sdk.annotation.Required;
+Import io.nuls.contract.sdk.annotation.View;
+
+Import java.math.BigDecimal;
+Import java.math.BigInteger;
+
+Public class SimpleContract implements Contract {
+
+ Private String sayContent;
+
+ @Override
+ @Payable
+ Public void _payable() {
+ // override this method and mark the @Payable annotation. The smart contract can receive direct transfer of the NULS wallet assets
+ // you can do something else
+ // ...
+ }
+
+ Public String sayContent(@Required String content) {
+ this.sayContent = content;
+ Return "you want say " + content;
+ }
+
+ @Payable
+ Public String transferToContract() {
+ // mark the @Payable annotation. Smart contract can receive NULS when invoking this method
+ BigInteger value = Msg.value();
+ BigDecimal nuls = new BigDecimal(value).movePointLeft(8);
+ // you can do something else
+ // ...
+
+ Return "I received your transfer amount: " + nuls.toPlainString();
+ }
+
+ @View
+ Public String sayWhat() {
+ If(sayContent != null) {
+ Return "you want say " + sayContent;
+ }
+ Return "you want say nothing.";
+ }
+}
+
+[Smart contract repository collected by NULS officials] (https://github.com/nuls-io/contracts)
[Community member Angelillou's smart contract - Partnership income distribution smart contract] (https://github.com/amalcaraz/nuls-partnership-smartcontract)
[Community member Angelillou's smart contract - Lottery factory smart contract for Nuls blockchain)
[Community member Naveen's Smart Contracts - Contract to write reviews for any product] (https://github.com/naveen7252/ProductReviewContract)
[How to deploy and invoke the wallet smart contract] +(https://dev.nuls.io/zh-cn/contract/smartContract.html)
[Smart contract specifications and syntax] (https://dev.nuls.io/zh-cn/contract/index.html)
+ ← + + Build Chain + + Development Manual + + → +