区块链研究实验室|使用Geth和Web3.js部署您的第一个私有以太坊智能合约

以太坊智能合约基本上是使用区块链中的以太坊虚拟机(EVM)运行的程序。创建以太坊地址时,会分配一个以太坊地址,并且每个交互使用一个事务。合约/应用程序将在区块链中具有状态,并且与之交互时状态将发生变化。重要的是,一旦合约被发送到区块链,它就永远不会改变(它是不可变的)。您可以通过更改再次上载同一个合约,但前一个合约将保持不变,并且它们将在彼此不知情的情况下并行运行。在智能合约进入主网之前,质量保证和测试至关重要。
 如何创建以太坊智能合约
Solidity是以太坊智能合约的主要编译器之一。你可以像这样在Ubuntu中安装它。
apt-get install solc
在本教程中,我将使用Remix的示例合约之一(Owner.sol)。在较高级别上,此合约会将合约的所有者设置为部署它的人。有一个“ getter”可以检索当前所有者是谁,还有一个“ setter”可以允许当前所有者设置另一个所有者。非常简单,但可以达到目的。

pragma solidity >=0.4.22 <0.7.0;
contract Owner {
address private owner;

event OwnerSet(address indexed oldOwner, address indexed newOwner);

modifier isOwner() {
require(msg.sender == owner, “Caller is not owner”);
_;
}

constructor() public {
owner = msg.sender;
emit OwnerSet(address(0), owner);
}

function changeOwner(address newOwner) public isOwner {
emit OwnerSet(owner, newOwner);
owner = newOwner;
}

function getOwner() external view returns (address) {
return owner;
}

}


快速Remix介绍
使用一些示例合约重新Remix加载。我们正在使用的一个在上面称为Owner.sol。我删除了本教程中包含的注释。我将解释如何与之互动。
我们将从文件浏览器开始在左侧菜单中进行操作。您只需在这里选择Owner.sol。

区块链研究实验室|使用Geth和Web3.js部署您的第一个私有以太坊智能合约

然后,您想将一个菜单选项下移到Solidity Compiler。只需单击蓝色的Compile Owner.sol按钮。

区块链研究实验室|使用Geth和Web3.js部署您的第一个私有以太坊智能合约

现在将鼠标移到Deploy&runtransactions菜单。只需单击橙色Deploy按钮。

区块链研究实验室|使用Geth和Web3.js部署您的第一个私有以太坊智能合约

请注意,Remix提供了几个可使用的资金帐户。每个账户有100以太币资金。)我将使用从0x5B3开始的第一个帐户来部署合约。

区块链研究实验室|使用Geth和Web3.js部署您的第一个私有以太坊智能合约

单击橙色Deploy后,您将看到部署在deployed Contracts下的合约。你也会注意到它有自己的以太坊地址。

区块链研究实验室|使用Geth和Web3.js部署您的第一个私有以太坊智能合约

我展开了合约,您可以从那里看到合约中的两种方法。带输入字段的“ getter” getOwner和“ setter” changeOwner。我单击getOwner按钮并看到部署的地址:0x5B38Da6a701c568545dCfcB03FcB875f56beddC4

区块链研究实验室|使用Geth和Web3.js部署您的第一个私有以太坊智能合约

我想改变合约的所有者。在顶部,我移动到第二个帐户,以便能够复制它,然后移回第一个帐户,即所有者。

区块链研究实验室|使用Geth和Web3.js部署您的第一个私有以太坊智能合约

现在从0x5B3帐户运行changeOwner方法,将新帐户设置为0xAb8帐户。

区块链研究实验室|使用Geth和Web3.js部署您的第一个私有以太坊智能合约

现在我再次运行getOwner方法,并正确地将所有者更改为0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2

区块链研究实验室|使用Geth和Web3.js部署您的第一个私有以太坊智能合约

因此这只是Remix的1分钟介绍。我建议您自己尝试一下。尝试将changeOwner设置为无效地址,或者尝试使changeOwner不作为所有者,然后看看会发生什么。
在Ubuntu中使用solc编译Owner.sol
现在您可能会遇到的一个问题是,Remix中的默认Owner.sol合约使用的编译器≥0.4.22并且<0.7.0。我的Ubuntu系统上安装的solc编译器是0.7.1

solc –version
solcthe solidity compiler commandline interface
Version: 0.7.1+commit.f4a555be.Linux.g++


对于0.7.1中的合约,语法略有不同。请在下面使用我更改后的Owner.sol。您还可以将Remix中的编译器版本更改为0.7.1,并也使用此合约。

pragma solidity >=0.4.22 <0.8.0;
contract Owner {
address public owner;
event OwnerSet(address indexed oldOwner, address indexed newOwner);
modifier isOwner() {
require(msg.sender == owner, “Caller is not owner”);
_;
}

constructor() {
emit OwnerSet(address(0), owner);
owner = msg.sender;
}

function changeOwner(address newOwner) public isOwner {
emit OwnerSet(owner, newOwner);
owner = newOwner;
}

function getOwner() external view returns (address) {
return owner;
}

}


我希望您按照以下方式编译Owner.sol合约。

~/dapp# solc –combined-json abi,bin Owner.sol > Owner.json
Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing “SPDX-License-Identifier: <SPDX-License>” to each source file. Use “SPDX-License-Identifier: UNLICENSED” for non-opensource code. Please see https://spdx.org for more information.
–> Owner.sol
~/dapp# cat Owner.json
{“contracts”:{“Owner.sol:Owner”:{“abi”:“[{“inputs”:[],”stateMutability”:”nonpayable”,”type”:”constructor”},{“anonymous”:false,”inputs”:[{“indexed”:true,”internalType”:”address”,”name”:”oldOwner”,”type”:”address”},{“indexed”:true,”internalType”:”address”,”name”:”newOwner”,”type”:”address”}],”name”:”OwnerSet”,”type”:”event”},{“inputs”:[{“internalType”:”address”,”name”:”newOwner”,”type”:”address”}],”name”:”changeOwner”,”outputs”:[],”stateMutability”:”nonpayable”,”type”:”function”},{“inputs”:[],”name”:”getOwner”,”outputs”:[{“internalType”:”address”,”name”:””,”type”:”address”}],”stateMutability”:”view”,”type”:”function”},{“inputs”:[],”name”:”owner”,”outputs”:[{“internalType”:”address”,”name”:””,”type”:”address”}],”stateMutability”:”view”,”type”:”function”}]”,“bin”:“608060405234801561001057600080fd5b5060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a3336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102f3806100db6000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063893d20e8146100465780638da5cb5b1461007a578063a6f9dae1146100ae575b600080fd5b61004e6100f2565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61008261011b565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100f0600480360360208110156100c457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061013f565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610200576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f43616c6c6572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505056fea2646970667358221220ba9a494e8dd99908b8c962ed752cac0bf679199c5c8dad87d13f5f9d9088c39c64736f6c63430007010033”}},“version”:“0.7.1+commit.f4a555be.Linux.g++”}


为了方便地读取这个JSON输出,我建议安装“jq”。

apt-get install jq -y
~/dapp# cat Owner.json | jq .
{
“contracts”: {
“Owner.sol:Owner”: {
“abi”“[{“inputs“:[],”stateMutability“:”nonpayable“,”type“:”constructor“},{“anonymous“:false,”inputs“:[{“indexed“:true,”internalType“:”address“,”name“:”oldOwner“,”type“:”address“},{“indexed“:true,”internalType“:”address“,”name“:”newOwner“,”type“:”address“}],”name“:”OwnerSet“,”type“:”event“},{“inputs“:[{“internalType“:”address“,”name“:”newOwner“,”type“:”address“}],”name“:”changeOwner“,”outputs“:[],”stateMutability“:”nonpayable“,”type“:”function“},{“inputs“:[],”name“:”getOwner“,”outputs“:[{“internalType“:”address“,”name“:”“,”type“:”address“}],”stateMutability“:”view“,”type“:”function“},{“inputs“:[],”name“:”owner“,”outputs“:[{“internalType“:”address“,”name“:”“,”type“:”address“}],”stateMutability“:”view“,”type“:”function“}]”,
“bin”“608060405234801561001057600080fd5b5060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a3336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102f3806100db6000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063893d20e8146100465780638da5cb5b1461007a578063a6f9dae1146100ae575b600080fd5b61004e6100f2565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61008261011b565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100f0600480360360208110156100c457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061013f565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610200576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f43616c6c6572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505056fea2646970667358221220ba9a494e8dd99908b8c962ed752cac0bf679199c5c8dad87d13f5f9d9088c39c64736f6c63430007010033”
}
},
“version”“0.7.1+commit.f4a555be.Linux.g++”
}


现在,对于下一部分,您将需要一个以太坊Geth节点来安装智能合约。
我现在要连接到我的工作节点…

~/geth# ./2020-attach.sh
Welcome to the Geth JavaScript console!
instance: Geth/v1.9.21-stable-0287d548/linux-amd64/go1.15
coinbase: 0x6be8a6cad397746efc5033e27e82477e27c9afec
at block: 3981 (Tue Sep 22 2020 22:44:03 GMT+0100 (BST))
datadir: /root/.ethereum/net2020
modules: admin:1.0 debug:1.0 eth:1.0 ethash:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
> eth.blockNumber
3983


要部署合约,请执行以下操作。

> var ownerContractCompiled = {“contracts”:{“Owner.sol:Owner”:{“abi”:“[{“inputs“:[],”stateMutability“:”nonpayable“,”type“:”constructor“},{“anonymous“:false,”inputs“:[{“indexed“:true,”internalType“:”address“,”name“:”oldOwner“,”type“:”address“},{“indexed“:true,”internalType“:”address“,”name“:”newOwner“,”type“:”address“}],”name“:”OwnerSet“,”type“:”event“},{“inputs“:[{“internalType“:”address“,”name“:”newOwner“,”type“:”address“}],”name“:”changeOwner“,”outputs“:[],”stateMutability“:”nonpayable“,”type“:”function“},{“inputs“:[],”name“:”getOwner“,”outputs“:[{“internalType“:”address“,”name“:”“,”type“:”address“}],”stateMutability“:”view“,”type“:”function“},{“inputs“:[],”name“:”owner“,”outputs“:[{“internalType“:”address“,”name“:”“,”type“:”address“}],”stateMutability“:”view“,”type“:”function“}]”,“bin”:“608060405234801561001057600080fd5b5060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a3336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102f3806100db6000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063893d20e8146100465780638da5cb5b1461007a578063a6f9dae1146100ae575b600080fd5b61004e6100f2565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61008261011b565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100f0600480360360208110156100c457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061013f565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610200576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f43616c6c6572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505056fea2646970667358221220ba9a494e8dd99908b8c962ed752cac0bf679199c5c8dad87d13f5f9d9088c39c64736f6c63430007010033”}},“version”:“0.7.1+commit.f4a555be.Linux.g++”}

> typeof ownerContractCompiled.contracts[“Owner.sol:Owner”].abi
“string”

> var ownerContract = eth.contract(JSON.parse(ownerContractCompiled.contracts[“Owner.sol:Owner”].abi))

> eth.mining
true    <–   make sure you are mining or miner.start(1)

> eth.coinbase
“0x6be8a6cad397746efc5033e27e82477e27c9afec”   <–   you will have your own address
> var deployTransactionObject = { from: eth.coinbase, data: “0x” + ownerContractCompiled.contracts[“Owner.sol:Owner”].bin, gas: 1000000 }

> personal.unlockAccount(eth.coinbase)
Unlock account 0x6be8a6cad397746efc5033e27e82477e27c9afec
Passphrase:
true

> var ownerContractInstance = ownerContract.new(deployTransactionObject)


请注意,合约已部署,我们的两种方法都在这里。

> ownerContractInstance
{
abi: [{
inputs: [],
stateMutability: “nonpayable”,
type“constructor”
}, {
anonymous: false,
inputs: [{…}, {…}],
name: “OwnerSet”,
type“event”
}, {
inputs: [{…}],
name: “changeOwner”,
outputs: [],
stateMutability: “nonpayable”,
type“function”
}, {
inputs: [],
name: “getOwner”,
outputs: [{…}],
stateMutability: “view”,
type“function”
}, {
inputs: [],
name: “owner”,
outputs: [{…}],
stateMutability: “view”,
type“function”
}],
address: “0xb2c455aa1ac281180b4faca7b8896092169ccd55”,
transactionHash: “0x38391d46e37e79b7764df2ba31cc32ff45457e2a33a5826b8af15fce9a0e5cf2”,
OwnerSet: function(),
allEvents: function(),
changeOwner: function(),
getOwner: function(),
owner: function()
}


区块链中有交易收据。

> eth.getTransactionReceipt(ownerContractInstance.transactionHash);
{
blockHash: “0x94a0e3c9c9d562c34061147e1ef21f9260178693df124ff81cba37f1818fa8a7”,
blockNumber: 4061,
contractAddress: “0xb2c455aa1ac281180b4faca7b8896092169ccd55”,
cumulativeGasUsed: 287352,
from“0x6be8a6cad397746efc5033e27e82477e27c9afec”,
gasUsed: 287352,
logs: [{
address: “0xb2c455aa1ac281180b4faca7b8896092169ccd55”,
blockHash: “0x94a0e3c9c9d562c34061147e1ef21f9260178693df124ff81cba37f1818fa8a7”,
blockNumber: 4061,
data: “0x”,
logIndex: 0,
removed: false,
topics: [“0x342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a735”“0x0000000000000000000000000000000000000000000000000000000000000000”“0x0000000000000000000000000000000000000000000000000000000000000000”],
transactionHash: “0x38391d46e37e79b7764df2ba31cc32ff45457e2a33a5826b8af15fce9a0e5cf2”,
transactionIndex: 0
}],
logsBloom: “0x00000000000000000000000000000000000000000400000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000002000000000000000800000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000004000000000000000000000000000000000”,
root: “0xb37e7b1b1e55b358585677fe3cad149e859540f8981c0d9c57d8adc5af536c20”,
to: null,
transactionHash: “0x38391d46e37e79b7764df2ba31cc32ff45457e2a33a5826b8af15fce9a0e5cf2”,
transactionIndex: 0
}


合约已部署并正常工作。您将不希望一遍又一遍地部署合约以与之集成。这就是您与现有合约进行交互的方式。

var ownerContractAddress = eth.getTransactionReceipt(ownerContractInstance.transactionHash).contractAddress
> ownerContractAddress
“0xb2c455aa1ac281180b4faca7b8896092169ccd55”


现在你可以在这里提供合约地址。我们正在使用一个变量,但您也可以提供实际地址。请注意以前使用的“.at”而不是“.new”。这意味着您希望检索现有合约,而不是创建新合约。
var ownerContractInstance = ownerContract.at(ownerContractAddress)
任何人都可以检索合约二进制文件。

var deployedBinary = eth.getCode(ownerContractAddress)
> (“0x” + ownerContractCompiled.contracts[“Owner.sol:Owner”].bin.substring(2 + ownerContractCompiled.contracts[“Owner.sol:Owner”].bin.length – deployedBinary.length)).localeCompare(deployedBinary);
0   <–   this means the contract is the same as the contract deployed


这就是我们访问合约方法的方式。

ownerContractInstance.getOwner()
ownerContractInstance.setOwner(eth.accounts[1], { from: eth.accounts[0] })


使用React.js或Node.js库(Web3.js)与您的智能合约进行交互。
因此,让我们开始创建一个非常基本的React.js应用程序。我将使用“ create-react-app”工具创建默认应用程序。
create-react-app mediumtutorialCreating a new React app in /Repos/React/mediumtutorial.*** INSTALL PROCESS ***Success! Created mediumtutorial at /Repos/React/mediumtutorialInside that directory, you can run several commands:yarn start
Starts the development server.yarn build
Bundles the app into static files for production.yarn test
Starts the test runner.yarn eject
Removes this tool and copies build dependencies, configuration files and scripts into the app directory. If you do this, you can’t go back!We suggest that you begin by typing:cd mediumtutorial
yarn startHappy hacking!
按照说明,如果您将目录更改为“ mediumtutorial”和“ yarn start”,它将打开您的默认浏览器,您应该会看到。

% cd mediumtutorial
mediumtutorial % yarn add web3


该库可用于Node.js和React.js。您可以像这样与Geth节点RPC进行交互。
let web3 = new Web3('ws://localhost:8546');
———————————————
原文作者:Jack
译者:链三丰
译文出处:http://bitoken.world

该内容来自于互联网公开内容,非区块链原创内容,如若转载,请注明出处:https://htzkw.com/archives/25633

联系我们

aliyinhang@gmail.com