celestiaorg/blobstream-contracts

feat!: Deploy contract with a custom nonce

Closed this issue · 3 comments

Context:

Currently, when deploying the Blobstream contract:

function initialize(uint256 _nonce, uint256 _powerThreshold, bytes32 _validatorSetHash) public initializer {
// CHECKS
bytes32 newCheckpoint = domainSeparateValidatorSetHash(_nonce, _powerThreshold, _validatorSetHash);
// EFFECTS
state_eventNonce = _nonce;
state_lastValidatorSetCheckpoint = newCheckpoint;
state_powerThreshold = _powerThreshold;
/// @dev Initialize the OwnableUpgradeable explicitly.
/// DO NOT REMOVE! It is mandatory for allowing the owner to upgrade.
__Ownable_init(_msgSender());
// LOGS
emit ValidatorSetUpdatedEvent(_nonce, _powerThreshold, _validatorSetHash);
}

We're using the nonce of the valset that was provided as the initial nonce. And that nonce is used to calculate the checkpoint so we can't use a different nonce than the one from the valset.

However, let's assume we have a stable network for over a year, where the same validator set is kept and no changes happened. When we will want to deploy the Blobstream contract, we will get that 1 year old valset and use it for deployment. The problem is that the contract will start at the nonce of that initial validator set and would expect the attestations to be relayed starting that valset.nonce+1. This wouldn't be possible in case that Blobstream is freshly deployed on that network. Also, orchestrators will only sign a maximum of 3 weeks of attestations. So, the bridge will not be deployable in this case.

Proposal:

Add another field to the constructor of the contract containing the desired starting nonce and checking if it's > valset.Nonce that was used for deployment. And make it the user's responsibility to choose where to start Blobstream.

cc @adlerjohn @evan-forbes

Makes sense, good catch. Constructor is one-time so fixed cost doesn't really matter.

slight deviation from this per a sync discussion is just to accept the checkpoint as an arg and not construct it using the validator set hash

Huhhhh that's actually an interesting alternative since the initial state is trusted anyways.