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

codec.gno

2.76 Kb · 124 lines
  1package cometbls
  2
  3import (
  4	abienc "gno.land/p/onbloc/encoding/abi"
  5	"gno.land/p/onbloc/ibc/union/types"
  6)
  7
  8// Wire formats for the cometbls client and consensus state.
  9//
 10// ibc-union heights carry a single revision (revision 0), so only the revision
 11// height is encoded; decoding rebuilds the Height with types.NewHeight.
 12
 13var clientStateSchema = abienc.Schema{Fields: []abienc.Field{
 14	{Type: abienc.TypeBytes32},
 15	{Type: abienc.TypeUint64},
 16	{Type: abienc.TypeUint64},
 17	{Type: abienc.TypeUint64},
 18	{Type: abienc.TypeUint64},
 19	{Type: abienc.TypeBytes32},
 20}}
 21
 22var consensusStateSchema = abienc.Schema{Fields: []abienc.Field{
 23	{Type: abienc.TypeUint64},  // Timestamp
 24	{Type: abienc.TypeBytes32}, // Root (app hash)
 25	{Type: abienc.TypeBytes32}, // NextValidatorsHash
 26}}
 27
 28func EncodeClientState(m *ClientState) ([]byte, error) {
 29	var chainIdWord [32]byte
 30
 31	chainBytes := []byte(m.ChainID)
 32	if len(chainBytes) > 31 {
 33		chainBytes = chainBytes[:31]
 34	}
 35
 36	copy(chainIdWord[:], chainBytes)
 37
 38	return abienc.Encode(clientStateSchema, []any{
 39		chainIdWord,
 40		m.TrustingPeriod,
 41		m.MaxClockDrift,
 42		uint64(m.FrozenHeight.RevisionHeight),
 43		uint64(m.LatestHeight.RevisionHeight),
 44		[32]byte(m.ContractAddress),
 45	})
 46}
 47
 48func DecodeClientState(buf []byte) (*ClientState, error) {
 49	vals, err := abienc.Decode(clientStateSchema, buf)
 50	if err != nil {
 51		return nil, err
 52	}
 53
 54	chainIdWord := vals[0].([32]byte)
 55	chainID := trimNullBytes(chainIdWord)
 56	trustingPeriod := vals[1].(uint64)
 57	maxClockDrift := vals[2].(uint64)
 58	frozenHeight := types.NewHeight(vals[3].(uint64))
 59	latestHeight := types.NewHeight(vals[4].(uint64))
 60	contractAddress := vals[5].([32]byte)
 61
 62	return NewClientState(
 63		chainID,
 64		trustingPeriod,
 65		0,
 66		maxClockDrift,
 67		frozenHeight,
 68		latestHeight,
 69		contractAddress,
 70	), nil
 71}
 72
 73// EncodeConsensusState ABI-encodes a ConsensusState (96 bytes).
 74// Root.Hash must be exactly 32 bytes.
 75func EncodeConsensusState(cs *ConsensusState) ([]byte, error) {
 76	appHash, err := toBytes32(cs.Root.Hash)
 77	if err != nil {
 78		return nil, err
 79	}
 80
 81	validatorsHash, err := toBytes32(cs.NextValidatorsHash)
 82	if err != nil {
 83		return nil, err
 84	}
 85
 86	return abienc.Encode(
 87		consensusStateSchema,
 88		[]any{cs.Timestamp, appHash, validatorsHash},
 89	)
 90}
 91
 92func DecodeConsensusState(buf []byte) (*ConsensusState, error) {
 93	vals, err := abienc.Decode(consensusStateSchema, buf)
 94	if err != nil {
 95		return nil, err
 96	}
 97
 98	var cs ConsensusState
 99
100	rootHash, ok := vals[1].([32]byte)
101	if !ok {
102		return nil, ErrDecodeState
103	}
104
105	nextValidatorsHash, ok := vals[2].([32]byte)
106	if !ok {
107		return nil, ErrDecodeState
108	}
109
110	cs.Timestamp = vals[0].(uint64)
111	cs.Root.Hash = rootHash[:]
112	cs.NextValidatorsHash = nextValidatorsHash[:]
113
114	return &cs, nil
115}
116
117func trimNullBytes(b [32]byte) string {
118	end := 32
119	for end > 0 && b[end-1] == 0 {
120		end--
121	}
122
123	return string(b[:end])
124}