Symphonious

Living in a state of accord.

Exploring Ethereum 2: Weak Subjectivity Period

Occasionally the term “weak subjectivity period” pops up in Eth2 discussions. It’s a weird concept that you can usually just watch fly by and not miss too much. But when you’re talking about how to sync an existing Eth2 chain it becomes quite important.  Probably the best resource for it is Vitalik’s post: Proof of Stake: How I Learned to Love Weak Subjectivity I’ve struggled to get my head around it and why it matters so am writing up my current understanding. There is almost certainly at least one mistake in here somewhere…

So what is the weak subjectivity period? It’s the period that a client can be offline for and when it comes back online be able to completely reliably process blocks to get to the consensus chain head. For proof of work you can always do this, but not for proof of stake. To see why not, let’s look at an example.

Say we have an Eth2 network chugging away. Once 2/3 of those validators have attested to a particular epoch it’s considered finalised and no re-orgs can change it. In order to finalise two conflicting epoch’s you’d need at least 1/3 of validators to sign conflicting attestations but doing so is a slashable offence so there’s a very strong economic incentive to not do that. That incentive is essentially what crypto-economics are all about, whether you’re talking PoW or PoS it’s not that it’s mathematically impossible to break the chain, but that it costs you more money than anyone is willing or able to spend.

At this point it sounds like you should be able to just process blocks reliably, confirm the attestations and signatures all line up and it all works out. What’s the catch?

The catch is that validators can withdraw their staked funds and stop being a validator. There are limits on how fast those withdrawals can happen but once the money is out the economic incentive to not misbehave is gone. Critically despite the validator having withdrawn the money, they still have their private key and can sign things – with no staked funds anymore they can’t be slashed for it. Nodes fully sync’d to the chain know they are no longer a validator and reject those signatures but nodes further behind don’t yet have that information and see the signature as valid.

So, if we have 1/3 of validators which have withdrawn their stake, if my node is far enough back on the chain to have not seen the withdrawal of any of those nodes, then 1/3 of the validators you currently think are valid have no incentive to be honest and can sign any blocks or attestations with complete impunity and potentially form a chain which conflicts with the finalised state but is otherwise entirely valid. They can feed you those blocks to lead you down the wrong chain.

However if your node was further along the chain to see one or more of those validators exit, you’d reject their attestations leaving less than 1/3 of the validators as dishonest and allowing you to reliably reach the real chain head.

So the weak subjectivity period is essentially how far behind your node can be before 1/3 of validators can have exited without you knowing about it. Once you  fall behind more than that, you need to confirm the chain you want to sync to out of band.

Introducing Pantheon

This week, the work I’ve been doing for the past 6 months, and that PegaSys has been working on for the past 18 months or so was released into the world. Specifically we’ve released Pantheon 0.8.1, our new MainNet compatible, Apache 2 licensed, Java-based Ethereum client. And it’s open source.

I’m pretty excited about it on a few fronts.  Firstly I think it’s a pretty important thing for the Ethereum community. To be a healthy ecosystem, Ethereum needs to have diversity in its clients to avoid a bug in one client taking out or accidentally hard forking the entire network. Currently though, Geth and Parity dominate the Ethereum client landscape.  Pantheon clearly won’t change that in the short term, but it is backed by significant engineering resources to help it keep up with the ever changing Ethereum landscape and be a dependable option.

I’m also really excited that Pantheon is released under the Apache 2.0 license. Both Parity and Geth along with most other clients are licensed under the GPL or LGPL. There are still a large number of enterprises that completely avoid the GPL and LGPL which has closed off Ethereum to them. Having Pantheon available under a permissive license and in a highly familiar language like Java will make it much easier for many enterprises to start using, building on and innovating with Ethereum.

Pantheon will also be building out functionality from the Enterprise Ethereum standard for things like privacy and permissioning to make private chains more powerful and flexible. Meanwhile we have a significant number of researches continuing to work on developing new ways to get the most out of Ethereum.

Finally I’m quite excited to be able to contribute to an open source project as my full time job. I’ve had the opportunity to do some open source for work in the past but only on a fairly small scale. It’s a bit daunting to have everything in the open and on the record, but I’m really looking forward to engaging with the community and being able to show exactly what I’ve been doing.

Debugging Ethereum Reference Tests

There’s an exceptionally valuable set of ethereum reference tests that are run by  most or all of the different Ethereum clients to ensure they actually implement the specifications in a compatible way.  They’re one of the most valuable resources for anyone developing an Ethereum client.

The Aleth project maintains the official test client called testeth but it’s a little cryptic to work out how to actually run things with it and then use that to debug failures happening in the client you’re actually developing.  So this is what I’ve found useful:

Firstly, you need to checkout Aleth and compile it following their instructions. The one catch here is that you need to enable EVM tracing by adding the -D VMTRACE=1 flag when doing the initial cmake .. Once the whole build is finished you should find testeth in aleth/build/test/testeth Copy that to somewhere on your PATH.

Then you need to check out the actual reference tests and set ETHEREUM_TEST_PATH to point to where you checked it out.

Now you should be able to start running tests.  Running a single test with loads of debug looks like:

./testeth -t GeneralStateTests/stCreate2 -- --singletest create2collisionStorage --verbosity 3 --vmtrace --statediff | less -R

The param after -t needs to point to a directory containing the group of tests you want to run.  It could be as high level as GenerateStateTests or BlockchainTests or point to one of the directories under that.  The –singletest option lets you run just one file underneath that directory. The name is the filename without the .json extension.

–verbosity 3 –vmtrace –statediff turns on pretty comprehensive debugging information so you get a full EVM trace, plus a record of the changes to state that were made (it appears to show each change as well as the final state though I’m not sure I’ve fully understood the format yet).

And then finally piping to less -R allows you to scroll up and down and search through the output easily.  The -R tells less to render terminal control characters so you still get the pretty colours.

Now you have a reference client running the test and providing a ton of information about what the test expects to happen, go run the test in the client your developing, compare outputs, beat your head against a wall for a while and eventually find and fix your bug.

And a massive thanks to everyone who’s been involved in building up these reference tests. If you ever have to pay for your own beer at DevCon the community is doing something very wrong.

Exploring Ethereum – Account and Transaction Nonce

This is the second article on things I found particularly interesting in the Ethereum yellow paper.  The first is “What’s on the Blockchain?” and the same disclaimers apply: I’m no expert and you should go verify any claims I’m making before depending on them. Comments and corrections are most welcome either via email or @ajsutton on twitter.

One of the little details in the way Ethereum works is the idea of a “nonce” attached to each account and transaction. It’s a small but important detail.

For a “normal” account (ie has no code attached), the nonce is equal to the number of transaction sent from it. In the case of contracts (accounts with code) the nonce is the number of contract-creations made by the account.

When a transaction is created, the current nonce value from the account is assigned as the transaction nonce. Part of the initial tests for intrinsic transaction validity is that the transaction nonce is equivalent to the sender account’s current nonce.

The nonce is primarily included in transactions to prevent same-chain replay attacks on transactions. The transaction sender is identified by the signature they add to the transaction (those v, r and s items from each transaction we skipped over last time). To generate those you need the account’s private key so only the account owner can create a validly signed new transaction.

However, if the transaction data and the sender are the same, the signature will also be the same. So absent the nonce, an adversary could take any existing transaction and resend it to a node with a valid signature and have it processed a second time. For example, if Alice signed a transaction to send 10ETH to Bob, Bob could take that transaction signed by Alice and repeatedly submit it for processing until all of Alice’s funds had been transferred to Bob. Bob couldn’t change anything about the transaction but that doesn’t make Alice feel any better about losing all her ETH when she only approved a single transfer.

With the account nonce however, when the transaction is first processed, Alice’s account’s nonce is incremented and then when Bob resubmits the transaction, it is rejected because the nonce doesn’t match. Bob is unable to change the nonce on the transaction without invalidating Alice’s signature so the transaction can only be applied once, exactly as Alice intended.

BUT! This doesn’t entirely eliminate replay attacks.  The transaction could still be replayed on a different chain (though it may require replaying a number of transactions so the account nonce “catches up”).  The Ethereum / Ethereum Classic split caused quite a few headaches in this regard, until EIP-155 was implemented to include an ID for the chain in the data to sign, thus making the two different chains incompatible. The same problem can also occur between test chains and MainNet, though hopefully you aren’t sharing a single private key between them.

Interestingly, most explanations for the importance of the nonce suggest it’s there to prevent double spending which is not the case. The theory goes that Alice sends transaction t1 to pay Bob for some goods but then very quickly submits another transaction t2 with a higher gas price which is then prioritised higher and mined first allowing her to spend funds twice. Even if t2 was processed before t1, it would result in Alice’s balance being reduced before t1 was applied. If there were then insufficient funds t1 would be rejected. If you had already released the goods t1 was intended to pay for that might be bad, which is why typically people wait for the transaction to be in a block at a certain depth before considering it finalised. The nonce doesn’t help prevent this double-spend issue at all – Alice could deliberately setup the same race by giving both t1 and t2 the same nonce.

Finally, the account nonce is also used as part of creating the address for a new account/contract. The address of the new account is “the rightmost 160 bits of the Keccak hash of the RLP encoding of the structure containing only the sender and the account nonce”. Which is to say, the new address is a particular way of hashing the combination of the sender’s account hash and nonce. Since the sender account nonce is incremented when sending a new transaction this is guaranteed to generate a unique address.