停用硬盤后关机硬盘smart信息读取中的C0会+1

【区块链公开课三期视频】如何编写智能合约(Smart Contract)?(一)
如何编写智能合约(Smart Contract)?(一)
了解智能合约
简单环境搭建
能够利用solidity编写Hello World合约
和合约互动
使用solidity语言撰写智能合约
Ethereum上的智能合约需要使用solidity语言来撰写。虽然还有其他能用来撰写智能合约的语言如Serpent(类Python)、lll(类Fortran),但目前看到所有公开的智能合约都是使用solidity撰写。
宣传上说,solidity是一种类似Java的语言,而且围绕着solidity的各种开发工具链,都是使用属于Java生态系的npm来提供的。但我觉得solidity还是比较像Java或C#。因为和Java不同,solidity与Java或C#同属于强类型(Strong Type,在定义变数时需要指定类型)语言、在定义函式(function)时同样需指定回传的类型(type)、同样也需要先编译才能执行。这些特性都是Java所不具备的。 开发前的准备
本文将使用当前最活跃的智能合约开发框架truffle为基础来开发。ENS(Ethereum Name Service)也是采用truffle框架。其他选择还有embark等。
就像一般网站或App开发一样,在提供公开服务之前,开发者会在自己用于写程序的电脑(又称作本机)或透过测试网络来测试程序执行的效果,测试完成后,才会部署到公开的网络上提供服务。开发区块链智能合约(程序)的过程也是如此。特别是公开链上所有写入或读取计算结果的操作都需要真金白银(虚拟代币),而且根据网络状况,每个公开链上的操作都需要要一小段反应时间(15秒~数分钟),这些等待颇浪费宝贵的开发时间?。因此在开发的过程中,我们将使用testrpc工具在电脑上模拟智能合约所需的以太坊内存块链测试环境。
testrpc中也包含了Java版本的Ethereum虚拟机(Ethereum Virtual Machine),因此可以完整地执行智能合约。
此外,开发前还需准备一个合手的编辑器。我目前是使用Atom搭配solidity插件来开发。solidity插件除了支持语法高亮之外,也会透过Solium检查并提示基本的语法错误,相当方便。其他编辑器应该也有类似的插件可选择。 安装所需工具
首先开发机上必须装好Node.js,再使用以下命令安装所需的工具: $ npm install -g ethereumjs-testrpc truffle liyuechun:~ yuechunli$ npm install -g ethereumjs-testrpc truffle /usr/local/bin/testrpc -& /usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js /usr/local/bin/truffle -& /usr/local/lib/node_modules/truffle/build/cli.bundled.js + truffle@3.4.9+ ethereumjs-testrpc@4.1.3added 1 package and updated 7 packages in76.132s liyuechun:~ yuechunli$ 启动Testrpc
安装好后随时可以使用testrpc命令来启动以太坊测试环境。 liyuechun:~ yuechunli$ testrpc EthereumJS TestRPC v4.1.3 (ganache-core: 1.1.3) Available Accounts ================== (0) 0xbbd414b340f2255dab9df0b65d9df81 (1) 0xeb6fcadf229c7c4fea25e (2) 0xc79eb9e499dd6f569be (3) 0x9a6fd4dbbba) 0x5b13a5ddd4e338aae2e0e (5) 0xfc7f56d942ad5260be23ecee92a344aba1b7e7d8 (6) 0xc48dc22c6bacd6adebc45c1c5x3fe2b7d661fcbaf3b78f (8) 0x567979fed26ca85e9d1b4ac919c840e3fc) 0xb2eafe245f098eef1c2c1f466d9a8dcd58764c62 Private Keys ================== (0) 947ab78eca099d60e6c38cac5bb769f7f097c82d003cf058500bd (1) 8ffe0ba8dc53e16944a17dddd3378b5fbaed05b8762f (2) ffe2e04e43e56f5233bcc3e0cdf9c1def (3) a20e453dc44c76aaca6a22efdbb605c2ed9eea64ce11bd105ea7 (4) bd07a1b121b427e1bdede5dbb3c14efb1a5 (5) fd20d38be6c4f87d5fbb46 (6) 34e648b23c0ace6b2bf70be8496f97ecf6b7b4607b2acc4e05c9bd (7) d2477cedec217e3fb19a5981dafbc125ef66ccc9dc7dfda843cf5 (8) d319f85ccd80e55b2e707e05fcb96f82ea5eeaeefc33ac9fe82f86a0ce307e3bd8fcf683bf193f5bdc668 HD Wallet ================== Mnemonic: hire custom clinic expect fury fantasy try dress source spy viable flag Base HD Path: m/44'/60'/0'/0/{account_index} Listening on localhost:8545
可以看到testrpc启动后自动建立了10个帐号(Accounts),与每个帐号对应的私钥(Private Key)。每个帐号中都有100个测试用的以太币(Ether)。要注意testrpc仅运行在內存中,因此每次重开时都会回到全新的状态。
一切准备就绪,我们可以开始建立第一份智能合约项目了。 建立项目
开启另一个终端窗口,输入以下命令以建立项目: liyuechun:Desktop yuechunli$ mkdir SmartContractDemo liyuechun:Desktop yuechunli$ cd SmartContractDemo/ liyuechun:SmartContractDemo yuechunli$ mkdir HelloWorld liyuechun:SmartContractDemo yuechunli$ cd HelloWorld/ liyuechun:HelloWorld yuechunli$ truffle init Downloading project... Project initialized. Documentation: http://truffleframework.com/docs Commands: Compile: truffle compile Migrate: truffle migrate Test: truffle test liyuechun:HelloWorld yuechunli$ ls contracts migrations test truffle.js 目录结构:
/contracts:存放智能合约原始代码的地方,可以看到里面已经有三个sol文件,我们开发的HelloWorld.sol文件就存放在这里。
/migrations:这是 Truffle用来部署智能合约的功能,待会儿我们会修改2_deploy_contracts.js来部署 HelloWorld.sol。/test:测试智能合约的代码放在这里,支持js 与 sol 测试。truffle.js:Truffle 的设置文档。
新建HelloWorld合约
在contracts文件夹下新建HelloWorld.sol文件,当然也可以直接在HelloWorld路径下面直接执行truffle create contract HelloWorld命令来创建HelloWorld.sol。
HelloWorld.sol文件內容如下: pragma solidity ^0.4.4; contract HelloWorld { functionsayHello()returns(string){ return ("Hello World"); } } 讲解 pragma solidity ^0.4.4;
第一行指名目前使用的solidity版本,不同版本的solidity可能会编译出不同的bytecode。^代表兼容solidity``0.4.4 ~ 0.4.9的版本。 contract HelloWorld { ... }
contract关键字类似于其他语言中较常见的class。因为solidity是专为智能合约(Contact)设计的语言,声明contract后即内置了开发智能合约所需的功能。也可以把这句理解为class HelloWorld extends Contract。 functionsayHello()returns(string){ return ("Hello World"); }
函数的结构与其他程序类似,但如果有传入的参数或回传值,需要指定参数或回传值的类型(type)。 编译
现在执行truffle compile命令,我们可以将HelloWorld.sol原始码编译成Ethereum bytecode。 liyuechun:HelloWorld yuechunli$ ls contracts migrations test truffle.js liyuechun:HelloWorld yuechunli$ truffle compile Compiling ./contracts/ConvertLib.sol... Compiling ./contracts/HelloWorld.sol... Compiling ./contracts/MetaCoin.sol... Compiling ./contracts/Migrations.sol... Writing artifacts to ./build/contracts liyuechun:HelloWorld yuechunli$ ls build contracts migrations test truffle.js liyuechun:HelloWorld yuechunli$ cd build/ liyuechun:build yuechunli$ ls contracts liyuechun:build yuechunli$ cd contracts/ liyuechun:contracts yuechunli$ ls ConvertLib.json HelloWorld.json MetaCoin.json Migrations.json liyuechun:contracts yuechunli$ cat HelloWorld.json { "contract_name": "HelloWorld", "abi": [ { "inputs": [], "payable": false, "type": "constructor" } ], "unlinked_binary": "0x80fd5b5b5b5bbaaee98abc0aba8df5bbf63e", "networks": {}, "schema_version": "0.0.5", "updated_at": 2} liyuechun:contracts yuechunli$
编译成功后,会在HelloWorld文件夹下面的build/contracts文件夹下面看见HelloWorld.json文件。 部署
truffle框架中提供了方便部署合约的脚本。打开migrations/2_deploy_contracts.js文件(脚本使用Java编写),将内容修改如下: var HelloWorld = artifacts.require("HelloWorld");module.exports = function(deployer){ deployer.deploy(HelloWorld); };
使用artifacts.require语句来取得准备部署的合约。使用deployer.deploy语句将合约部署到区块链上。这边HelloWorld是contract的名称而不是文件名。因此可以用此语法读入任一.sol文件中的任一合约。
现在执行truffle migrate命令: liyuechun:HelloWorld yuechunli$ ls build contracts migrations test truffle.js liyuechun:HelloWorld yuechunli$ truffle migrate Compiling ./contracts/HelloWorld.sol... Writing artifacts to ./build/contracts Using network 'development'. Running migration: 1_initial_migration.js Deploying Migrations... ... 0xa5cadcdbcc9dc9b Migrations: 0x64e642afb7f2ea9bcdSaving successful migration to network... ... 0xd9ec788c106df36bab02ff1e5ef22c6ecSaving artifacts... Running migration: 2_deploy_contracts.js Deploying HelloWorld... ... 0xd7bc7abbda6a1fce30c290ca9140450ea HelloWorld: 0x471a22ffe2bddd02e67e4c07a7f4Saving successful migration to network... ... 0xe5e2e11cf5a63cadadb3cae2ca42cbfed93c09c575b6d5f275fc8bSaving artifacts... liyuechun:HelloWorld yuechunli$
如此一来合约已经部署到testrpc中。切换到testrpc窗口,可以看到testrpc有反应了。
与合约互动
truffle提供命令行工具,执行truffle console命令后,可用Java来和刚刚部署的合约互动。 liyuechun:HelloWorld yuechunli$ ls build contracts migrations test truffle.js liyuechun:HelloWorld yuechunli$ truffle consoletruffle(development)& HelloWorld.deployed().then(instance =& contract = instance) TruffleContract { constructor: { [Function: TruffleContract] _static_methods: { setProvider: [Function: setProvider], new: [Function: new], at: [Function: at], deployed: [Function: deployed], defaults: [Function: defaults], hasNetwork: [Function: hasNetwork], isDeployed: [Function: isDeployed], detectNetwork: [Function: detectNetwork], setNetwork: [Function: setNetwork], resetAddress: [Function: resetAddress], link: [Function: link], clone: [Function: clone], addProp: [Function: addProp], toJSON: [Function: toJSON] }, _properties: { contract_name: [Object], abi: [Object], network: [Function: network], networks: [Function: networks], address: [Object], links: [Function: links], events: [Function: events], binary: [Function: binary], unlinked_binary: [Object], schema_version: [Function: schema_version], updated_at: [Function: updated_at] }, _property_values: {}, _json: { contract_name: 'HelloWorld', default_network: undefined, abi: [Array], unlinked_binary: '0x0b1ff263ffffffff7cef5fb05b5bbbc505bf35ba565bbc6c6f565baad4dd8e4ea58db573fa09a0b634d1d5bd76ba330029', networks: [Object], schema_version: '0.0.5', updated_at: 5 }, setProvider: [Function: bound setProvider], new: [Function: bound new], at: [Function: bound at], deployed: [Function: bound deployed], defaults: [Function: bound defaults], hasNetwork: [Function: bound hasNetwork], isDeployed: [Function: bound isDeployed], detectNetwork: [Function: bound detectNetwork], setNetwork: [Function: bound setNetwork], resetAddress: [Function: bound resetAddress], link: [Function: bound link], clone: [Function: bound clone], addProp: [Function: bound addProp], toJSON: [Function: bound toJSON], web3: Web3 { _requestManager: [Object], currentProvider: [Object], eth: [Object], db: [Object], shh: [Object], net: [Object], personal: [Object], bzz: [Object], settings: [Object], version: [Object], providers: [Object], _extend: [Object] }, class_defaults: { from: '0xbbd414b340f2255dab9df0b65d9df81', gas: 4712388, gasPrice:
}, currentProvider: HttpProvider { host: 'http://localhost:8545', timeout: 0, send: [Function], sendAsync: [Function], _alreadyWrapped: true }, network_id: '5' }, abi: [ { constant: false, inputs: [], name: 'sayHello', outputs: [Array], payable: false, type: 'function' } ], contract: Contract { _eth: Eth { _requestManager: [Object], getBalance: [Object], getStorageAt: [Object], getCode: [Object], getBlock: [Object], getUncle: [Object], getCompilers: [Object], getBlockTransactionCount: [Object], getBlockUncleCount: [Object], getTransaction: [Object], getTransactionFromBlock: [Object], getTransactionReceipt: [Object], getTransactionCount: [Object], call: [Object], estimateGas: [Object], sendRawTransaction: [Object], signTransaction: [Object], sendTransaction: [Object], sign: [Object], compile: [Object], submitWork: [Object], getWork: [Object], coinbase: [Getter], getCoinbase: [Object], mining: [Getter], getMining: [Object], hashrate: [Getter], getHashrate: [Object], syncing: [Getter], getSyncing: [Object], gasPrice: [Getter], getGasPrice: [Object], accounts: [Getter], getAccounts: [Object], blockNumber: [Getter], getBlockNumber: [Object], protocolVersion: [Getter], getProtocolVersion: [Object], iban: [Object], sendIBANTransaction: [Function: bound transfer] }, transactionHash: null, address: '0x471a22ffe2bddd02e67e4c07a7f4', abi: [ [Object] ], sayHello: { [Function: bound ] request: [Function: bound ], call: [Function: bound ], sendTransaction: [Function: bound ], estimateGas: [Function: bound ], getData: [Function: bound ], '': [Circular] }, allEvents: [Function: bound ] }, sayHello: { [Function] call: [Function], sendTransaction: [Function], request: [Function: bound ], estimateGas: [Function] }, sendTransaction: [Function], send: [Function], allEvents: [Function: bound ], address: '0x471a22ffe2bddd02e67e4c07a7f4', transactionHash: null } truffle(development)& contract.sayHello.call()'Hello World'truffle(development)& 讲解 HelloWorld.deployed().then(instance =& contract = instance)
truffle console中预载了truffle-contract函数库,以方便操作部署到区块链上的合约。
这边使用HelloWorld.deployed().then语句来取得HelloWorld合约的Instance(实例),并存到contract变量中,以方便后续的调用。
上面用的是Java ES6+的语法,这句也可以写成: HelloWorld.deployed().then(instance =& { contract = instance });
还可以用ES5的写法: HelloWorld.deployed().then(function(instance){ hello = }); truffle(development)& contract.sayHello.call()'Hello World'
这里直接呼叫contract.sayHello()也会得到一样的结果。truffle-contract提供使用call()来读取只读(read only)的数据,这样就不需提供gas。因此如果遇到的操作需要向区块链写入数据,我们就不能用call语句了。
如此一来,我们已写好并部署完成了第一个智能合约,也验证了合约确实可以运作。 加入新方法
我们在HelloWorld.sol中再加入一个echo方法,echo方法接受输入一个参数,并回传传送的参数。 functionecho(string name)constantreturns(string){ }
新的echo方法中传入了一个name参数。我们也为echo方法加入一个constant声明,表示调用这个方法并不会改变区块链的状态。如此一来,透过truffle-contract来调用此方法时,会自动选用call来呼叫,也不需要额外提供gas。
由于更新了合约内容,我们需要先重新新编译一次,将编译结果部署到testrpc上,再透过truffle console执行看看结果。 liyuechun:HelloWorld yuechunli$ ls build contracts migrations test truffle.js liyuechun:HelloWorld yuechunli$ truffle compile Compiling ./contracts/HelloWorld.sol... Writing artifacts to ./build/contracts liyuechun:HelloWorld yuechunli$ truffle migrate --reset Using network 'development'. Running migration: 1_initial_migration.js Replacing Migrations... ... 0x64cdc42e08a7e3f7ba246d95cbbccbfe1b9abd2450cfc02b48eda Migrations: 0xb84ea223c1bdefb6f4dSaving successful migration to network... ... 0xf40a4f88ce855ed5ae5fc1f7f36ea0e5b3Saving artifacts... Running migration: 2_deploy_contracts.js Replacing HelloWorld... ... 0xaae9d6bed235fc6dc59ae209df4cf8f12b HelloWorld: 0xbf68789cdd6bec739abfacSaving successful migration to network... ... 0xb4b706d7ea2bdc43b688b466b10159Saving artifacts... liyuechun:HelloWorld yuechunli$ truffle consoletruffle(development)& let contractundefinedtruffle(development)& HelloWorld.deployed().then(instance =& contract = instance) TruffleContract { constructor: { [Function: TruffleContract] _static_methods: { setProvider: [Function: setProvider], new: [Function: new], at: [Function: at], deployed: [Function: deployed], defaults: [Function: defaults], hasNetwork: [Function: hasNetwork], isDeployed: [Function: isDeployed], detectNetwork: [Function: detectNetwork], setNetwork: [Function: setNetwork], resetAddress: [Function: resetAddress], link: [Function: link], clone: [Function: clone], addProp: [Function: addProp], toJSON: [Function: toJSON] }, _properties: { contract_name: [Object], abi: [Object], network: [Function: network], networks: [Function: networks], address: [Object], links: [Function: links], events: [Function: events], binary: [Function: binary], unlinked_binary: [Object], schema_version: [Function: schema_version], updated_at: [Function: updated_at] }, _property_values: {}, _json: { contract_name: 'HelloWorld', default_network: undefined, abi: [Array], unlinked_binary: '0x0b1ff263ffffffff7cef5fb05b5bbbc565bb5bfcbbde525bf565bfcbee565bbc6c6f565bee565b565baafeceed53de80b1a32a91caab996bb270d54425ebd7140029', networks: [Object], schema_version: '0.0.5', updated_at: 0 }, setProvider: [Function: bound setProvider], new: [Function: bound new], at: [Function: bound at], deployed: [Function: bound deployed], defaults: [Function: bound defaults], hasNetwork: [Function: bound hasNetwork], isDeployed: [Function: bound isDeployed], detectNetwork: [Function: bound detectNetwork], setNetwork: [Function: bound setNetwork], resetAddress: [Function: bound resetAddress], link: [Function: bound link], clone: [Function: bound clone], addProp: [Function: bound addProp], toJSON: [Function: bound toJSON], web3: Web3 { _requestManager: [Object], currentProvider: [Object], eth: [Object], db: [Object], shh: [Object], net: [Object], personal: [Object], bzz: [Object], settings: [Object], version: [Object], providers: [Object], _extend: [Object] }, class_defaults: { from: '0xbbd414b340f2255dab9df0b65d9df81', gas: 4712388, gasPrice:
}, currentProvider: HttpProvider { host: 'http://localhost:8545', timeout: 0, send: [Function], sendAsync: [Function], _alreadyWrapped: true }, network_id: '5' }, abi: [ { constant: false, inputs: [], name: 'sayHello', outputs: [Array], payable: false, type: 'function' }, { constant: true, inputs: [Array], name: 'echo', outputs: [Array], payable: false, type: 'function' } ], contract: Contract { _eth: Eth { _requestManager: [Object], getBalance: [Object], getStorageAt: [Object], getCode: [Object], getBlock: [Object], getUncle: [Object], getCompilers: [Object], getBlockTransactionCount: [Object], getBlockUncleCount: [Object], getTransaction: [Object], getTransactionFromBlock: [Object], getTransactionReceipt: [Object], getTransactionCount: [Object], call: [Object], estimateGas: [Object], sendRawTransaction: [Object], signTransaction: [Object], sendTransaction: [Object], sign: [Object], compile: [Object], submitWork: [Object], getWork: [Object], coinbase: [Getter], getCoinbase: [Object], mining: [Getter], getMining: [Object], hashrate: [Getter], getHashrate: [Object], syncing: [Getter], getSyncing: [Object], gasPrice: [Getter], getGasPrice: [Object], accounts: [Getter], getAccounts: [Object], blockNumber: [Getter], getBlockNumber: [Object], protocolVersion: [Getter], getProtocolVersion: [Object], iban: [Object], sendIBANTransaction: [Function: bound transfer] }, transactionHash: null, address: '0xbf68789cdd6bec739abfac', abi: [ [Object], [Object] ], sayHello: { [Function: bound ] request: [Function: bound ], call: [Function: bound ], sendTransaction: [Function: bound ], estimateGas: [Function: bound ], getData: [Function: bound ], '': [Circular] }, echo: { [Function: bound ] request: [Function: bound ], call: [Function: bound ], sendTransaction: [Function: bound ], estimateGas: [Function: bound ], getData: [Function: bound ], string: [Circular] }, allEvents: [Function: bound ] }, sayHello: { [Function] call: [Function], sendTransaction: [Function], request: [Function: bound ], estimateGas: [Function] }, echo: { [Function] call: [Function], sendTransaction: [Function], request: [Function: bound ], estimateGas: [Function] }, sendTransaction: [Function], send: [Function], allEvents: [Function: bound ], address: '0xbf68789cdd6bec739abfac', transactionHash: null } truffle(development)& contract.echo("春哥微信:liyc1215")'春哥微信:liyc1215'truffle(development)&
echo方法确实将我们输入的内容回传了。同时因为声明了constant,我们不需要直接调用call()方法,truffle会自动选用call来呼叫。
另一点需要注意的,是这次如果还是用truffle migrate命令,我们会得到如下信息: $ truffle migrate Using network 'development'. Network up to date.
Truffle会告诉你现在网络上的合约都已是最新的,但事实上刚刚程序中新增的方法并没有更新到内存块链上。要更新内存块链上已部署的程序,需要改写migrations中的脚本,但现在还不到介绍migration的时候。还好我们开发用的内存块链是怎么修改都没关系的testrpc,可以使用truffle migrate --reset命令直接重新在testrpc上部署一次。 总结
这篇文章非常简单,通过这篇文章,你将掌握如何配置开发环境、如何创建新项目、如何编译、如何部署合约以及了解整个智能合约开发的流程。 打赏地址
比特币:1FcbBw62FHBJKTiLGNoguSwkBdVnJQ9NUn以太坊:0xF055775eBD516ed50C682d4170645 技术交流
区块链技术交流QQ群:
「区块链部落」官方公众号
[1] Solidity http://solidity.readthedocs.io/en/latest/index.html
[2] Solidity線上編輯器 https://ethereum.github.io/browser-solidity/
[3] Truffle Framework http://truffleframework.com/
[4] Embark Framework https://github.com/iurimatias/embark-framework
[5] ENS也使用Truffle框架 https://github.com/ethereum/ens
[6] https://github.com/ethereumjs/testrpc
[7] https://github.com/ethereumjs/ethereumjs-vm
[8] HelloWorld範例修改自 https://app.pluralsight.com/library/courses/blockchain-fundamentals/
[9] Truffle issue on windows http://truffleframework.com/docs/advanced/configuration#resolving-naming-conflicts-on-windows
[10] https://medium.com/taipei-ethereum-meetup/ethereum-dapp-tutorial-push-button-cae
[11] Solidity支援的型別(Type) https://solidity.readthedocs.io/en/develop/types.html
[12] Solium syntax check https://github.com/duaraghav8/Solium
[13] https://medium.com/taipei-ethereum-meetup/如何撰寫智能合約-smart-contract-i-363d06b1965b
[14] http://truffleframework.com/docs/getting_started/contracts
责任编辑:
声明:该文观点仅代表作者本人,搜狐号系信息发布平台,搜狐仅提供信息存储空间服务。
今日搜狐热点

我要回帖

更多关于 硬盘smart信息读取中 的文章

 

随机推荐