8. Alternatives to Dapps

The concept of dapps is compelling and native to blockchain technology’s most obvious use cases, such as peer-to-peer financing. However, the world is never binary. There are also many blockchain application use cases that could fit into the model of traditional web applications. Those are typically use cases where the public or consortium blockchain’s transparency and immutability can add value to an existing business. The application only needs the blockchain as a feature and does not need to decentralize the entire application itself. A payment processor for e-commerce web sites to accept cryptocurrencies is a good example. A crypto asset exchange (crypto to crypto or crypto to fiat) is another example.

For those applications, we need to make blockchain transactions and/or make smart contract function calls from a server. To do that, the accounts’ private keys or keystores and passwords must be managed on the server side.

  • For new transactions, it is obvious since the sender account needs to use its private key to authenticate the funds transferring out of it.

  • For modifying contract states, an Ethereum-compatible blockchain requires the party requesting the change to pay a “gas fee” for network maintainers (miners) to validate the request and record the change in new blocks. That also requires transferring funds (a gas fee) out of the requestor’s account and hence requires its private key.

In this chapter, we explore how to access Ethereum-compatible blockchain functionalities from a web app. The basic approach is to use a web3-compatible library but without a client-side wallet like Metamask.

JavaScript

The node.js framework enables JavaScript applications to be deployed on the server side. It is hence conceivable to use the web3.js library (or the compatible web3-cmt.js library) in a node.js server application.

The Full-Node Wallet

The first approach is to use a fully synchronized Ethereum node as the “wallet” for the application. The GETH (Ethereum) or Travis (CyberMiles) software running the node is able to manage keystores (i.e., the web3.personal package), sign transactions, and broadcast transactions to other blockchain nodes. Through the blockchain node’s Remote Procedure Call (RPC) interface, external applications can interact with the blockchain.

You will need to synchronize a full Ethereum (or Ethereum-compatible blockchain, such as CyberMiles) node behind a firewall. The node should turn on RPC services (i.e., the Ethereum default port 8545) so that the server-side web application can access it behind the firewall. It is important that the node’s port 8545 be completely blocked by the firewall and available only inside the firewall, as illustrated in Figure 8.1.

image

Figure 8.1 The behind-the-firewall setup

The following code example shows how to call the HelloWorld contract’s updateMessage() function (see Chapter 4) to record a new state in helloMessage onto the blockchain and pay its gas fees. We assume that the web3.js instance on the node.js server is attached to an Ethereum node that already has the keystore containing an account private key. The account has a sufficient balance to pay the gas fee for this transaction. You just need to unlock the account using its passphrase.

web3 = new Web3(new Web3.providers.HttpProvider(
              "http://node.ip.addr:8545"));
web3.personal.unlockAccount("...", pass);
hello.updateMessage(new_mesg);

Of course, storing the keystores on the node is still insecure. A single misconfigured firewall setting might expose the node’s port 8545 to attackers. Attackers could easily gain access to all private keys on the server as they are unlocked by the web application.

Raw Transactions

The second approach is to create signed raw transactions and then simply use web3.js to broadcast the transaction onto a blockchain node. In this setup, the blockchain node could be a third-party hosted node outside of the firewall, such as an Infura node. The blockchain node does not store any private key or keystore. The web application itself, however, manages the private keys it needs in a database table. Figure 8.2 illustrates the architecture of this design.

image

Figure 8.2 Application-managed private keys

Signing raw transactions is beyond the scope of web3.js. We use the EthereumJS library here to work in conjunction with web3.js. In particular, the ethereumjs-tx project provides ways to sign transactions using private keys. The private keys are typically stored in database tables in this case.

The following code shows how to deploy the HelloWorld smart contract on Ethereum using a signed raw transaction. The gas fee is paid from the account, and the application has access to the private key.

const Web3 = require("web3");
const Tx = require('ethereumjs–tx')
web3 = new Web3(new Web3.providers.HttpProvider(
            "http://node.ip.addr:8545"));

var account = "0x1234"; // Ethereum account address
var key = new Buffer('private key', 'hex');

var abi = // ABI of Hello World
var bytecode = // Bytecode of Hello World

var create_contract_tx = {
    gasPrice: web3.toHex(web3.eth.gasPrice),
    gasLimit: web3.toHex(3000000),
    data: bytecode,
    from: account
};

var tx = new Tx(create_contract_tx);
tx.sign(key);

var stx = tx.serialize();
web3.eth.sendRawTransaction('0x' + stx.toString('hex'), (err, hash) => {
    // ... Test if success
});

The next example shows how to call the updateMessage() function on the contract:

const Web3 = require("web3");
const Tx = require('ethereumjs–tx')
web3 = new Web3(new Web3.providers.HttpProvider(
            "http://node.ip.addr:8545"));

var account = "0x1234"; // Ethereum account address
var key = new Buffer('private key', 'hex');

var abi = // ABI of Hello World
var contract_address = "0xabcd";
var contract = web3.eth.contract(abi).at(contract_address);
var data = contract.updateMessage.getData(msg);
var nonce = web3.eth.getTransactionCount(account);

var call_contract_tx = {
    nonce: web3.toHex(nonce),
    gasPrice: web3.toHex(web3.eth.gasPrice),
    gasLimit: web3.toHex(3000000),
    from: account,
    to: contract_address,
    value: '0x00',
    data: data
};

var tx = new Tx(call_contract_tx);
tx.sign(key);

var stx = tx.serialize();
web3.eth.sendRawTransaction('0x' + stx.toString('hex'), (err, hash) => {
    // ... Test if success
});

The EthereumJS library is much more than just ethereumjs–tx. It provides the JavaScript to manage private keys, keystores, and wallets. It would be useful if you are doing extensive key management and low-level programming on your own.

Python and Others

While JavaScript is the native language for web3.js, many developers do not like to use JavaScript on server applications. Because of that, there are other programming languages’ implementations of the web3 library. For example, web3.py is a Python implementation of web3. The following code shows how to decrypt and construct a private key from a GETH keystore file. You can store the content of this keystore file in a database table, and its password in another database table.

with open('filename') as keyfile:
    encrypted_key = keyfile.read()
    private_key = w3.eth.account.decrypt(encrypted_key, password)

With the private key in place, the code segment next illustrates how to construct a raw transaction in web3.py to transfer ETH from one account to another.

from web3 import Web3

tx = {
    'to': '0xABCD',
    'value': w3.toWei('10', 'ether'),
    'gas': 2000000,
    'gasPrice': w3.toWei('2', 'gwei'),
    'nonce': 0
}

private_key = b"xyz123"
signed = w3.eth.account.signTransaction(transaction, private_key)
tx_hash = w3.eth.sendRawTransaction(signed.rawTransaction)

The next example shows how to use web3.py to make a smart contract function call:

from web3 import Web3

contract_address = ="0xWXYZ"
contract = w3.eth.contract(address=contract_address, abi=HELLO_ABI)
nonce = w3.eth.getTransactionCount('0xABCD')
tx = contract.functions.updateMessage(
    'A new hello message'
).buildTransaction({
    'gas': 70000,
    'gasPrice': w3.toWei('2', 'gwei'),
    'nonce': nonce
})

private_key = b"xyz123"
signed = w3.eth.account.signTransaction(tx, private_key)
tx_hash = w3.eth.sendRawTransaction(signed.rawTransaction)

There is obviously a lot more to the web3.py library, and it is substantially different from web3.js when it comes to the exact API usages. I encourage interested readers to review its documentation at https://web3py.readthedocs.io. Furthermore, there are other programming language choices for web3.

Since web applications vary a lot depending on the development framework you choose, I will leave it as an exercise for you to work out your own web applications.

Conclusion

In this chapter, I discussed how to build server-side applications that interact with blockchains and smart contracts. Those applications require central servers to function and hence are less decentralized than the dapps discussed in Chapter 7. However, for the short term, incorporating decentralized features into otherwise centralized applications could be the most plausible path for the mass adoption of blockchain applications.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.66.178