欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Windows下使用python-web3.py进行以太坊Dapp开发笔记--第1篇

程序员文章站 2022-07-07 13:12:30
...

1.环境准备

使用的环境包括:

  1. geth
  2. python3.7
  3. web3.py
  4. solc

geth的安装及简单实用

  1. 安装
    地址:https://geth.ethereum.org/downloads/
    找到对应的操作系统安装最新的版本就好(一般这里如果安装最新的,下面的web3.py也需要最新版,不然可能会出现各种错误!!!
    我的版本是:
    Windows下使用python-web3.py进行以太坊Dapp开发笔记--第1篇
  2. 使用(这里仅介绍创建私链及geth命令行的简单使用)
    A.创建私链
    a.创建一个文件夹btc,用以存放以太坊私链数据:
    b.创建json文件genesis.json,将文件内容改为下面所示并保存:
{

"config":{
"chainId":9,
"homesteadBlock":0,
"eip155Block":0,
"eip158Block":0
},

"nonce":"0x0000000000000042",
"timestamp":"0x0",
"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData":"0x00000000",
"gasLimit":"0x80000000",
"difficulty":"0x1",
"mixhash":"0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase":"0x3333333333333333333333333333333333333333",
"alloc": {}
}

各个参数的作用:

参数 作用
config 定义链配置,会影响共识协议,对创世影响不大,但新区块的产出规则均依赖该项。
nonce 64为随机数,用于挖矿,对应创世区块的Nonce字段,注意他和mixhash的设置需要满足以太坊的Yellow paper, 4.3.4. Block Header Validity, (44)章节所描述的条件。
timestamp UTC时间戳,对应创世区块的Time字段。
parentHash 父哈希,上一个区块的hash值,这里因为是创世区块,所以值为0
extraData 附加信息,随便填,可以填个性信息。
gasLimit 该值设置对gas的消耗总量限制,用来限制区块所能包含的交易信息总和,因为是私链,填写最大以后不需更改。
difficulty 设置当前区块的难度,用于挖矿,难度越大挖矿越难,这里设置较小难度。
mixhash 与nonce配合用于挖矿,由上一个区块的一部分生成的hash。注意他和nonce的设置需要满足以太坊的Yellow paper, 4.3.4. Block Header Validity, (44)章节所描述的条件。
coinbase 旷工账户,随便填
alloc 用来预置账号以及账号的以太币数量,因为私有链挖矿比较容易,所以我们不需要预置有币的账号,需要的时候自己创建即可。

c.初始化创世区块
打开命令行cmd,或者是Powershell输入如下命令完成初始化:
Windows下使用python-web3.py进行以太坊Dapp开发笔记--第1篇
d.启动私有链使用命令

geth --datadir data --networkid 989898 --rpc console --port 30304 --rpcport 8545 --rpccorsdomain "*" --ws --wsorigins="*" --wsaddr 0.0.0.0 --wsapi="eth,web3,personal,net" --allow-insecure-unlock

各参数的含义查看:
这其中有一些比较坑的命令,会在后面遇到的问题中补充,先用此命令进入geth的JavaScript命令行,看到下图表示成功:
Windows下使用python-web3.py进行以太坊Dapp开发笔记--第1篇
B.创建账户
在进入Geth Javascript后使用:personal.newAccount(“你的密码”)
Windows下使用python-web3.py进行以太坊Dapp开发笔记--第1篇
最下面绿色的就是公钥生成出来的地址,这个地址不需要记住。
创建完账户之后可以使用eth.accounts数组查看账户有哪些
Windows下使用python-web3.py进行以太坊Dapp开发笔记--第1篇

C.尝试挖矿
可以先查看自己的挖矿账户是哪个:
Windows下使用python-web3.py进行以太坊Dapp开发笔记--第1篇
miner.start():开始挖矿
miner.stop():停止挖矿

重新指定挖矿账户(默认挖矿账户为eth.accounts[0]):miner.setEtherbase(eth.aaccounts[1])

D.解锁账户
这个在刚开始使用geth阶段经常使用,想避免多次使用改命令的解决办法是-使用离线签名
personal.unlockAccount(eth.accounts[1],“你创建时的密码”)
Windows下使用python-web3.py进行以太坊Dapp开发笔记--第1篇
说明:在以太坊,凡是涉及到账户操作(外部账户:以太发送、发布、调用合约等)都需要事先解锁账户

E.发送以太
personal.sendTransaction({from:发送方账户,to:接收方账户,value:发送以太数目},“发送方账户密码”)
Windows下使用python-web3.py进行以太坊Dapp开发笔记--第1篇
发送完之后必须进行挖矿才能真正完成以太发送,其实就把以太坊当成账本,任何变动都需要记账,“记账的实现方式就是挖矿”。

安装python3.7和安装web3.py

我的版本:
python3.74
web3.py 5.1.0

web3.py直接使用pip install web3命令安装即可

安装nodejs以及solc

说明:这里主要是利用solc对solidity编写的智能合约进行编译!
百度搜索nodejs进行安装。
测试安装成功与否:
Windows下使用python-web3.py进行以太坊Dapp开发笔记--第1篇

安装好nodejs后,nodejs自带npm,使用npm安装solc:
先修改npm的存储路径:
PS C:\Users\Lee> npm config set prefix “D:\nodejs\node_global”
PS C:\Users\Lee> npm config set cache “D:\nodejs\node_cache”
然后使用npm install solc 安装即可。

环境准备完毕!!!

2. 利用web3.py进行简单的私链连接

from web3 import Web3
self.web3 = Web3(Web3.WebsocketProvider("ws://127.0.0.1:8546"))
# 检查是否连接成功
if self.web3.eth.getBlock(0) is None:
	print("连接失败")
elif self.web3.isConnected():
	print("连接成功")

Windows下使用python-web3.py进行以太坊Dapp开发笔记--第1篇

3.部署智能合约并进行简单的调用

a.使用remix网页编辑器进行智能合约编写,合约代码如下:

pragma solidity >=0.4.22 <0.7.0;

contract HelloWorld {
    event CreatePeopleLog(address indexed creator,string name,uint age);
    event SendEthToUserLog(address indexed sender,address indexed accepter,uint money);
    
    enum Sex{man,woman}
    struct Human{
        address payable addr;
        string name;
        uint age;
        Sex sex;
    }
    mapping(address => Human) public people;
    uint numOfPeople = 0;
    function CreatePeople(string memory _name,uint _age,Sex _sex) public{
        Human memory human = Human({
            addr:msg.sender,
            name:_name,
            age:_age,
            sex:_sex
        });
        numOfPeople += 1;
        people[msg.sender] = human;
        emit CreatePeopleLog(msg.sender,people[msg.sender].name,people[msg.sender].age);
    }
    
    function SendEthToUser(address payable _accepter) public payable{
        _accepter.transfer(msg.value);
        emit SendEthToUserLog(msg.sender,_accepter,msg.value);
    }
    
    uint public luckyNum;
    constructor() public{
        luckyNum = 888;
    }
    
    function SetLuckyNum(uint _num) public{
        luckyNum = _num;
    }
    
    function printHelloWorld() public returns(string memory){
        return 'Hello,World!';
    }
}

b.solc编译智能合约获取ABI
创建一个文件夹contract,创建.sol文件myContract.sol,将上面智能合约代码复制到myContract.sol并保存。使用命令行(这里命令行要先进入到保存myContract.sol文件的目录下,例如myContract.sol保存在D:\contract,需要先cd D:\contract再使用solcjs):
Windows下使用python-web3.py进行以太坊Dapp开发笔记--第1篇
c.python使用web3.py调用智能合约
python代码为:

from web3 import Web3
import json
class ethereumHandler():
    def __init__(self):
        self.web3 = Web3(Web3.WebsocketProvider("ws://127.0.0.1:8546"))
        # 检查是否连接成功
        if self.web3.eth.getBlock(0) is None:
            print("Failed to connect!")
        elif self.web3.isConnected():
            # read the abi
            # r"D:\pycharm_code\contract\myContract_sol_baseContract.abi", 'r'
            with open(r"D:\pycharm_code\exercise\contract\helloWorld_sol_HelloWorld.abi", 'r') as fo:
                preabi = fo.read()
                # print(self.preabi)
                myabi = json.loads(preabi)
                self.myContractAddr = '0xF327021D3dCCa3a5803C137f01653b54468C7D5E'
                self.myContract = self.web3.eth.contract(address=self.myContractAddr, abi=myabi)
                print("Successfully connected")
            print(self.myContract.all_functions())

    """检查传入地址是否正确,不正确则转换为正确地址并返回"""
    def CheckAddress(self, _address):
        if self.web3.isChecksumAddress(_address):
            return _address
        else:
            return self.web3.toChecksumAddress(_address)

    def unlockAccount(self,_addr):
        self.web3.geth.personal.unlockAccount(self.CheckAddress(_addr),"123")

    def SetLuckyNum(self,_addr,_num):
        self.unlockAccount(_addr)
        tx_hash = self.myContract.functions.SetLuckyNum(int(_num)).transact()
        return self.web3.toHex(tx_hash)

    def GetHuman(self,_addr):
        human = self.myContract.functions.people(self.CheckAddress(_addr)).call()
        print(human)

    def PrintHelloWorld(self):
        mystr = self.myContract.functions.printHelloWorld().call()
        print("调用合约函数printHelloWorld结果:",mystr)

    def SendEthToUser(self,_senderAddr,_accepterAddr,_money):
        self.unlockAccount(_senderAddr)
        tx_hash = self.myContract.functions.SendEthToUser(self.CheckAddress(_accepterAddr)).transact({
            'from':self.CheckAddress(_senderAddr),
            'value':self.web3.toWei(_money,"ether")
        })
        return self.web3.toHex(tx_hash)

    def GetLuckyNum(self):
        luckynum = self.myContract.functions.luckyNum().call()
        print("获取的幸运号码为:",luckynum)
       
    def CreatePeople(self,_addr,_name,_age,_sex):
        self.unlockAccount(_addr)
        tx_hash = self.myContract.functions.CreatePeople(_name,_age,_sex).transact({
            'from':self.CheckAddress(_addr)
        })
        return self.web3.toHex(tx_hash)

    def GetBalance(self,_addr):
        balance = self.web3.eth.getBalance(self.CheckAddress(_addr))
        print(("\n账户:{} \n余额: {}").format(str(self.CheckAddress(_addr)),str(balance)))

# 这里仅调用两个,剩余可以自己测试
e1 = ethereumHandler()
e1.GetLuckyNum()
e1.PrintHelloWorld()

结果:
Windows下使用python-web3.py进行以太坊Dapp开发笔记--第1篇
以上是调用合约中“不需要修改区块链数据”的函数,所以不用挖矿直接返回结果。下面是调用“修改区块链数据”的函数,需要挖矿。
(代码还是上面的代码)
先说明一下如何查看是否调用成功:(remix的简单使用)
现在remix-ide上连接到本地以太坊:
Windows下使用python-web3.py进行以太坊Dapp开发笔记--第1篇
上面选择 web3 provider,若连接成功会显示本地的账户信息:
Windows下使用python-web3.py进行以太坊Dapp开发笔记--第1篇
选第一个账户地址,在remix调用people函数:
Windows下使用python-web3.py进行以太坊Dapp开发笔记--第1篇
可以看到结果全为空值。
现在在python调用CreatePeople函数:
e1.CreatePeople(e1.web3.eth.accounts[0],“又摘桃花换酒钱”,18,0)
调用后在geth命令行会看到调用的hash信息:
Windows下使用python-web3.py进行以太坊Dapp开发笔记--第1篇
这时需要挖矿进行确认(因为修改了区块链的数据)
Windows下使用python-web3.py进行以太坊Dapp开发笔记--第1篇
Windows下使用python-web3.py进行以太坊Dapp开发笔记--第1篇
挖矿完成后停止:miner.stop()
再在remix网页调用一次People:
Windows下使用python-web3.py进行以太坊Dapp开发笔记--第1篇
可以看到区块链数据已被修改!!

所以记住一点(对于以太坊智能合约,只要对链上数据有修改,必须进行挖矿确认,没有修改链上数据的智能合约函数可以直接调用获得结果!

以上是第一篇博客。。也是第一次写博客,大四学生刚接触区块链,还有许多地方不懂,欢迎各位大佬给予开发经验。在学习过程中,希望通过博客记录一下自己走过的路!

相关标签: 区块链 python