Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

ethabi.gno

3.64 Kb · 164 lines
  1package ics23_mpt
  2
  3import (
  4	"errors"
  5
  6	abienc "gno.land/p/onbloc/encoding/abi"
  7)
  8
  9var (
 10	clientStateSchema = abienc.Schema{Fields: []abienc.Field{
 11		{Type: abienc.TypeString},
 12		{Type: abienc.TypeUint32},
 13		{Type: abienc.TypeUint32},
 14		{Type: abienc.TypeUint64},
 15		{Type: abienc.TypeUint32},
 16		{Type: abienc.TypeUint32},
 17		{Type: abienc.TypeUint32},
 18	}}
 19
 20	consensusStateSchema = abienc.Schema{Fields: []abienc.Field{
 21		{Type: abienc.TypeUint64},
 22		{Type: abienc.TypeBytes32},
 23		{Type: abienc.TypeBytes32},
 24	}}
 25
 26	headerSchema = abienc.Schema{Fields: []abienc.Field{
 27		{Type: abienc.TypeUint64},
 28		{Type: abienc.TypeUint64},
 29		{Type: abienc.TypeBytes},
 30		{Type: abienc.TypeBytes},
 31	}}
 32)
 33
 34func EncodeClientState(cs ClientState) ([]byte, error) {
 35	return abienc.Encode(clientStateSchema, []any{
 36		cs.L2ChainID,
 37		cs.L1ClientID,
 38		cs.L2ClientID,
 39		uint64(cs.L2LatestHeight),
 40		uint32(cs.TimestampOffset),
 41		uint32(cs.StateRootOffset),
 42		uint32(cs.StorageRootOffset),
 43	})
 44}
 45
 46func DecodeClientState(buf []byte) (ClientState, error) {
 47	vals, err := abienc.Decode(clientStateSchema, buf)
 48	if err != nil {
 49		return ClientState{}, wrapErr(err)
 50	}
 51
 52	timestampOffset, err := toUint16(vals[4].(uint32), "timestamp offset")
 53	if err != nil {
 54		return ClientState{}, err
 55	}
 56
 57	stateRootOffset, err := toUint16(vals[5].(uint32), "state root offset")
 58	if err != nil {
 59		return ClientState{}, err
 60	}
 61
 62	storageRootOffset, err := toUint16(vals[6].(uint32), "storage root offset")
 63	if err != nil {
 64		return ClientState{}, err
 65	}
 66
 67	return ClientState{
 68		L2ChainID:         vals[0].(string),
 69		L1ClientID:        vals[1].(uint32),
 70		L2ClientID:        vals[2].(uint32),
 71		L2LatestHeight:    vals[3].(uint64),
 72		TimestampOffset:   timestampOffset,
 73		StateRootOffset:   stateRootOffset,
 74		StorageRootOffset: storageRootOffset,
 75	}, nil
 76}
 77
 78func EncodeConsensusState(cs ConsensusState) ([]byte, error) {
 79	stateRoot, err := toBytes32(cs.StateRoot, "state root")
 80	if err != nil {
 81		return nil, err
 82	}
 83
 84	storageRoot, err := toBytes32(cs.StorageRoot, "storage root")
 85	if err != nil {
 86		return nil, err
 87	}
 88
 89	return abienc.Encode(consensusStateSchema, []any{
 90		cs.Timestamp,
 91		stateRoot,
 92		storageRoot,
 93	})
 94}
 95
 96func DecodeConsensusState(buf []byte) (ConsensusState, error) {
 97	vals, err := abienc.Decode(consensusStateSchema, buf)
 98	if err != nil {
 99		return ConsensusState{}, wrapErr(err)
100	}
101
102	stateRoot := vals[1].([32]byte)
103	storageRoot := vals[2].([32]byte)
104
105	return ConsensusState{
106		Timestamp:   vals[0].(uint64),
107		StateRoot:   cloneBytes(stateRoot[:]),
108		StorageRoot: cloneBytes(storageRoot[:]),
109	}, nil
110}
111
112func EncodeHeader(h Header) ([]byte, error) {
113	return abienc.Encode(headerSchema, []any{
114		uint64(h.L1Height),
115		uint64(h.L2Height),
116		h.L2ConsensusStateProof,
117		h.L2ConsensusState,
118	})
119}
120
121func DecodeHeader(buf []byte) (Header, error) {
122	vals, err := abienc.Decode(headerSchema, buf)
123	if err != nil {
124		return Header{}, wrapErr(err)
125	}
126
127	return Header{
128		L1Height:              vals[0].(uint64),
129		L2Height:              vals[1].(uint64),
130		L2ConsensusStateProof: vals[2].([]byte),
131		L2ConsensusState:      vals[3].([]byte),
132	}, nil
133}
134
135// wrapErr prefixes a wrapped decode error with the package domain.
136func wrapErr(err error) error {
137	return errors.New("ics23mpt: " + err.Error())
138}
139
140func toUint16(v uint32, name string) (uint16, error) {
141	if v > 0xFFFF {
142		return 0, errors.New("ics23mpt: " + name + " exceeds uint16")
143	}
144
145	return uint16(v), nil
146}
147
148func toBytes32(b []byte, name string) ([32]byte, error) {
149	if len(b) != 32 {
150		return [32]byte{}, errors.New("ics23mpt: " + name + " must be 32 bytes")
151	}
152
153	var out [32]byte
154	copy(out[:], b)
155
156	return out, nil
157}
158
159func cloneBytes(b []byte) []byte {
160	out := make([]byte, len(b))
161	copy(out, b)
162
163	return out
164}