package types import ( "context" "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/synapsecns/sanguine/ethergo/signer/signer" ) const ( stateOffsetRoot = 0 stateOffsetOrigin = 32 stateOffsetNonce = 36 stateOffsetBlockNumber = 40 stateOffsetTimestamp = 45 stateOffsetGasData = 50 stateSize = 62 ) // State is the state interface. type State interface { Encoder // Root is the root of the Origin Merkle Tree. Root() [32]byte // Origin is the domain where Origin is located. Origin() uint32 // Nonce is the amount of sent messages. Nonce() uint32 // BlockNumber is the block of the last sent message. BlockNumber() *big.Int // Timestamp is the unix time of the last sent message. Timestamp() *big.Int // GasData is the gas data from the chain's gas oracle. GasData() GasData // Hash returns the hash of the state. Hash() ([32]byte, error) // SubLeaves returns the left and right sub-leaves of the state. SubLeaves() (leftLeaf, rightLeaf [32]byte, err error) // SignState returns the signature of the state payload signed by the signer. SignState(ctx context.Context, signer signer.Signer) (signer.Signature, []byte, common.Hash, error) } type state struct { root [32]byte origin uint32 nonce uint32 blockNumber *big.Int timestamp *big.Int gasData GasData } // NewState creates a new state. func NewState(root [32]byte, origin uint32, nonce uint32, blockNumber *big.Int, timestamp *big.Int, gasData GasData) State { return &state{ root: root, origin: origin, nonce: nonce, blockNumber: blockNumber, timestamp: timestamp, gasData: gasData, } } func (s state) Root() [32]byte { return s.root } func (s state) Origin() uint32 { return s.origin } func (s state) Nonce() uint32 { return s.nonce } func (s state) BlockNumber() *big.Int { return s.blockNumber } func (s state) Timestamp() *big.Int { return s.timestamp } func (s state) GasData() GasData { return s.gasData } func (s state) Hash() ([32]byte, error) { leftLeaf, rightLeaf, err := s.SubLeaves() if err != nil { return [32]byte{}, err } concatLeafs := append(leftLeaf[:], rightLeaf[:]...) return crypto.Keccak256Hash(concatLeafs), nil } func (s state) SubLeaves() (leftLeaf, rightLeaf [32]byte, err error) { encodedState, err := s.Encode() if err != nil { return } leftLeaf = crypto.Keccak256Hash(encodedState[stateOffsetRoot:stateOffsetNonce]) rightLeaf = crypto.Keccak256Hash(encodedState[stateOffsetNonce:stateSize]) return } func (s state) SignState(ctx context.Context, signer signer.Signer) (signer.Signature, []byte, common.Hash, error) { return signEncoder(ctx, signer, s, StateInvalidSalt) } var _ State = state{}