If you’re Java developer dipping into the Ethereum blockchain, here’s what you need to know about the ins and outs of sending transactions.
Join the DZone community and get the total member practice.
After I’ve voiced my concerns about the blockchain technology, let’s get a bit more practical with the blockchain. In particular, with Ethereum.
I needed to send a transaction with Java, so I looked at EthereumJ. You have three options:
- Utter knot – you enable syncing, which means the entire blockchain gets downloaded. It takes a lot of time, so I abandoned that treatment
- “Light” knot – you disable syncing, so you just become part of the network, but don’t fetch any parts of the chain. Not entirely sure, but I think this corresponds to the “light” mode of geth (the Ethereum CLI). You are able to send messages (e.g. transaction messages) to other peers to process and store on the blockchain, but you yourself do not have the blockchain.
- Offline (no knot) – just create and sign the transaction, compute its raw representation (in the Ethereum RLP format) and thrust it to the blockchain via a centralized API, e.g. the etherscan.io API. Etherscan is itself a knot on the network and it can perform all of the operations (so it serves as a proxy)
Before going further, maybe it’s worth pointing out a few general properties of the blockchain (the Ethereum one and popular cryptocurrencies at least) – it is a distributed database, relying on a peer-to-peer (overlay) network, formed by whoever has a client software running (wallet or otherwise). Transactions are in the form of “I (private key holder) want to send this amount to that address”. Transactions can have extra data stored inwards them, e.g. signifying what they are about. Transactions then get verified by peers (presently using a Proof-of-work based consensus) and get stored on the blockchain, which means every connected peer gets the freshly created blocks (each block consisting of numerous transactions). That’s the blockchain in brief, and Ethereum is no exception.
Why may you want to send transactions? I can’t think of a ordinary and evident use-case. Maybe you just want to implement a better wallet than the existing ones. For example, in my case, I wished to store the head of a hash chain on the blockchain so that it cannot be tampered with.
In my particular case, I was more interested in storing a particular lump of data as part of the transaction, rather than the transaction itself, so I had two knots that sent very puny transactions to each other (randomly choosing sender and recipient). I know I could most likely have done that with a clever contract instead, but “one step at a time”. The initial code can be found here and is based intensely on the EthereumJ samples. Since EthereumJ uses Spring internally, and my application uses Spring, it took some extra effort to permit for two knots, but that’s not so relevant to the task at palm. The most significant chunk of the code can be seen further below in this post, only slightly modified.
You should have a user.conf file on the classpath with some defaults, and it can be based on the default EthereumJ config. The more significant part is the outward user1 and user2 conf files (which in the general script can just be one conf file). Here’s a sample one, with the following significant parameters:
- peer.networkId – whether you are using the real production network (=1), or a test network (=Trio). Obviously, for anything than production, you’d want a test network. On test networks, you can get free ether by utilizing a faucet. In order to use a test network, there are two more parameters below – blockchain.config.name = ropsten and genesis = ropsten.json . Note that there are more test networks at the moment for experimenting with alternatives to proof-of-work.
- peer.privateKey – this is the most significant bit. It is your secret key that gives you control over your blockchain “account”. Only using that private key can you sign transactions (using an elliptic curve algorithm). The private key has a corresponding public key, which is basically your address on the network – if anyone wants to send funds, they send them to your public key. But only you can then send funds from your account, as nobody else wields the private key. Which means you have to protect it. In this case, it’s in plaintext in a file, which may not be ideal if you operate with big amounts of ether. Consider using some key-management solution (as outlined here).
- peer.ip.list – this is optional, but preferable – you need to have a list of peers to connect to in order to bootstrap your client and make it part of the network. The peers there are connected to other peers, and so on and so forward, so in the end, it’s a single interconnected network. Note that in combination with the port number, that requires some extra network configuration if you are using that on a server/cluster/stack – you’d have to open some ports and permit outgoing and incoming connections.
- database.dir – this is the directory where the blockchain and the list of discovered peers will be stored. It uses leveldb, and what I found out is that EthereumJ uses an outdated leveldb, which didn’t work on my machine. So I excluded them and by hand used newer versions
- sync.enabled – whether you want to fetch the blockchain or not. Normally you don’t need to, as it takes a lot of time, but that way you are not a utter knot and don’t contribute to the network.
As I noted earlier, I didn’t need a utter knot, I just needed to send a transaction. The light knot would do (the difference should be simply switching sync.enabled from true to false), but after primarily successfully connecting to peers, I began getting weird exceptions I didn’t have time to go into, so I couldn’t join the network anymore (maybe because of the crappy Wi-Fi I’m presently using).
Fortunately, there is a totally “offline” treatment – use an outward API to publish your transactions. All you need is your private key and a library (EthereumJ in this case) to prepare your transaction. So you can leave behind everything you read in the previous paragraphs. What you need is just the RLP encoded transaction after you have signed it. E.g.:
In this example, I use the Etherscan.io API (there’s also a test one for the Ropsten network). It also has a manual entry form to test your transactions (the link is for the Ropsten test network).
What are the parameters above?
- nonce – this is a sequence number for transactions per user (=per private key). Each subsequent transaction should have a nonce that is the nonce of the previous + 1. That way, nobody can replay the same transaction and drain the funds of the sender (the transaction that gets signed contains the nonce, so you cannot use the same raw transaction representation and just resubmit it). How to obtain the nonce? If you are connected to the Ethereum network, there’s an ethereum.getRepository().getNonce(fromAddress), . However, in a disconnected script, you’d need to obtain the current number of transactions for the sender, and then increment it. This is done via the eth_getTransactionCount endpoint. Note that it’s returned as hexadecimal, so you have to parse it, e.g.
- gas price, maximum gas price – these are used to cover the transaction costs (sending isn’t for free). You can read more here. You can obtain the current gas price by calling the “eth_gasPrice” API endpoint. Most likely it’s a good idea to actually fetch the gas price periodically and cache it for a brief period, rather than fetching it for every transaction. If you are connected to the network, you can obtain the gas price automatically.
- receiverAddress – a byte array signifying the public key of the recipient
- value – how much ether you want to send. The smallest unit is actually a “gwei”, and the value is specified in gweis (a fraction of 1 ETH)
- data – any extra data that you want to put in the transaction.
- chainId – this is again related to which network you are using. Production=1, Ropsten test network=Three. If you are nosey why you have to encode it in a transaction, you can read here.
After that, you sign the raw representation of the transaction with your private key (the raw representation is RLP (Recursive Length Prefix)). And then you send it to the API (you’d need a key for that, which you can get at Etherscan and include it in the URL). It’s almost identical to what you would’ve done if you were connected. But now you are relying on a central party (Etherscan) instead of becoming part of the network.
It may look “easy”, and when you’ve already done it and grabbed it, it sounds like a chunk of cake, but there are too many details that nobody abstracts from you, so you have to have the utter picture before even being able to shove a single transaction. What a nonce is, what a chainId is, what a test network is, how to get test ether (the top google result for a ropsten faucet doesn’t work at the moment, so you have to figure that out as well), then figure out whether you want to sync the chain or not, to be part of the network or not, to resolve weird connectivity issues and network configuration. And that’s not even mentioning clever contracts. I’m not telling it’s bad, it’s just not elementary enough and that’s a barrier to broader adoption. That very likely applies to most of programming, tho’. Anyway, I hope the above examples can get people began more lightly.
Build vs Buy a Data Quality Solution: Which is Best for You? Maintaining high quality data is essential for operational efficiency, meaningful analytics and good long-term customer relationships. But, when dealing with numerous sources of data, data quality becomes elaborate, so you need to know when you should build a custom-built data quality devices effort over canned solutions. Download our whitepaper for more insights into a hybrid treatment.
Like This Article? Read More From DZone
Free DZone Refcard
Microservices in Java
Published at DZone with permission of Bozhidar Bozhanov , DZone MVB . See the original article here.
Opinions voiced by DZone contributors are their own.