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 · 123 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		maxClockDrift,
 66		frozenHeight,
 67		latestHeight,
 68		contractAddress,
 69	), nil
 70}
 71
 72// EncodeConsensusState ABI-encodes a ConsensusState (96 bytes).
 73// Root.Hash must be exactly 32 bytes.
 74func EncodeConsensusState(cs *ConsensusState) ([]byte, error) {
 75	appHash, err := toBytes32(cs.Root.Hash)
 76	if err != nil {
 77		return nil, err
 78	}
 79
 80	validatorsHash, err := toBytes32(cs.NextValidatorsHash)
 81	if err != nil {
 82		return nil, err
 83	}
 84
 85	return abienc.Encode(
 86		consensusStateSchema,
 87		[]any{cs.Timestamp, appHash, validatorsHash},
 88	)
 89}
 90
 91func DecodeConsensusState(buf []byte) (*ConsensusState, error) {
 92	vals, err := abienc.Decode(consensusStateSchema, buf)
 93	if err != nil {
 94		return nil, err
 95	}
 96
 97	var cs ConsensusState
 98
 99	rootHash, ok := vals[1].([32]byte)
100	if !ok {
101		return nil, ErrDecodeState
102	}
103
104	nextValidatorsHash, ok := vals[2].([32]byte)
105	if !ok {
106		return nil, ErrDecodeState
107	}
108
109	cs.Timestamp = vals[0].(uint64)
110	cs.Root.Hash = rootHash[:]
111	cs.NextValidatorsHash = nextValidatorsHash[:]
112
113	return &cs, nil
114}
115
116func trimNullBytes(b [32]byte) string {
117	end := 32
118	for end > 0 && b[end-1] == 0 {
119		end--
120	}
121
122	return string(b[:end])
123}