Ir ao contido principal

Axude a traducir esta p谩xina

馃審

Est谩 a ver esta p谩xina en ingl茅s porque a铆nda non a traducimos. Ax煤denos a traducir este contido.

Traducir p谩xina

No bugs here!馃悰

This page is not being translated. We've intentionally left this page in English for now.

A Python developer's introduction to Ethereum, part 1

getting started
python
blockchain
web3.py
Beginner
鉁Marc Garreau
馃摎Snake charmers
馃搯8 de setembro de 2020
鈴憋笍12 minute read

So, you鈥檝e heard about this Ethereum thing and are ready to venture down the rabbit hole? This post will quickly cover some blockchain basics, then get you interacting with a simulated Ethereum node 鈥 reading block data, checking account balances, and sending transactions. Along the way, we鈥檒l highlight the differences between traditional ways of building apps and this new decentralized paradigm.

(Soft) prerequisites

This post aspires to be accessible to a wide range of developers. Python tools will be involved, but they are just a vehicle for the ideas 鈥 no problem if you are not a Python developer. I will, however, be making just a few assumptions about what you already know, so we can quickly move on the Ethereum-specific bits.

Assumptions:

  • you can get around in a terminal,
  • you've written a few lines of Python code,
  • Python version 3.6 or greater is installed on your machine (use of a virtual environment is strongly encouraged), and
  • you鈥檝e used pip, Python鈥檚 package installer. Again, if any of these are untrue, or you don鈥檛 plan to reproduce the code in this article, you can likely still follow along just fine.

Blockchains, briefly

There are many ways to describe Ethereum, but at its heart is a blockchain. Blockchains are made up of a series of blocks, so let鈥檚 start there. In the simplest terms, each block on the Ethereum blockchain is just some metadata and a list of transactions. In JSON format, that looks something like this:

1{
2 "number": 1234567,
3 "hash": "0xabc123...",
4 "parentHash": "0xdef456...",
5 ...,
6 "transactions": [...]
7}
8
馃搵 Copiar

Each block has a reference to the block that came before it; the parentHash is simply the hash of the previous block.

A diagram depicting a blockchain including the data inside  each block

A blockchain is essentially a linked list; each block has a reference to the previous block.

This data structure is nothing novel, but the rules (i.e., peer-to-peer protocols) that govern the network are. There鈥檚 no central authority; the network of peers must collaborate to sustain the network, and compete to decide which transactions to include in the next block. So, when you want to send some money to a friend, you鈥檒l need to broadcast that transaction to the network, then wait for it to be included in an upcoming block.

The only way for the blockchain to verify that money was truly sent from one user to another is to use a currency native to (i.e., created and governed by) that blockchain. In Ethereum, this currency is called ether, and the Ethereum blockchain contains the only official record of account balances.

A new paradigm

This new decentralized tech stack has spawned new developer tools. Such tools exist in many programming languages, but we鈥檒l be looking through the Python lens. To reiterate: even if Python isn鈥檛 your language of choice, it shouldn鈥檛 be much trouble to follow along.

Python developers that want to interact with Ethereum are likely to reach for Web3.py. Web3.py is a library that greatly simplifies the way you connect to an Ethereum node, then send and receive data from it.

Ethereum clients can be configured to be reachable by IPC, HTTP, or Websockets, so Web3.py will need to mirror this configuration. Web3.py refers to these connection options as providers. You鈥檒l want to choose one of the three providers to link the Web3.py instance with your node.

A diagram showing how web3.py uses IPC to connect your applicaction to an Ethereum node

Configure the Ethereum node and Web3.py to communicate via the same protocol, e.g., IPC in this diagram.

Once Web3.py is properly configured, you can begin to interact with the blockchain. Here鈥檚 a couple of Web3.py usage examples as a preview of what鈥檚 to come:

1# read block data:
2w3.eth.get_block('latest')
3
4# send a transaction:
5w3.eth.send_transaction({'from': ..., 'to': ..., 'value': ...})
6
馃搵 Copiar

Installation

In this walkthrough, we鈥檒l just be working within a Python interpreter. We won't be creating any directories, files, classes or functions.

First, install IPython for a user-friendly environment to explore in. IPython offers tab completion, among other features, making it much easier to see what鈥檚 possible within Web3.py.

$ pip install ipython

Web3.py is published under the name web3. Install it like so:

$ pip install web3

One more thing 鈥 we're going to simulate a blockchain later, which requires a couple more dependencies. You can install those via:

$ pip install 'web3[tester]'

You鈥檙e all set up to go!

Spin up a sandbox

Open up a new Python environment by running ipython in your terminal. This is comparable to running python, but comes with more bells and whistles.

$ ipython

This will print out some information about the versions of Python and IPython you鈥檙e running, then you should see a prompt waiting for input:

1In [1]:
2
馃搵 Copiar

You鈥檙e looking at an interactive Python shell now. Essentially, its a sandbox to play in. If you鈥檝e made it this far, its time to import Web3.py:

1In [1]: from web3 import Web3
2
馃搵 Copiar

Introducing the Web3 module

Besides being a gateway to Ethereum, the Web3 module offers a few convenience functions. Let鈥檚 explore a couple.

In an Ethereum application, you will commonly need to convert currency denominations. The Web3 module provides a couple of helper methods just for this: fromWei and toWei.

Try converting some values to and from wei. Note that there are names for many of the denominations in between ether and wei. One of the better known among them is gwei, as it鈥檚 often how transaction fees are represented.

1In [2]: Web3.toWei(1, 'ether')
2Out[2]: 1000000000000000000
3
4In [3]: Web3.fromWei(500000000, 'gwei')
5Out[3]: Decimal('0.5')
6
馃搵 Copiar

Other utility methods on the Web3 module include data format converters (e.g., toHex), address helpers (e.g., isAddress), and hash functions (e.g., keccak). Many of these will be covered later in the series. To view all the available methods and properties, utilize IPython鈥檚 auto-complete by typing Web3. and hitting the tab key twice after the period.

Talk to the chain

The convenience methods are lovely, but let鈥檚 move on to the blockchain. The next step is to configure Web3.py to communicate with an Ethereum node. Here we have the option to use the IPC, HTTP, or Websocket providers.

We won't be going down this path, but an example of a complete workflow using the HTTP Provider might look something like this:

  • Download an Ethereum node, e.g., Geth.
  • Start Geth in one terminal window and wait for it to sync the network. The default HTTP port is 8545, but is configurable.
  • Tell Web3.py to connect to the node via HTTP, on localhost:8545. w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))
  • Use the w3 instance to interact with the node.

While this is one 鈥渞eal鈥 way to do it, the syncing process takes hours and is unnecessary if you just want a development environment. Web3.py exposes a fourth provider for this purpose, the EthereumTesterProvider. This tester provider links to a simulated Ethereum node with relaxed permissions and fake currency to play with.

A diagram showing the EthereumTesterProvider linking your web3.py application to a simulated Ethereum node

The EthereumTesterProvider connects to a simulated node and is handy for quick development environments.

That simulated node is called eth-tester and we installed it as part of the pip install web3[tester] command. Configuring Web3.py to use this tester provider is as simple as:

1In [4]: w3 = Web3(Web3.EthereumTesterProvider())
2
馃搵 Copiar

Now you鈥檙e ready to surf the chain! That鈥檚 not a thing people say. I just made that up. Let鈥檚 take a quick tour.

The quick tour

First things first, a sanity check:

1In [5]: w3.isConnected()
2Out[5]: True
3
馃搵 Copiar

Since we鈥檙e using the tester provider, this isn鈥檛 a very valuable test, but if it does fail, chances are you typed something in wrong when instantiating the w3 variable. Double-check that you included the inner parentheses, i.e., Web3.EthereumTesterProvider().

Tour stop #1: accounts

As a convenience, the tester provider created some accounts and preloaded them with test ether.

First, let鈥檚 see a list of those accounts:

1In [6]: w3.eth.accounts
2Out[6]: ['0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
3 '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF',
4 '0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69', ...]
5
馃搵 Copiar

If you run this command, you should see a list of ten strings that begin with 0x. Each is a public address and is, in some ways, analogous to the account number on a checking account. You would provide this address to someone that wanted to send you ether.

As mentioned, the tester provider has preloaded each of these accounts with some test ether. Let鈥檚 find out how much is in the first account:

1In [7]: w3.eth.get_balance(w3.eth.accounts[0])
2Out[7]: 1000000000000000000000000
3
馃搵 Copiar

That鈥檚 a lot of zeros! Before you go laughing all the way to the fake bank, recall that lesson about currency denominations from earlier. Ether values are represented in the smallest denomination, wei. Convert that to ether:

1In [8]: w3.fromWei(1000000000000000000000000, 'ether')
2Out[8]: Decimal('1000000')
3
馃搵 Copiar

One million test ether鈥娾斺妔till not too shabby.

Tour stop #2: block data

Let鈥檚 take a peek at the state of this simulated blockchain:

1In [9]: w3.eth.get_block('latest')
2Out[9]: AttributeDict({
3 'number': 0,
4 'hash': HexBytes('0x9469878...'),
5 'parentHash': HexBytes('0x0000000...'),
6 ...
7 'transactions': []
8})
9
馃搵 Copiar

A lot of information gets returned about a block, but just a couple things to point out here:

  • The block number is zero鈥娾斺妌o matter how long ago you configured the tester provider. Unlike the real Ethereum network, which adds a new block every 12 seconds, this simulation will wait until you give it some work to do.
  • transactions is an empty list, for the same reason: we haven鈥檛 done anything yet. This first block is an empty block, just to kick off the chain.
  • Notice that the parentHash is just a bunch of empty bytes. This signifies that it's the first block in the chain, also known as the genesis block.

Tour stop #3: transactions

We鈥檙e stuck at block zero until there鈥檚 a pending transaction, so let鈥檚 give it one. Send a few test ether from one account to another:

1In [10]: tx_hash = w3.eth.send_transaction({
2 'from': w3.eth.accounts[0],
3 'to': w3.eth.accounts[1],
4 'value': w3.toWei(3, 'ether'),
5 'gas': 21000
6})
7
馃搵 Copiar

This is typically the point where you鈥檇 wait for several seconds for your transaction to get included in a new block. The full process goes something like this:

  1. Submit a transaction and hold on to the transaction hash. Until the block containing the transaction is created and broadcast, the transaction is 鈥減ending.鈥 tx_hash = w3.eth.send_transaction({ 鈥 })
  2. Wait for the transaction to be included in a block: w3.eth.wait_for_transaction_receipt(tx_hash)
  3. Continue application logic. To view the successful transaction: w3.eth.get_transaction(tx_hash)

Our simulated environment will add the transaction in a new block instantly, so we can immediately view the transaction:

1In [11]: w3.eth.get_transaction(tx_hash)
2Out[11]: AttributeDict({
3 'hash': HexBytes('0x15e9fb95dc39...'),
4 'blockNumber': 1,
5 'transactionIndex': 0,
6 'from': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
7 'to': '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF',
8 'value': 3000000000000000000,
9 ...
10})
11
Mostrar todo
馃搵 Copiar

You鈥檒l see some familiar details here: the from, to, and value fields should match the inputs of our send_transaction call. The other reassuring bit is that this transaction was included as the first transaction ('transactionIndex': 0) within block number 1.

We can also easily verify the success of this transaction by checking the balances of the two accounts involved. Three ether should have moved from one to another.

1In [12]: w3.eth.get_balance(w3.eth.accounts[0])
2Out[12]: 999996999999999999969000
3
4In [13]: w3.eth.get_balance(w3.eth.accounts[1])
5Out[13]: 1000003000000000000000000
6
馃搵 Copiar

The latter looks good! The balance went from 1,000,000 to 1,000,003 ether. But what happened to the first account? It appears to have lost slightly more than three ether. Alas, nothing in life is free, and using the Ethereum public network requires that you compensate your peers for their supporting role. A small transaction fee was deducted from the account making the transaction to the tune of 31000 wei.

And breathe

We鈥檝e been at this for a while, so this seems as good a place as any to take a break. The rabbit hole continues on, and we鈥檒l continue exploring in part two of this series. Some concepts to come: connecting to a real node, smart contracts, and tokens. Have follow-up questions? Let me know! Your feedback will influence where we go from here. Requests welcome via Twitter.

脷ltima edici贸n: , Invalid DateTime
Editar p谩xina

Was this page helpful?