美文网首页
ETH00:区块链的智能合约部署与执行

ETH00:区块链的智能合约部署与执行

作者: 杨强AT南京 | 来源:发表于2020-03-25 09:35 被阅读0次

  要用区块链,所以从新梳理了一下代码,把版本问题确认下,顺便开启区块链的技术主题;
  下面说明下环境与代码。主要使用的Node.js编程环境与geth私有以太坊节点。本文不依赖框架,把基础技术说明白,再来说框架。


环境

  • 主要包含:
    1. node: 12.16.1
    2. geth: 1.8.3
    3. solc: 0.6.4 (实际代码中我们使用的是0.5.0)
    4. web3: 1.2.6

node.js

C:\01works\08eth\ethnodes\codes>node --version
v12.16.1

geth

C:\01works\08eth\ethnodes\codes>geth version
Geth
Version: 1.8.3-stable
Git Commit: 329ac18ef617d0238f71637bffe78f028b0f13f7
Architecture: amd64
Protocol Versions: [63 62]
Network Id: 1
Go Version: go1.10
Operating System: windows
GOPATH=
GOROOT=C:\go

solc

C:\01works\08eth\ethnodes\codes>npm view solc

solc@0.6.4 | MIT | deps: 8 | versions: 70
Solidity compiler
https://github.com/ethereum/solc-js#readme

bin: solcjs

dist
.tarball: https://registry.npm.taobao.org/solc/download/solc-0.6.4.tgz
.shasum: 4b0f11fccd6f5ef9802c6bb1c007abb16881c2ca

dependencies:
command-exists: ^1.2.8      fs-extra: ^0.30.0           memorystream: ^0.3.1        semver: ^5.5.0
commander: 3.0.2            js-sha3: 0.8.0              require-from-string: ^2.0.0 tmp: 0.0.33

maintainers:
- chriseth <c@ethdev.com>
- d11e9 <d11e9@turkd.net>

dist-tags:
latest: 0.6.4      series0.4: 0.4.26  series0.5: 0.5.17

published 2 weeks ago by chriseth <chris@ethereum.org>

web3

C:\01works\08eth\ethnodes\codes>npm view web3

web3@1.2.6 | LGPL-3.0 | deps: 8 | versions: 117
Ethereum JavaScript API
https://github.com/ethereum/web3.js#readme

dist
.tarball: https://registry.npm.taobao.org/web3/download/web3-1.2.6.tgz
.shasum: c497dcb14cdd8d6d9fb6b445b3b68ff83f8ccf68

dependencies:
@types/node: ^12.6.1     web3-core: 1.2.6         web3-eth: 1.2.6          web3-shh: 1.2.6
web3-bzz: 1.2.6          web3-eth-personal: 1.2.6 web3-net: 1.2.6          web3-utils: 1.2.6

maintainers:
- frozeman <fabian@frozeman.de>
- nivida <samuel@ethereum.org>

dist-tags:
latest: 1.2.6        next: 2.0.0-alpha.1

published a month ago by nivida <samuel@ethereum.org>

代码实现

编译智能合约

  • 使用编译后的两个结果:
    1. bin
    2. abi
var path =  require('path');
var fs = require('fs');
var solc =  require('solc');

// 获取智能合约的绝对路径
var contract_path = path.resolve('contract1_base.sol');
// console.log("合同路径: " + contract_path);
 
// 读取合约内容
var contract_source = fs.readFileSync(contract_path, 'utf-8');
// console.log(contract_source)
// 编译
var contract_json = JSON.stringify({
    language: 'Solidity',
    sources: {
        'contract1_base.sol': {  // 指明编译的文件名
            content: contract_source, // solidity 源代码
        },
    },
    settings: { // 自定义编译输出的格式。以下选择输出全部结果。
        outputSelection: {
            '*': {
                '*': [ '*' ]
            }
        }
    },
});

var contract_compiled = solc.compile(contract_json);
// console.log(contract_compiled);
// 注意: solc的版本。
var contract_obj = JSON.parse(contract_compiled);
var ou = contract_obj.contracts['contract1_base.sol']['Contrac_Base'];

// ABI
console.log(ou.abi);
// BIN
console.log(ou.evm.bytecode.object);

部署智能合约

  • 记录一下合同地址,下面查询使用
const path =  require('path');
const fs = require('fs');
const solc =  require('solc');

const Web3 = require("web3");
const web3 = new Web3();
web3.setProvider(new Web3.providers.HttpProvider("http://localhost:9999"));


// 获取智能合约的绝对路径
var contract_path = path.resolve('contract1_base.sol');
// console.log("合同路径: " + contract_path);
 
// 读取合约内容
var contract_source = fs.readFileSync(contract_path, 'utf-8');
// console.log(contract_source)
// 编译
var contract_json = JSON.stringify({
    language: 'Solidity',
    sources: {
        'contract1_base.sol': {  // 指明编译的文件名
            content: contract_source, // solidity 源代码
        },
    },
    settings: { // 自定义编译输出的格式。以下选择输出全部结果。
        outputSelection: {
            '*': {
                '*': [ '*' ]
            }
        }
    },
});

var contract_compiled = solc.compile(contract_json);
// console.log(contract_compiled);
// 注意: solc的版本。
var contract_obj = JSON.parse(contract_compiled);
var ou = contract_obj.contracts['contract1_base.sol']['Contrac_Base'];

var abi = ou.abi;
var bytecode = ou.evm.bytecode.object;

// 部署合约前的准备
web3.eth.getAccounts().then(function(accouts_){
    accounts = accouts_;
    new web3.eth.Contract(abi).deploy(
        {
            data: '0x' + bytecode, // 需要注意 字节码需要添加 '0x' 不然会有各种错误   
            arguments: []          // 此处是参数列表

        }
    ).send(
        {
            from: accounts[0],
            gas: '4712388',
            gasPrice: '1000000'
        }
    )
    .on(
        'transactionHash', 
        function (hash) {
            console.log("交易Hash:" + hash)
        }
    )
    .on(
        'receipt', 
        function (receipt) {
            console.log("交易收据:" , receipt);
        }
    )
    // .on(   // 不注释会抑制调用
    //     'confirmation', 
    //     function (confirmationNumber, receipt) {
    //         console.log( "交易确认:" + confirmationNumber);
    //     }
    // )
    .on(
        'error', 
        function(error){
            console.log("错误:" + error);
        } 
    )
    .then(
        function(newContractInstance){  // 部署成功,返回一个新的合同实例,包含合同的部署地址
            console.log("合同地址:" + newContractInstance.options.address) 
        }
    )
});

查询智能合约

  • 使用call,不修改区块数据,所以不需要发起一个交易执行。
const path =  require('path');
const fs = require('fs');
const solc =  require('solc');

const Web3 = require("web3");
const web3 = new Web3();
web3.setProvider(new Web3.providers.HttpProvider("http://localhost:9999"));


// 获取智能合约的绝对路径
var contract_path = path.resolve('contract1_base.sol');
// console.log("合同路径: " + contract_path);
 
// 读取合约内容
var contract_source = fs.readFileSync(contract_path, 'utf-8');
// console.log(contract_source)
// 编译
var contract_json = JSON.stringify({
    language: 'Solidity',
    sources: {
        'contract1_base.sol': {  // 指明编译的文件名
            content: contract_source, // solidity 源代码
        },
    },
    settings: { // 自定义编译输出的格式。以下选择输出全部结果。
        outputSelection: {
            '*': {
                '*': [ '*' ]
            }
        }
    },
});

var contract_compiled = solc.compile(contract_json);
// console.log(contract_compiled);
// 注意: solc的版本。
var contract_obj = JSON.parse(contract_compiled);
var ou = contract_obj.contracts['contract1_base.sol']['Contrac_Base'];

var abi = ou.abi;
var bytecode = ou.evm.bytecode.object;

// 部署合约前的准备(这个地址来自部署合约程序的输出,也可以使用api获取。
contract_addr = '0x44823446fb1daF884Bf4C3a92F86Ece06F87326D';
web3.eth.getAccounts().then(function(accouts_){
    accounts = accouts_;
    new web3.eth.Contract(abi, contract_addr)
    .methods
    .getAge()
    .call(
        {
            from: accounts[0]
        }
    )
    .then(
        function(result){
            console.log(result);
        }
    );
});

执行智能合约交易

  • 需要修该数据,就必须发起一个交易。
const path =  require('path');
const fs = require('fs');
const solc =  require('solc');

const Web3 = require("web3");
const web3 = new Web3();
web3.setProvider(new Web3.providers.HttpProvider("http://localhost:9999"));


// 获取智能合约的绝对路径
var contract_path = path.resolve('contract1_base.sol');
// console.log("合同路径: " + contract_path);
 
// 读取合约内容
var contract_source = fs.readFileSync(contract_path, 'utf-8');
// console.log(contract_source)
// 编译
var contract_json = JSON.stringify({
    language: 'Solidity',
    sources: {
        'contract1_base.sol': {  // 指明编译的文件名
            content: contract_source, // solidity 源代码
        },
    },
    settings: { // 自定义编译输出的格式。以下选择输出全部结果。
        outputSelection: {
            '*': {
                '*': [ '*' ]
            }
        }
    },
});

var contract_compiled = solc.compile(contract_json);
// console.log(contract_compiled);
// 注意: solc的版本。
var contract_obj = JSON.parse(contract_compiled);
var ou = contract_obj.contracts['contract1_base.sol']['Contrac_Base'];

var abi = ou.abi;
var bytecode = ou.evm.bytecode.object;

// 部署合约前的准备
contract_addr = '0x44823446fb1daF884Bf4C3a92F86Ece06F87326D';
web3.eth.getAccounts().then(function(accouts_){
    accounts = accouts_;
    new web3.eth.Contract(abi, contract_addr)
    .methods
    .setAge(128)
    .send(
        {
            from: accounts[0],
            gas: '4712388',
            gasPrice: '1000000'
        }
    )
    .on(
        'transactionHash', 
        function (hash) {
            console.log("交易Hash:" + hash);
        }
    )
    .on(
        'receipt', 
        function (receipt) {
            console.log("交易收据:" , receipt);
        }
    )
    .on(
        'error', 
        function(error){
            console.log("错误:" + error);
        } 
    )
    .then(
        function(contract_instance){  // 部署成功,返回一个新的合同实例,包含合同的部署地址
            // 只有调用deploy函数后,才返回合同实例。合同交易是不会返回的。
            console.log("合同地址:" + contract_instance) 
            var keys = Object.getOwnPropertyNames(contract_instance);
            console.log(keys);
            for(var k in  contract_instance){
                console.log(k + ":" + contract_instance[k]);
            }
            new web3.eth.Contract(abi, contract_addr)
            .methods.getAge()
            .call(
                {
                    from: accounts[0]
                }
            )
            .then(
                function(result){
                    console.log(result);
                }
            )
        }
    )
});

  • 说明:
    • 后面几个代码中的合约地址,在部署的时候得到的。可以使用代码或者geth控制终端得到。

相关文章

网友评论

      本文标题:ETH00:区块链的智能合约部署与执行

      本文链接:https://www.haomeiwen.com/subject/wrttuhtx.html