zoukankan      html  css  js  c++  java
  • 以太坊入门三 Web3j.py 与节点交互

    以太坊 geth 客户端提供自带的交互接口即 web3j ,来控制节点的信息操作。到实际开发中,不论是采用 Java 版的 web3j,还是 Python 版的 web3j,其实关系就不是很大了。

    web3 js :https://web3js.readthedocs.io/en/v2.0.0-alpha/

    java-web3j:https://docs.web3j.io/getting_started/

    python-web3j:https://web3py.readthedocs.io/en/latest/index.html

    Tips:<对应的可自行搜索中文相关文档,这里就不一一列出,英语文档想对详细些。中文看过后,开发过程中遇到问题,查看英语文档可了解更多相关信息。>

    下面主要列举些 web3.py 里面的常用语句。这里我是写了一个关于节点的类,常用的语句单独写为一个方法。

    1. 连接节点

    def start_node(db='D:/eth-test/db/', port='30303', rpcport='8545'):
        cmdOrder = 'geth --datadir ' + db + ' --rpc --rpcapi "eth,net,web3,personal,admin,txpool,debug,miner"' 
                  ' --port ' + port + ' --rpcport ' + rpcport + ' --nodiscover --rpccorsdomain "*" --allow-insecure-unlock' 
                  ' --ipcdisable'
        os.system(cmdOrder)

    2. 生成 web3 实例

    def __init__(self, ip, rpcport):
        # 连接本地以太坊节点
        self.w3 = Web3(Web3.HTTPProvider('http://' + ip + ':' + rpcport, request_kwargs={'timeout': 60}))

    3. 返回当前的账户列表

    # 返回当前所有账户
    def getAddrs(self):
        return self.w3.eth.accounts

    4. 返回指定账户余额

    # 返回指定地址的余额
    def getBalance(self, addr):
        balance = self.w3.fromWei(self.w3.eth.getBalance(addr), 'ether')
        return balance

    5. 返回当前节点的 enode

    此作用用来添加节点

    # 返回当前节点的 enode 信息
    def getEnode(self):
        return self.w3.geth.admin.node_info()['enode']

    6. 返回节点个数

    # 返回当前节点数
    def peers(self):
        return self.w3.geth.admin.peers()

    7. 添加节点

    # 当前节点添加节点
    def addPeer(self, enode):
        return self.w3.geth.admin.add_peer(enode)

    8. 挖矿、停止挖矿

    # 开始挖矿
    def minerStart(self):
        self.w3.geth.miner.start(1)
    # 结束挖矿
    def minerStop(self):
        self.w3.geth.miner.stop()

    9. 部署智能合约

    部署合约以及对智能合约的调用(改变合约状态时),都需要设置节点默认账户,并解锁该账户。此外还需要 引入 solc.exe 文件(放在同级目录)

    from web3 import Web3
    from solc import compile_standard

    personal.unlockAccount(ins.getAddrs()[2], 'sophia', 300) # 参数分别为 账户地址、私匙、解锁时间(秒)
    def contractCompile(ins):
        compiledSol = compile_standard({
            'language': 'Solidity',
            'sources': {'UserInfo.sol': {
                            'content': '''
                                pragma solidity ^0.6.0;
    
                                contract UserInfo {
                                     string name;
                                     uint age;
                                     bool gender = true;
                                     constructor() public{
                                         name = 'junweiJun';
                                         age = 18;
                                         gender = true;
                                     }
                                     function setAttr(string memory _name, uint _age, bool _gender) public{
                                         name = _name;
                                         age = _age;
                                         gender = _gender;
                                     }
                
                                     function getAttr() public view returns (string memory, uint, bool) {
                                         return (name, age, gender);
                                     }
                                 }
                            
                            '''
                        }
            },
            "settings":
                {
                    "outputSelection": {
                        "*": {
                            "*": [
                                "metadata", "evm.bytecode"
                                , "evm.bytecode.sourceMap"
                            ]
                        }
                    }
                }
        })
        # 设置默认账户
        # ins.w3.eth.coinbase = ins.getAddrs()[1]
        # 获取 bytecode
        bytecode = compiledSol['contracts']['UserInfo.sol']['UserInfo']['evm']['bytecode']['object']
        # 获取 abi
        abi = json.loads(compiledSol['contracts']['UserInfo.sol']['UserInfo']['metadata'])['output']['abi']
        print("abi:", abi)
        # 生成合约
        UserInfo = ins.w3.eth.contract(abi=abi, bytecode=bytecode)
        # # 部署合约
        print(ins.w3.eth.defaultAccount)
        ins.w3.eth.defaultAccount = ins.getAddrs()[1]
        print(ins.w3.eth.defaultAccount)
        # 解锁账户
        ins.w3.geth.personal.unlockAccount(ins.getAddrs()[1], 'xsmile', 300)
        # 设置 defaultAccount 并解锁账户,否则会出现 ValueError: {'code': -32000, 'message': 'unknown account'}
        txHash = UserInfo.constructor().transact()
        try:
            ins.minerStart()
            # # 等待合约被挖掘
            txReceipt = ins.w3.eth.waitForTransactionReceipt(txHash)
            print('txReceipt:', txReceipt)
            # ins.minerStop()
            userInfo = ins.w3.eth.contract(address=txReceipt.contractAddress, abi=abi)
            user = userInfo.functions.getAttr().call()
            print('init: ', user)
        except Exception:
            pass
        finally:
            ins.minerStop()
        pass
    合约部署

    10. 调用智能合约

    def updateContract(ins):
        # 解锁账户
        ins.w3.eth.defaultAccount = ins.getAddrs()[2]
        ins.w3.geth.personal.unlockAccount(ins.getAddrs()[2], 'sophia', 300)
        abi = [{'inputs': [], 'stateMutability': 'nonpayable', 'type': 'constructor'}, {'inputs': [], 'name': 'getAttr', 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}, {'internalType': 'uint256', 'name': '', 'type': 'uint256'}, {'internalType': 'bool', 'name': '', 'type': 'bool'}], 'stateMutability': 'view', 'type': 'function'}, {'inputs': [{'internalType': 'string', 'name': '_name', 'type': 'string'}, {'internalType': 'uint256', 'name': '_age', 'type': 'uint256'}, {'internalType': 'bool', 'name': '_gender', 'type': 'bool'}], 'name': 'setAttr', 'outputs': [], 'stateMutability': 'nonpayable', 'type': 'function'}]
        contractAddress = '0x9DBF7256f54Eefe99Aa1f9436921F0F0e13147Ff'
        userInfo = ins.w3.eth.contract(address=contractAddress, abi=abi)
        user = userInfo.functions.getAttr().call()
        print(user)
        try:
            ins.minerStart()
            uName = 'jerry'
            uAge = 20
            uGender = True
            txHash = userInfo.functions.setAttr(uName, uAge, uGender).transact()
            print("txHash:", txHash)
            txReceipt = ins.w3.eth.waitForTransactionReceipt(txHash)
            print("******************************************")
            print('txReceipt:', txReceipt)
            user1 = userInfo.functions.getAttr().call()
            print('after: ', user1)
        except Exception:
            print(Exception)
        finally:
            ins.minerStop()
    调用合约

    11. 查询区块中存储的信息

    这里指调用智能合约,并改变合约状态后,存储到区块中合约内的信息。

    打印信息时,如区块地址为类型为:Hexbytes 类型的,我们需要的是字符串类型的一串16进制字符。

    参考:https://web3py.readthedocs.io/en/latest/contracts.html#web3.contract.ContractFunction.call

    block.hash.hex()  # 转换输出字符串地址
    def searchContract(ins):
        abi = [{'inputs': [], 'name': 'getAttr', 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}, {'internalType': 'string', 'name': '', 'type': 'string'}, {'internalType': 'string', 'name': '', 'type': 'string'}], 'stateMutability': 'view', 'type': 'function'}, {'inputs': [{'internalType': 'string', 'name': '_number', 'type': 'string'}, {'internalType': 'string', 'name': '_batch', 'type': 'string'}, {'internalType': 'string', 'name': '_createTime', 'type': 'string'}], 'name': 'setAttr', 'outputs': [], 'stateMutability': 'nonpayable', 'type': 'function'}]
        contractAddress = '0xb27a8caeAeE69B17d377a889246DA5112c9e14b8'
        userInfo = ins.w3.eth.contract(address=contractAddress, abi=abi)
        print("****************区块 Hash 值查询******************")
        blockHash = '0x627b561fe9d60ec6e6b392a4361340ed009df2c37497d4a343e172c96da1552d'
        info = userInfo.functions.getAttr().call(block_identifier=blockHash)
        print(info)
    查询合约内容

    原创不易,尊重版权。转载请注明出处:http://www.cnblogs.com/xsmile/

  • 相关阅读:
    Javascript操纵Cookie--转
    java使用jsp servlet来防止csrf 攻击的实现方法
    Creating a CSRF protection with Spring 3.x--reference
    Preventing CSRF in Java web apps---reference
    Linux服务器集群系统(四)--转
    Linux服务器集群系统(三)--转
    UVA 10529 Dumb Bones 可能性dp 需求预期
    android 渐变drawable
    定义你自己ViewGroup
    Android系统关机或几种方式重启
  • 原文地址:https://www.cnblogs.com/xsmile/p/12591286.html
Copyright © 2011-2022 走看看