区块链基础信息,如果节点中的信息用JSON格式描述,它看起来是这样的:{"number":1234567,"hash":"0xabc123...","parentHash":"0xdef456...","miner":"0xa1b2c3...",...,"transactions":[...]}hash:当前节点的哈希值parentHash:当前节点的哈希值前节点矿工:矿工地址交易:当前节点包含的交易数据矿工收到交易数据后,将其封装成一个区块,并将区块信息广播到以太坊网络。这里会有很多细节。推荐阅读本书。这里要强调的是,我们要让矿工干活,就需要花钱。在以太坊上,它的货币被称为“以太币”。使用Web3.pyWeb3.py是一个用于与以太坊网络交互的Python库。它封装了很多操作,方便我们进行交易、与智能合约交互、读取区块数据等。Web3.py官方文档:https://web3py.readthedocs.io/en/stable/index.html通过一张图,可以清楚的知道我们开发的应用Web3.py和以太坊网络的关系。从上图可以看出,Web3.py其实是中间层,可以通过HTTP、IPC(进程间通信)、WebSocket连接到以太坊节点,从而实现与整个以太坊网络的交互.使用前,我们需要安装Web3.py:pipinstallweb3pipinstall'web3[tester]'安装web3[tester]时,使用Web3.py提供的模拟节点进行测试。如果我们要同步真实节点,我们需要做:1.下载Geth搭建以太坊节点。2.启动Geth,等待其同步以太坊网络中的数据。Geth默认会启动HTTP服务,端口为8545。3.使用Web3.py通过HTTP连接新建的节点。4.使用Web3.py提供的API与节点进行交互。Geth是一个使用Go来实现以太坊协议的程序。与之类似,它是使用C++或Python实现的,但Geth是第一个。同步过程需要提取数据,可能需要几个小时。这里只是演示,直接使用模拟节点即可,如下图:上图中Web3.py提供了4种访问以太坊节点的方式,其中第4种是通过TesterProvider,要使用这个特性,你需要安装web3[tester]。安装web3后,首先通过TesterProvider方法连接到模拟节点。In[1]:fromweb3importWeb3#使用EthereumTesterProvider连接模拟节点In[2]:w3=Web3(Web3.EthereumTesterProvider())#判断连接是否正常In[3]:w3.isConnected()Out[3]:Truefor方便我们测试(比如测试写好的智能合约),Web3.py提供的模拟节点已经为我们提供了一些账户,每个账户有1,000,000个以太币。#获得可以使用的测试账户In[4]:w3.eth.accountsOut[4]:['0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf','0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF','0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69','0x1efF47bc3a10a45D4B230B5d10E37751FE6AA718','0xe1AB8145F7E55DC933d51a18c793F901A3A0b276','0xE57bFE9F44b819898F47BF37E5AF72a0783e1141','0xd41c057fd1c78805AAC12B0A94a405c0461A6FBb','0xF1F6619B38A98d6De0800F1DefC0a6399eB6d30C','0xF7Edc8FA1eCc32967F827C9043FcAe6ba73afA5c','0x4CCeBa2d7D2B4fdcE4304d3e09a1fea9fbEb1528']#获得第一个账户下的金额In[5]:w3.eth.get_balance(w3.eth.accounts[0])Out[5]:1000000000000000000000000使用w3.Theamountobtainedbytheeth.get_balancemethodis1000000000000000000000000,becausetheunitiswei.Becausecomputersarenotverygoodatdealingwithfloating-pointnumbers,inordertosolvethisproblem,manyprogrammerswillstore1.23yuaninthedatabaseas123,whichisthebasicunitincents.ThesameistrueforEthereum.Etherissimilartoyuan,andweiissimilartocents,butthecentsareonlyincreasedby100times,andtheratioofweitoetheris(18zeros):1ether=100000000000000000wei1wei=0.0000000000000000001etherWeb3.pyThetoWeiandfromWeimethodsareprovidedforunitconversion.Therearemultipleunitsbetweenetherandweiunits.YoucanrefertotheWeb3.pydocumentConvertingcurrencydenominations.简单的使用toWei和fromWei这两个方法:In[7]:Web3.toWei(1,'ether')Out[7]:1000000000000000000In[8]:Web3.fromWei(1000000000000000000000000,'ether')Out[8]:Decimal('1000000')模拟交易当你有了账户和资金后,你就可以模拟交易行为,即将你账户中的货币转入其他账户。我们来看看没有任何转账状态的区块链:#获取区块链最新区块的信息In[9]:w3.eth.get_block('latest')Out[9]:AttributeDict({'number':0,'hash':HexBytes('0x78b6514d115669937c0933824a0c74ff2eab14a25f1b1e799609872bcb18113b'),#前一个区块Hash为0'parentHash':HexBytes('0x0000000000000000000000000000000000000000000000000000000000000000'),...'gasLimit':3141592,'gasUsed':0,'timestamp':1635092566,#没有交易'transactions':[],'uncles':[]})因为是模拟节点,和真实节点不同,15秒左右不会添加新块,并且是的,它会模拟等待,直到您进行交易。至此,因为我们还没有进行任何交易,所以parentHash(出块前Hash)为0,transactions(交易数据)为空。这个区块其实就是创世区块。现在我们做一个交易,如下:#InitiateatransactionIn[10]:tx_hash=w3.eth.send_transaction({...:'from':w3.eth.accounts[0],...:'to':w3.eth.accounts[1],...:'value':w3.toWei(3,'ether')...:})from:senderaccountaddressto:receiveraccountaddressvalue:金额这次转会。我们可以通过get_transaction获取更多关于这笔交易的详细信息,如下:#获取该笔交易的信息In[14]:w3.eth.get_transaction(tx_hash)Out[14]:AttributeDict({'hash':HexBytes('0x15e9fb95dc39da2d70f4cc41556bd092c68a97a04892426a064e321bfe78662a'),'nonce':0,'blockHash':HexBytes('0x9f92558e214519a5e4ba7b8b4769a59bdc8c6c13e6fe5b0ec062b806e18f049f'),#交易数据在第一个区块中'blockNumber':1,#全网络第一个交易'transactionIndex':0,'':':'0x7E5F4552091A69125DFCB7B7B7B8C2659029395BDF','to':':'0x2B5C4795C026514F8317C7A215E215E215E215E218DCCDCDCDCDCDCDCD6CFQUELISTPOR':HexBytes('0x11bebd35f91582f55dc180dcfc1c5ccad48dadc207802727f7ac997df6490b22'),'s':HexBytes('0x697db707f5b7cc4d3a3196b434b0d5616300b8afbe8a21ab47ed9335252e4ebd')})完成交易后,我们可以查询对应账户的余额来判断是否转账成功。In[15]:w3.eth.get_balance(w3.eth.accounts[0])Out[15]:999996999999999999979000In[16]:w3.eth.get_balance(w3.eth.accounts[1])Out[16]:1000003000000000000000000可以看出,第二个账户的余额在1,000,000到1,000,003个ether之间,但是第一个账户中减少了3个多ether的金额是因为交易需要扣除少量交易费用。在真实的以太坊网络中,交易费用是可以调整的,这取决于您发起交易时的网络要求以及您希望处理交易的速度。就目前而言,交易手续费是一个比较大的成本。创建帐户在Web2.0中,大多数应用程序都需要在使用前创建一个帐户。该账号会保存在公司服务器中,即您虽然使用了该账号,但您并不拥有该账号的所有权。以微信为例,如果有一天腾讯要关闭你的账号是非常容易的,而这个账号下对你来说非常重要的数据将不辞而别。在Web3.0中,您还可以创建一个帐户。创建完成后,您将拥有账户的私钥和公钥。此帐户不会受到应用程序创建者或公司的影响。只要不泄露私钥,账户的所有权就掌握在自己手中,当然也存在一些隐患。如果您丢失了私钥,您将丢失您的帐户,并且无法找回密码。因此,在币圈,保护好你的私钥非常重要。通过Web3.py,我们可以轻松创建一个账户。这个过程不需要连接区块链网络或任何服务,也没有注册过程,如下:#createaccountIn[17]:acct=w3.eth.account.create()#账户地址In[19]:acct.addressOut[19]:'0x004D8ae69CD02Be5c491F7D095b5585cECE01407'#账户私钥(不可泄露给他人)In[20]:acct.keyOut[20]:HexBytes('0x39a579d1302e36fbf8b283eca5e1d52b4c56811921dfcdc2996f59eff7be6258')Again,youdon'tneedtobeconnectedto互联网或提供任何其他信息以创建有效的以太坊帐户。后面会写账号生成过程。账户是一个重要的概念,因为我们唯一能影响区块链变化的方式就是产生一笔交易(调用智能合约也被视为产生一笔交易),而每笔交易都必须由一个账户签署,以避免被假冒。一个账户可以进行交易,在交易之间传输信息,部署智能合约,并与智能合约进行交互。首先,让我们练习如何通过账户转账。回顾前面的代码,我们有一些账户通过EthereumTesterProvider连接到模拟节点。这些账户的转账过程是通过send_transaction方法完成的。这里隐藏了更多的细节,因为Web3.py知道你使用的是EthereumTesterProvider管理的测试账户,而这些账户都处于解锁状态,即默认情况下,这些账户的交易会被自动签名。这次我们先从我们创建的账户转钱,因为我们自己的账户没有以太币,所以我们需要先从测试账户转一些钱。In[25]:w3.eth.get_balance(acct.address)Out[25]:0In[26]:w3.eth.get_balance(test_acct)Out[26]:10000000000000000000000000#测试账户转账10000000000到创建的账户In[27]:tx_hash=w3.eth.send_transaction({...:'from':test_acct,...:'to':acct.address,...:'value':10000000000...:})在[28]:tx_hashOut[28]:HexBytes('0xa1b8be56bee0421035cbb9afb157218770f692c71b553a82cb52529c5dd12c3d')创建的账户中有钱,现在使用创建的账户完成一笔交易。在这个过程中,我们需要对交易数据进行人工签名。#TransactiondataIn[29]:tx_data={...:'to':test_acct,...:'value':500000000,...:'gas':21000,...:'gasPrice':1,#这个gas价格只存在于测试网...:'nonce':0...:}#使用acct的私钥对交易数据进行签名In[30]:signed=w3.eth.account。sign_transaction(tx_data,acct.key)In[31]:signedOut[31]:SignedTransaction(rawTransaction=HexBytes('0xf8638001825208946813eb9362372eef6200f3b1dbc3f819671cba69841dcd6500801ca029f2b216949529fbd19841c52e0cc78f218f45dd3531b918224f345f2e381aa9a0266619842d80050ab00bf8e0ea383056d7691a955113764e86927ddf36a478bb'),hash=HexBytes('0x402a89616ea2c37af4a17d8ff527e83141ac39968f3a61ddf92d4a1f5830cd29'),r=18973632901206428005591964593075310485747666570252293259781563419879236180649,s=17368282753934865160480197991111055873845272890414273881219608275127669913787,v=28)#进行交易In[32]:tx_hash=w3.eth.send_raw_transaction(signed.rawTransaction)In[33]:tx_hashOut[33]:HexBytes('0x402a89616ea2c37af4a17d8ff527e83141ac39968f3a61ddf92d4a1f5830cF首先关注交易数据,ga。gas:表示本次交易将花费多少gas(煤气)。gasPrice:表示gas的价格。在真实的以太坊网络中,gasPrice很高,这也是目前以太坊网络的一个问题和痛点none:在以太坊网络中,none表示当前账户的交易数量,而以太坊协议(Ethereum协议)将跟踪该值以避免双重支付(也称为双花攻击)。这里,0表示acct账户第一次产生交易。需要注意的是,send_transaction方法和send_raw_transaction方法都不代表交易完成。这些方法仅将交易数据广播到以太坊网络。只有以太坊网络中的矿工节点将交易上传到链上,才能说交易完成。现在,如果你的gas和gasPrice很小,在真正的以太坊网络中,你很难上链,也就是很难完成真正的交易。从开发者的角度来看,以太坊上的这种账户模型可以让我们在创建应用时无需考虑账户管理等功能。以太坊自然解决了这部分问题,你可以专注于具体的业务。中间。以太坊被提出与智能合约交互的一个重要原因是比特币网络不支持图灵完备的编程语言,导致很多应用开发失败,而以太坊支持图灵完备的编程语言,比如Solidity语言,它的语法类似于JS,是一门图灵完备的语言。基于Solidity语言,可以快速开发智能合约。简单来说,智能合约就是存储在以太坊区块链上的程序,任何人都可以使用。如果需要部署智能合约,流程类似于发起交易,只是交易数据包含Solidity编译的字节码,伪代码如下:#codecompiledintobytecodebytecode="6080604052348015610...36f6c63430006010033"tx={#Includebytecodeasdatainthetransactiondatabody'data':bytecode,'value':0,'gas':1500000,'gasPrice':1,'nonce':0}部署智能合约通常需要比普通交易,部署智能合约的交易体中没有to字段。Web3.py简化了智能合约的部署和交互过程。伪代码如下:#部署一个新的智能合约Example=w3.eth.contract(abi=abi,bytecode=bytecode)tx_hash=Example.constructor().transact()#通过smart的地址连接一个智能合约contractmyContract=web3.eth.contract(address=address,abi=abi)#传递参数并使用智能合约twentyone=myContract.functions.multiply7(3).call()生成签名信息账户不仅可以在链上执行交易等操作,还执行消息签名等链下操作。与交易不同的是,签名消息不需要上传到链上,也不会广播到区块链网络,即不花钱。简单来说,签名消息只是用你的私钥对数据进行数学运算,当你将这段数据发送给别人时,别人可以通过data方法还原出签名私钥对应的公钥,从而进行确认数据由您签名。这有什么用?它可以在NFT上使用。你可以对你的作品(一份数据)进行签名,然后在OpenSea(目前最大的NFT交易市场)上出售。当卖家购买时,购买过程中产生的交易数据会上传到链上。它需要以太币,而您的签名过程不需要任何费用。上链操作其实只是说明你签的作品是用一个账号购买的,而这次购买的交易操作产生的数据会记录在区块链中。是不可变的。通过一段伪代码,可以更直观的理解签名消息的整个过程:#1。待签名数据msg="我是二良,给我钱"#2.使用你账户的私钥执行之前的pk=b"..."signed_message=sign_message(message=msg,private_key=pk)#3。通过网络#4发送签名数据。消息接收方对发送的数据进行解码,得到数据的公钥,从而可以确定发送方的身份。1A以太坊开发人员指南,Pt。2个
