Sunday, February 23, 2020

Programming an Ethereum Smart Contract with Vyper

and deploying it with MetaMask and MyEtherWallet (MEW)


Introduction

Ethereum has a vast amount of developer resources available, such that for a beginner its hard to know where to start.

If you go with the recommended approach you'd probably choose Solidity along with either JavaScript or golang. JavaScript and golang are traditionally the most well supported languages for the developer tooling around Ethereum. The original Ethereum node software, geth, is written in golang. There's a version of the Solidity smart contract compiler, solcjs, written in JavaScript, and available as a Node.js NPM package.

The other Smart Contract language that is supported by the Ethereum Foundation is Vyper. Vyper is a python-like language that was designed for security, simplicity and testability. In my view this makes Vyper ideal for a beginner. Vyper foregoes some of the power of Solidity (for example, class inheritance and function modifiers) in order to uphold the Vyper principles of being simple and secure.

In this article I'll be stepping you through creating a smart contract with the Vyper programming language, deploying it to the Ethereum test network, and then interacting with the contract - calling its two externally accessible functions. The contract deployment and contract interaction are achieved using two in-browser tools - MyEtherWallet (MEW) and MetaMask.


Background reading

Before you start I would highly recommend this article to get up to speed with the Ethereum ecosystem as a whole.
https://medium.com/@mattcondon/getting-up-to-speed-on-ethereum-63ed28821bbe
Its from 2017 but the content is still valid today.

Along with the Ethereum whitepaper, which is a must-read if you're a developer:
https://github.com/ethereum/wiki/wiki/White-Paper


Installing the Vyper compiler

There's a number of options available to you as documented here:
https://vyper.readthedocs.io/en/latest/installing-vyper.html

One of the simplest options is to install it using python's package manager (pip). I'll start by ensuring you have the python development environment setup correctly.


Installing a recent version of Python and Pip with Pyenv

If you don't have already have a recent version of Python installed, or don't even know, I would highly recommend that you start by installing pyenv. Pyenv is a tool for python version management.

I followed the Pyenv installation instructions for a MacOS installation via homebrew, but there are instructions for other OSes given.

After installing pyenv, you can install the latest version of python with

% pyenv install 3.8.0

You will now have an up to date version of both python and pip available from your terminal command prompt.

Check what version of python is installed:
% python -V

Output:
Python 3.8.0


Check what version of pip is installed:
% pip -V

Output:

pip 19.2.3 from /Users/hg/.pyenv/versions/3.8.0/lib/python3.8/site-packages/pip (python 3.8)


Installing the Vyper compiler

Once you have python and pip installed aready, you can install the Vyper compiler with:

% pip install vyper

Check what version of Vyper is installed:

% vyper --version

Output:
0.1.0b16+commit.5e4a94a



Writing a smart contract in Vyper

For the first contract, we're going to keep things very simple and go with a public storage contract.
All the contract does is stores a single number in its storage area, and implements two public accessor functions - a getter and a setter.

Use a text editor and open a new file named storage.vy

Note that vy is the file extension for Vyper source code.

Here's the Vyper code:

stored_data: uint256

@public
def set(new_value : uint256):
    self.stored_data = new_value

@public
@constant
def get() -> uint256:
    return self.stored_data


Line 1 declares a variable named 'stored_data' of type 'uint256'. This is the only thing that the contract will store on the blockchain.

Line 3 (def set...) declares the public set function, to update the 'stored_data' variable.

Line 9 (def get...) declares the public get function, to get the 'stored_data' variable.

Its important to note that these two functions get and set are marked public and so can be 'called' by anyone - by using Ethereum client software like MyEtherWallet, or programmatically via the web3 or by other library.

Calling a public function on a smart contract actually consists of sending a transaction to the deployed contract's address - but this is an implementation detail hidden that is hidden by client software or libraries.

Further reading about the structure of contracts in Vyper:
https://vyper.readthedocs.io/en/latest/structure-of-a-contract.html


Compiling the Vyper smart contract

To compile the contract into EVM bytecode:

% vyper -f bytecode storage.vy > storage.bin

To generate the ABI for the contract:

% vyper -f abi storage.vy > storage.abi

The ABI is a JSON format interface specification file, and it is needed to be able to interact with the smart contract (i.e. call its functions).


Deploy the smart contract to the Rinkeby test network

Install MetaMask

If you haven't already, now is a good time to install the MetaMask plugin/extension into your browser - https://metamask.io/
Setup MetaMask with a seed phrase and it will create an in-browser Ethereum wallet that you can use for real transactions, or in this case, test transactions.

When MetaMask is setup, at the top right you should see the network dropdown.

Change this to 'Rinkeby Test Network'. Press the DEPOSIT button, then press the GET ETHER button under the TEST FAUCET option.

After opening https://www.rinkeby.io/#stats use the 'Crypto Faucet' button on the left and follow the instructions. The minimum option (3 ETH) will be more than enough for test purposes and to deploy this contract.

The second thing you'll need to do is to setup MyEtherWallet (MEW). This will let you deploy and interact with your smart contract.


Setup MyEtherWallet (MEW)

Go to https://www.myetherwallet.com and setup the seed phrase.

Now you'll need to give MyEtherWallet (MEW) access to your MetaMask wallet, which contains the 3 ETH for testing.

Go to https://www.myetherwallet.com/access-my-wallet and press the browser extension option.

It should come up with a 'Access via MetaMask' window, and you'll need to grant it permission. Press the 'Access My Wallet' button.


Deploy the smart contract

Inside MyEtherWallet (MEW), press the left hand side option 'Contract' then 'Deploy Contract'.

From the terminal, issue this command:

% cat storage.bin

Output:
0x6100f456600436101561000d576100ea565b600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a0526360fe47b160005114156100c25734156100ba57600080fd5b600435600055005b636d4ce63c60005114156100e95734156100db57600080fd5b60005460005260206000f350005b5b60006000fd5b6100046100f4036100046000396100046100f4036000f3

Using the mouse, copy the contents of the file from the terminal prompt.

Inside MEW, paste the copied text contents into the bytecode field.

On the terminal again, issue this command:

% cat storage.abi

Output:
[{"name": "set", "outputs": [], "inputs": [{"type": "uint256", "name": "new_value"}], "constant": false, "payable": false, "type": "function", "gas": 35315}, {"name": "get", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 1181}]


Using the mouse, copy the contents of the file from the terminal prompt.

Inside MEW, paste the copied text contents into the ABI/JSON field.

Enter a name for your contract, e.g. 'storage1'.

Press the 'Sign Transaction' button.

MetaMask will open up a window where you'll be able to confirm the deployment of your contract.

You'll see the gas fee and total.
You can press on the data tab and you'll see the bytecode that you pasted earlier.

Press the Confirm button to proceed with the deployment of your contract.

You may need to wait several seconds for the transaction to be confirmed at this point.
MetaMask should give you a successful deployment popup and link you to the transaction on etherscan.io.
E.g.
https://rinkeby.etherscan.io/tx/0x36663b338ab0eaa7d7cdd91aa5abacdc273757ff56b81221d76a2ff0aedc9860

Here you can see the address of your newly deployed contract. In my case it is here:
https://rinkeby.etherscan.io/address/0x7baad2f634d6bde84916e7d6db40ca2e502eaff6


Side note on contract addresses

Contract addresses are calculated deterministically, based on the account that created it. They are based on the nonce value of your account. So it is possible to know in advance what the contract address will be, if necessary.

Details here: https://ethereum.stackexchange.com/questions/760/how-is-the-address-of-an-ethereum-contract-computed


Interacting with the smart contract

Now that your contract is deployed, its time to interact with it - call its get and set functions.

The get function can be called 'for free' - it doesn't cost any gas, because its just returning the current state of the blockchain.
Calling the 'set' fuction however must be paid for in gas, because by calling it you are actually changing the current state of the blockchain.

Go back to MEW and navigate to the left hand side 'Contract' option then 'Interact with Contract'.

Paste your newly created contract address into the 'Contract Address' field.

In the ABI/JSON field, past your ABI file contents.

Press the Continue button.

There's a dropdown which shows 'Select an item'. This lists all of the public functions on the smart contract. There's only two available - get and set.

Choose get first, it will execute immediately and show the result being 0. 0 is the default value for uninitialised storage in Ethereum.

Now choose 'set' from the dropdown.

Enter the required value into the new_value field, e.g. 88.

Leave the Value in ETH as 0.

Press the 'Write' button.

MetaMask will open up a window where you'll be able to confirm your contract interaction.
What you're actually doing here is sending a transaction to the contract with a value in the data field - the data specifies to the EVM which function is being called (set) and the value of the parameter to it (88).

Press the confirm button.

You may need to wait several seconds for the transaction to be confirmed.

MetaMask should give you a confirmed transaction popup and link you to the transaction on etherscan.io.
E.g.
https://rinkeby.etherscan.io/tx/0x42af3501fff6ddd67a97cc52c94565f149f4d7f985d223523cebae2efc693bbb

Press the "Press to see more" link at the bottom of this page on etherscan.io to see the detail of the function call you made.

Go back to MEW and this time select the 'get' from the dropdown.

Confirm that the value you set is now reflected by the get.

You have now successfully deployed an Ethereum smart contract written in Vyper, and interacted with it using MetaMask and MyEtherWallet (MEW).

Congratulations!


Final notes - can you modify a smart contract?

Note that once a smart contract is deployed, you can't modify it; it is immutable and exists on the Ethereum blockchain forever.

If you need to modify or update the contract, you'll need to deploy the updated code to a new contract address.

There are various techniques for handling contract "upgrades" including migrating the existing storage. There's a good article here on this topic: https://mixbytes.io/blog/storage-upgradable-ethereum-smart-contracts

Note also that a contract can destroy itself (along with its storage), via the selfdestruct() function, as documented here: https://vyper.readthedocs.io/en/v0.1.0-beta.15/built-in-functions.html#selfdestruct

Once destroyed, the contract and its storage are removed from that block onwards. After destruction, it is technically still possible to see the historical contract bytecode and storage, which exists on earlier blocks of the Ethereum blockchain.


Follow @dodgy_coder on Twitter

Saturday, February 8, 2020

Programming Bitcoin Cash (BCH) with the NBitcoin .NET library and C#

The NBitcoin library is the most active and well supported library in .NET for working with Bitcoin and other similar cryptocurrencies.

NBitcoin fully supports Bitcoin Cash (BCH), however the ebook and programming guide examples focus solely on Bitcoin Core (BTC).

The problem you encounter when following the NBitcoin guide is firstly that the QBitNinja API only supports Bitcoin Core and secondly that broadcasting the transaction seems to require either running a full local node or using the QBitNinja API.

In this tutorial I'll show you how to spend your Bitcoin Cash using the NBitcoin library running under dotnet core, without the need for running a full local node or for accessing the QBitNinja API.

The program you write here will create a new transaction, sign it with your private key, and broadcast it to the Bitcoin Cash network.


Dotnet core
is the preferred programming environment for NBitcoin. Dotnet core is open source and runs under the Linux, MacOSX and Windows operating systems.

Bitcoin Cash is the ideal cryptocurrency for experimenting with programming APIs and libraries - you can send small transactions for very low fees, typically for a fraction of one US cent.


Step 1: Project Setup

Follow the setup guide as normal:
https://programmingblockchain.gitbook.io/programmingblockchain/introduction/project_setup

The rest of these steps 2-12 below loosely follow the "Spend Your Coin" guide:
https://programmingblockchain.gitbook.io/programmingblockchain/bitcoin_transfer/spend_your_coin

Its not absolutely required, but for a more complete and in depth understanding, I would recommend you read through the "Spend Your Coin" guide above (with the knowledge that it applies to Bitcoin Core) before proceeding with the rest of the below steps.


Step 2: Add support for Bitcoin Cash

On the command line:

dotnet add package NBitcoin.Altcoins

The code - add these using statements to the top of the C# source file.

using NBitcoin;
using NBitcoin.Altcoins;
using NBitcoin.Protocol;


And at the beginning of the program, add this:

// Important Note - this is not test code.
// It is going to run in production (called the "mainnet").
var network = NBitcoin.Altcoins.BCash.Instance.Mainnet;



Step 3: (Optional) Generate a new private key and address

The below code snippet generates a new BCH private key and BCH address using the NBitcoin library.
  
// Generate a random private key.
Key rawPrivateKey = new Key();

// The private key, also known as the Bitcoin secret or the WIF (Wallet Interchange Format).
// If you intend to use it, make sure you save the below somewhere safe!
BitcoinSecret privateKey = rawPrivateKey.GetBitcoinSecret(network);
Console.WriteLine("privateKey = " + privateKey);
Console.WriteLine("address (from privateKey) = " + privateKey.GetAddress(ScriptPubKeyType.Legacy));


Alternatively you can generate a new private key and address using BCH wallet software.


Step 4: Setup the variables for your private keys and addresses

To spend your Bitcoin Cash, you'll need to know the private keys of both the "destination" BCH address and the "from" BCH address.
The "from" BCH address is also known as the input address or the outpoint to spend.

Here's the code to setup the address and private keys of both the "destination" address and the "from" address.

// Destination - private key and address. The destination of the new transaction we are creating.
// Note: its not strictly necessary for creating the transaction to have the private key of the destination,
// but its better to add it here so that you know that you have access to it, and that the money won't be 'lost'.
var privateKey = new BitcoinSecret("PASTE_YOUR_DESTINATION_ADDRESS_PRIVATE_KEY_HERE", network);
Console.WriteLine("dest privateKey = " + privateKey);
var address = privateKey.GetAddress(ScriptPubKeyType.Legacy);
Console.WriteLine("dest address = " + address);
Console.WriteLine("dest address scriptPubKey= " + address.ScriptPubKey);

// Input Transaction - private key and address. The from address.
var inPrivateKey = new BitcoinSecret("PASTE_YOUR_FROM_ADDRESS_PRIVATE_KEY_HERE", network);
var inAddress = inPrivateKey.GetAddress(ScriptPubKeyType.Legacy);
Console.WriteLine("inPrivateKey = " + inPrivateKey);
Console.WriteLine("inAddress = " + inAddress);
Console.WriteLine("inAddress scriptPubKey= " + inAddress.ScriptPubKey);


You can run the program now to make sure its working - on the command line:

dotnet run


Step 5: Determine the Transaction ID of the "from" address

Now you need to determine the transaction ID and index number of your "from" address by looking at the transaction in a blockchain explorer and plugging in the correct TxId and index number below.

// Determine the previous output that will be spent, as the Input to our new transaction.
// For example:

// https://explorer.bitcoin.com/bch/tx/292f70e71f8bc2e94b7c0ac46c4e89371dc59b821639de67376f6f0b09544d92
string txInIdString = "292f70e71f8bc2e94b7c0ac46c4e89371dc59b821639de67376f6f0b09544d92";
uint txOutIndex = 0; // <== Ensure this index is correct!
OutPoint outPointToSpend = OutPoint.Parse(txInIdString + ":" + txOutIndex);



Step 6: Create the new transaction

var transaction = Transaction.Create(network);
transaction.Inputs.Add(new TxIn()
{
    PrevOut = outPointToSpend
});



Step 7: Setup the amount to spend and the miner fee

// Suggested miner fee for this transaction, as of February 2020,
// is 0.000003 BCH or around USD 0.001 (a tenth of a cent).
// Check recent blocks for guidance.

var minerFee = new Money(0.000003m, MoneyUnit.BTC);  

// Replace below with your amount.
// It is the total unspent amount of the "from" address.
var txInAmount = new Money(0.0021m, MoneyUnit.BTC);

// Move to the destination address.

var spendAmount = txInAmount - minerFee;
transaction.Outputs.Add(spendAmount, address.ScriptPubKey);


Step 8: Add a message to the transaction, using the OP_RETURN template (max 80 characters)

var message = "Test 1: using the NBitcoin library to move Bitcoin Cash. BCH Rocks!";
var bytes = Encoding.UTF8.GetBytes(message);
transaction.Outputs.Add(Money.Zero, TxNullDataTemplate.Instance.GenerateScriptPubKey(bytes));



Step 9: Sign the transaction

// Get the ScriptPubKey from the private key of the outPointToSpend.
transaction.Inputs[0].ScriptSig = inAddress.ScriptPubKey;

// Sign the transaction with the input private key.
var txInId = uint256.Parse(txInIdString);
var inCoin = new Coin(txInId, txOutIndex, txInAmount, inAddress.ScriptPubKey);
transaction.Sign(inPrivateKey, inCoin);



Step 10: Determine the TxId of your transaction, which is just its hash

Console.WriteLine("New TxId: " + transaction.GetHash());

Now is a good time to run the code and check its all working. From the command line:

dotnet run


Step 11: Broadcast your transaction to the Bitcoin Cash network

This is the final step and should only be attempted if your program runs fine up to step 10.

Before you run it, confirm your amount to spend is correct.

//
// Connect to a BCH node and broadcast the transaction.
// See here for the DNS Seed list:
// https://github.com/Bitcoin-ABC/bitcoin-abc/blob/master/src/chainparams.cpp

//
using (var node = Node.Connect(network, "seed.bchd.cash:8333"))
{
    // Say hello to the node.
    node.VersionHandshake();

    // Advertise your transaction (send just the hash).
    node.SendMessage(new InvPayload(InventoryType.MSG_TX, transaction.GetHash()));

    // Send the contents of the transaction.
    node.SendMessage(new TxPayload(transaction));

    // Wait for the message to be sent.
    Thread.Sleep(5000);
}


Run your program the command line:

dotnet run


Step 12: That's it, well done for making it to the end!!

If everything went well, your new transaction was accepted by the Bitcoin Cash network, and it will show up in a block explorer such as this one:

https://explorer.bitcoin.com/bch/tx/3ecf0f0dafd26e8d788b59a433bf00e1c3c079e82dada5111e899c87a75dadff

Replace the above TxId with yours from step 10.

Your new transaction will be listed initially as having 0 confirmations, which means its in the mempool.

Now you just need to wait for your transaction to be confirmed. This will happen as soon as the next block is mined and your transaction gets added to that block by the winning miner.

Follow @dodgy_coder on Twitter