如何开发编译部署调用智能合约

2024-08-28 23:32

本文主要是介绍如何开发编译部署调用智能合约,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

视频链接:http://yuntv.letv.com/bcloud.html?uu=obyao0lchj&vu=c0adea3148&auto_play=0&width=640&height=360&lang=zh_CN

转载链接:http://blog.csdn.net/u013137970/article/details/53018423

收藏,对区块链初学很有帮助!

前言

本文主要介绍智能合约的工作原理及其部署过程。

合约部署流程

一般来说,部署智能合约的步骤为1:

  1. 启动一个以太坊节点 (例如geth或者testrpc)。
  2. 使用solc编译智能合约。 => 获得二进制代码。
  3. 将编译好的合约部署到网络。(这一步会消耗以太币,还需要使用你的节点的默认地址或者指定地址来给合约签名。) => 获得合约的区块链地址和ABI(合约接口的JSON表示,包括变量,事件和可以调用的方法)。(译注:作者在这里把ABI与合约接口弄混了。ABI是合约接口的二进制表示。)
  4. 用web3.js提供的JavaScript API来调用合约。(根据调用的类型有可能会消耗以太币。)

下图表示了部署流程:

部署流程

你的DApp可以给用户提供一个界面先部署所需合约再使用之(如图1到4步),也可以假设合约已经部署了(常见方法),直接从使用合约(如图第6步)的界面开始。

智能合约实例

接下来我们将使用geth的控制台开发一个简单的智能合约并编译部署在私链上,最后与之交互。完成这些后,我们就能对智能合约的运行机制理解得更加深刻。本例子结合了汪晓明关于以太坊的开发的演示视频和以太坊项目有关交易和合约的wiki。

打开测试网络的控制台

输入以下命令:

geth --datadir "~/ethdev" --dev console 2>> geth.log
  • 1
  • 1

显示如下:

zcc@ubuntu:~$ geth --datadir "~/ethdev" --dev console 2>> geth.log
Welcome to the Geth JavaScript console!

instance: Geth/v1.4.18-stable/linux/go1.6.2
coinbase: 0xb005804a49e73acb17d1e7645dfd0a33dde6eb0e
at block: 217 (Tue, 01 Nov 2016 05:21:38 PDT)datadir: /home/zcc/ethdevmodules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 shh:1.0 txpool:1.0 web3:1.0>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

这样我们就打开了测试网的控制台,之后的步骤如无特别说明都将在控制台中完成。

检查编译器

我们接下来的智能合约的例子是使用solidity语言开发的。因此,至此之前我们要确保solidity编译器已经正确安装了。输入以下命令检查:

> eth.getCompilers()
["Solidity"]
  • 1
  • 2
  • 1
  • 2

我们发现solidity的编译器已经正确安装了。如果返回值为空数组,那么输入以下命令安装:

sudo add-apt-repository ppa:ethereum/ethereum
sudo apt-get update
sudo apt-get install solc
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

如果输入第一条命令的时候返回错误,请尝试重启系统。

编写智能合约

我们编写一个求解与7相乘结果的函数,即输入一个值a,返回a*7的值。

> source = "contract test { function multiply(uint a) returns(uint d) { return a * 7; }}"
"contract test { function multiply(uint a) returns(uint d) { return a * 7; }}"
  • 1
  • 2
  • 1
  • 2

编译智能合约

> contract = eth.compile.solidity(source).test
{code: "0x606060405260388060106000396000f3606060405260e060020a6000350463c6888fa18114601c575b6002565b3460025760076004350260408051918252519081900360200190f3",info: {abiDefinition: [{constant: false,inputs: [...],name: "multiply",outputs: [...],payable: false,type: "function"}],compilerOptions: "--bin --abi --userdoc --devdoc --add-std --optimize -o /tmp/solc359648392",compilerVersion: "0.4.3",developerDoc: {methods: {}},language: "Solidity",languageVersion: "0.4.3",source: "contract test { function multiply(uint a) returns(uint d) { return a * 7; }}",userDoc: {methods: {}}}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

注意:

在新版本solidity v0.4.9下不能使用".test",提示信息"undefined";

正确的命令如下:contract = web3.eth.compile.solidity(source)["<stdin>:test"]


准备一个创建合约的账户

在以太坊上创建智能合约就是使用一个外部账户(EOA)向区块链中发送一个交易。因此,我们需要准备一个有余额并被激活的以太坊外部账户。

查看是否有可用账户:

> personal.listAccounts
[]
  • 1
  • 2
  • 1
  • 2

返回为空,说明没有可用账户。创建一个外部账户:

> personal.newAccount('123456')
"0x62b1746767522b36f6421e630fa0198151d72964"
  • 1
  • 2
  • 1
  • 2

注意personal.newAccount()函数里的参数是账号密码,返回值是创建的新账号地址。

这个时候,我们再次使用personal.listAccounts命令查看可用账户:

> personal.listAccounts
["0x62b1746767522b36f6421e630fa0198151d72964"]
  • 1
  • 2
  • 1
  • 2

我们看到函数返回值为一个数组,数组目前只有一个元素,就是我们刚才创建的账号。

我们查看一下刚才创建的账户余额:

> web3.eth.getBalance(personal.listAccounts[0])
0
  • 1
  • 2
  • 1
  • 2

返回值为0,说明新创建的账户没有以太币。这个时候我们就可以开启挖矿来获得以太币。

首先开启挖矿:

> miner.start()
true
  • 1
  • 2
  • 1
  • 2

为了检测挖矿的状态,我们可以再另开起一个终端用于检测挖矿的状态。在新开起的终端中输入以下命令实时显示挖矿的状态:

tail -f geth.log
  • 1
  • 1

这样我们就能看到如下所示的挖矿状态:

zcc@ubuntu:~$ tail -f geth.log
I1102 10:10:21.382666 eth/backend.go:201] Blockchain DB Version: 3
I1102 10:10:21.382691 eth/backend.go:226] ethash used in test mode
I1102 10:10:21.384471 core/blockchain.go:214] Last header: #219 [7a2335e9…] TD=28838912
I1102 10:10:21.384501 core/blockchain.go:215] Last block: #219 [7a2335e9…] TD=28838912
I1102 10:10:21.384507 core/blockchain.go:216] Fast block: #219 [7a2335e9…] TD=28838912
I1102 10:10:21.389663 p2p/server.go:313] Starting Server
I1102 10:10:23.428074 p2p/discover/udp.go:217] Listening, enode://c7afa32e281c06bb529b9c0f0d9537ab4386cac1b2ba7de6bd777bdb15e3b7d0cbd260fc57f82b8f33b0c0ff83772b7d4da7c68017f8e05a2c08c77754d6ed62@[::]:39428
I1102 10:10:23.429805 whisper/whisper.go:176] Whisper started
I1102 10:10:23.439973 p2p/server.go:556] Listening on [::]:46364
I1102 10:10:23.440985 node/node.go:296] IPC endpoint opened: /home/zcc/ethdev/geth.ipc
I1102 10:13:11.541025 miner/miner.go:119] Starting mining operation (CPU=1 TOT=2)
I1102 10:13:11.541389 miner/worker.go:539] commit new work on block 220 with 0 txs & 0 uncles. Took 196.057µs
I1102 10:13:11.541464 ethash.go:259] Generating DAG for epoch 0 (size 32768) (0000000000000000000000000000000000000000000000000000000000000000)
I1102 10:13:11.541625 ethash.go:291] Generating DAG: 0%
I1102 10:13:11.541678 ethash.go:291] Generating DAG: 1%
I1102 10:13:11.541716 ethash.go:291] Generating DAG: 2%
I1102 10:13:11.541751 ethash.go:291] Generating DAG: 3%
I1102 10:13:11.541787 ethash.go:291] Generating DAG: 4%
I1102 10:13:11.541822 ethash.go:291] Generating DAG: 5%
...
I1102 10:13:11.547403 ethash.go:291] Generating DAG: 95%
I1102 10:13:11.547450 ethash.go:291] Generating DAG: 96%
I1102 10:13:11.547497 ethash.go:291] Generating DAG: 97%
I1102 10:13:11.547543 ethash.go:291] Generating DAG: 98%
I1102 10:13:11.547590 ethash.go:291] Generating DAG: 99%
I1102 10:13:11.547646 ethash.go:291] Generating DAG: 100%
I1102 10:13:11.547691 ethash.go:276] Done generating DAG for epoch 0, it took 6.229048ms
I1102 10:13:11.548248 eth/backend.go:454] Automatic pregeneration of ethash DAG ON (ethash dir: /home/zcc/.ethash)
I1102 10:13:11.548375 eth/backend.go:461] checking DAG (ethash dir: /home/zcc/.ethash)
I1102 10:13:24.938687 miner/worker.go:342] ��  Mined block (#220 / 1fdebe6d). Wait 5 blocks for confirmation
I1102 10:13:24.938953 miner/worker.go:539] commit new work on block 221 with 0 txs & 0 uncles. Took 86.067µs
I1102 10:13:24.939156 miner/worker.go:539] commit new work on block 221 with 0 txs & 0 uncles. Took 66.063µs
I1102 10:13:29.874128 miner/worker.go:342] ��  Mined block (#221 / ff995b19). Wait 5 blocks for confirmation
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

因为我之前已经挖过矿了,所以可以看到现在开始挖的区块编号为220。

再次使用web3.eth.getBalance(personal.listAccounts[0])命令来查看新建立的账号的余额:

> web3.eth.getBalance(personal.listAccounts[0])
65000000000000000000
  • 1
  • 2
  • 1
  • 2

这时我们看到当前账户余额为6.5e19wei,即65ether。我们可以参看Denominations来互相转换以太币的几种单位。

至此,用于创建合约的外部账户已经准备完毕。

指定创建合约的外部账户

我们首先需要从当前的账户里选择一个作为创建智能合约的外部账户:

> address = eth.accounts[0]
"0x62b1746767522b36f6421e630fa0198151d72964"
  • 1
  • 2
  • 1
  • 2

然后将该账户激活:

> personal.unlockAccount(address)
Unlock account 0x62b1746767522b36f6421e630fa0198151d72964
Passphrase: 
true
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

我们在使用personal.unlockAccount()函数的时候,可以选择指定一个解锁时间(以秒为单位),超出这个时间后会自动上锁。如果不指定的话,那么用户的账户就会在一定时间后自动上锁。例如:

> personal.unlockAccount(address,'123456',10000)
true
  • 1
  • 2
  • 1
  • 2

personal.unlockAccount()函数里第一个参数是要解锁的账户,第二个参数是账号密码,第三个是需要解锁的时间。在这个例子中,我们设定在10000秒内账户都处于激活状态。设定账号的解锁时间是个好方式,尤其是之后我们需要使用这个账号再次进行交易操作时,这样就省去了再次解锁账号的麻烦。不过,解锁时间不应设定过长,否则可能有安全隐患。

部署合约

部署合约就是将编译好的合约字节码通过外部账号发送交易的形式部署到以太坊区块链上。输入以下命令:

> abi = [{constant:false,inputs:{name:'a',type:'uint256'}}]
[{constant: false,inputs: {name: "a",type: "uint256"}
}]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
> MyContract = eth.contract(abi)
{abi: [{constant: false,inputs: {name: "a",type: "uint256"}}],eth: {accounts: ["0x62b1746767522b36f6421e630fa0198151d72964"],blockNumber: 292,coinbase: "0x62b1746767522b36f6421e630fa0198151d72964",compile: {lll: function(),serpent: function(),solidity: function()},defaultAccount: undefined,defaultBlock: "latest",gasPrice: 20000000000,hashrate: 3498,mining: true,pendingTransactions: [],syncing: false,call: function(),contract: function(abi),estimateGas: function(),filter: function(fil, callback),getAccounts: function(callback),getBalance: function(),getBlock: function(),getBlockNumber: function(callback),getBlockTransactionCount: function(),getBlockUncleCount: function(),getCode: function(),getCoinbase: function(callback),getCompilers: function(),getGasPrice: function(callback),getHashrate: function(callback),getMining: function(callback),getNatSpec: function(),getPendingTransactions: function(callback),getStorageAt: function(),getSyncing: function(callback),getTransaction: function(),getTransactionCount: function(),getTransactionFromBlock: function(),getTransactionReceipt: function(),getUncle: function(),getWork: function(),iban: function(iban),icapNamereg: function(),isSyncing: function(callback),namereg: function(),resend: function(),sendIBANTransaction: function(),sendRawTransaction: function(),sendTransaction: function(),sign: function(),signTransaction: function(),submitTransaction: function(),submitWork: function()},at: function(address, callback),getData: function(),new: function()
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
> myContract = MyContract.new({from:address,data:contract.code})
{abi: [{constant: false,inputs: {name: "a",type: "uint256"}}],address: undefined,transactionHash: "0xd10602e2099ab5873c762f070eb90a9fd559270484fbcebd4170d441848b9232"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这时,我们可以检查一下交易池,查看当前交易的待处理状况:

> txpool.status
{pending: 1,queued: 0
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

我们可以看到当前的交易池中有一个交易正在等待确认。然后,我们查看待确认交易的详细内容:

> eth.getBlock("pending",true).transactions
[{blockHash: "0x0299731121321b817206fb07187f94cd4537e3196e940b45e95b4e1709aadbf4",blockNumber: 294,from: "0x62b1746767522b36f6421e630fa0198151d72964",gas: 90000,gasPrice: 20000000000,hash: "0xd10602e2099ab5873c762f070eb90a9fd559270484fbcebd4170d441848b9232",input: "0x606060405260388060106000396000f3606060405260e060020a6000350463c6888fa18114601c575b6002565b3460025760076004350260408051918252519081900360200190f3",nonce: 0,to: null,transactionIndex: 0,value: 0
}]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

我们从显示出来的结果可以看出当前交易的一些内容。例如,from数据项就是我们发送交易的地址,input就是合约编译完成的字节码,这些内容均与我们之前的设定相同。而且,我们可以看到新的交易创建在第294号区块中。

与此同时,我们也可以查看一下刚才在新的终端中创建的挖矿日志。我们在日志中找到这样的一行信息:

I1102 11:37:46.573298 eth/api.go:1183] Tx(0xd10602e2099ab5873c762f070eb90a9fd559270484fbcebd4170d441848b9232) created: 0x115ced3f8b7ea92d324902e3a3a421a07540eb2b
  • 1
  • 1

这说明交易已经发送到区块链中了,正在等待矿工的确认。

耐心等待一段时间,等待矿工确认完成后,我们再次使用txpool.status命令查看交易池的状态:

> txpool.status
{pending: 0,queued: 0
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

我们发现交易池已经没有待确认的交易了。我们使用eth.getBlock(294)命令查看第294号区块的信息:

> eth.getBlock(294)
{difficulty: 131072,extraData: "0xd783010412844765746887676f312e362e32856c696e7578",gasLimit: 4712388,gasUsed: 36946,hash: "0x4da580cce8bc5ed34aa5a7bbeeb730d98cd7b425698f40433365f1463bc572ee",logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",miner: "0x62b1746767522b36f6421e630fa0198151d72964",nonce: "0x02956290420fe41f",number: 294,parentHash: "0x3fd3a8126d25dec98aaf2696c2812de2d2f4f28bae729dacd78634f046d8a1cc",receiptRoot: "0x44c28d68986fb814e431117f3759b24d5e668feeff8dacaadb7c08fd11b4f2fc",sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",size: 696,stateRoot: "0xab235f738e080d41efb4692633401917dfb9f04625d9476b6875e5d335f1b014",timestamp: 1478057886,totalDifficulty: 38670080,transactions: ["0xd10602e2099ab5873c762f070eb90a9fd559270484fbcebd4170d441848b9232"],transactionsRoot: "0xc983a661a81a1173bd0196a44e8d1092250f6c6a21acc1847cd7416de9d76f55",uncles: []
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

我们发现hash值为0xd10602e2099ab5873c762f070eb90a9fd559270484fbcebd4170d441848b9232的交易确实在第294号区块中。

与合约交互

首先我们需要使用eth.contract来定义一个合约类,定义的合约类遵从ABI定义2:

> Multiply7 = eth.contract(contract.info.abiDefinition)
{abi: [{constant: false,inputs: [{...}],name: "multiply",outputs: [{...}],payable: false,type: "function"}],eth: {accounts: ["0x62b1746767522b36f6421e630fa0198151d72964"],blockNumber: 346,coinbase: "0x62b1746767522b36f6421e630fa0198151d72964",compile: {lll: function(),serpent: function(),solidity: function()},defaultAccount: undefined,defaultBlock: "latest",gasPrice: 20000000000,hashrate: 39840,mining: true,pendingTransactions: [],syncing: false,call: function(),contract: function(abi),estimateGas: function(),filter: function(fil, callback),getAccounts: function(callback),getBalance: function(),getBlock: function(),getBlockNumber: function(callback),getBlockTransactionCount: function(),getBlockUncleCount: function(),getCode: function(),getCoinbase: function(callback),getCompilers: function(),getGasPrice: function(callback),getHashrate: function(callback),getMining: function(callback),getNatSpec: function(),getPendingTransactions: function(callback),getStorageAt: function(),getSyncing: function(callback),getTransaction: function(),getTransactionCount: function(),getTransactionFromBlock: function(),getTransactionReceipt: function(),getUncle: function(),getWork: function(),iban: function(iban),icapNamereg: function(),isSyncing: function(callback),namereg: function(),resend: function(),sendIBANTransaction: function(),sendRawTransaction: function(),sendTransaction: function(),sign: function(),signTransaction: function(),submitTransaction: function(),submitWork: function()},at: function(address, callback),getData: function(),new: function()
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69

然后得到合约实例:

> myMultiply7 = Multiply7.at(myContract.address)
{abi: [{constant: false,inputs: [{...}],name: "multiply",outputs: [{...}],payable: false,type: "function"}],address: "0x115ced3f8b7ea92d324902e3a3a421a07540eb2b",transactionHash: null,allEvents: function(),multiply: function()
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

我们可以看到,在实例中能够调用的函数有两个:allEventsmultiplymultiply显然是一开始我们定义合约的时候写的函数。我们可以使用两种方法来调用multiply函数:sendTransaction(3, {from: address})call(3)

方法一:使用sendTransaction(3, {from: address})调用:

> myMultiply7.multiply.sendTransaction(3, {from:address})
"0x1c46e9e85f5db00ba2bcbb2e8774f61cdb81620a46a19ea9cf6a532795d5950c"
  • 1
  • 2
  • 1
  • 2

我们可以发现返回的值为一个字符串,这个字符串代表的是发送的交易的hash值。使用这个方法调用合约将会使调用的结果成为全局共识的一部分3。

方法二:使用call(3)调用:

> myMultiply7.multiply.call(3)
21
  • 1
  • 2
  • 1
  • 2

我们可以发现返回值为21,这个值刚好是3*7的运算结果。使用这个方法调用合约只会在本地上运行4。

从以上两种方法的调用结果来看,如果你只想得知运算的结果,那么只需要使用方法二。而如果想要改变合约的状态,那么就使用方法一。

参考资料

  • Contracts and Transactions:以太坊客户端geth的wiki里编写智能合约的详细流程和例子。
  • Contracts:以太坊文档中有关智能合约编写、编译、部署和交互等的例子。
  • 明说(04):如何开发编译部署调用智能合约?:这个是汪晓明演示在以太坊geth命令行上编译部署智能合约的视频。

  1. 以太坊智能合约编程之菜鸟教程 ↩
  2. Interacting with contracts ↩
  3. Interacting with contracts ↩
  4. Interacting with contracts ↩


这篇关于如何开发编译部署调用智能合约的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1116196

相关文章

闲置电脑也能活出第二春?鲁大师AiNAS让你动动手指就能轻松部署

对于大多数人而言,在这个“数据爆炸”的时代或多或少都遇到过存储告急的情况,这使得“存储焦虑”不再是个别现象,而将会是随着软件的不断臃肿而越来越普遍的情况。从不少手机厂商都开始将存储上限提升至1TB可以见得,我们似乎正处在互联网信息飞速增长的阶段,对于存储的需求也将会不断扩大。对于苹果用户而言,这一问题愈发严峻,毕竟512GB和1TB版本的iPhone可不是人人都消费得起的,因此成熟的外置存储方案开

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

阿里开源语音识别SenseVoiceWindows环境部署

SenseVoice介绍 SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。富文本识别:具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。高效推

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta