diff --git a/da/mock/mock.go b/da/mock/mock.go index 1c706f5588..c70e9afed9 100644 --- a/da/mock/mock.go +++ b/da/mock/mock.go @@ -11,19 +11,16 @@ import ( // It does actually ensures DA - it stores data in-memory. type MockDataAvailabilityLayerClient struct { logger log.Logger - - Blocks map[[32]byte]*types.Block - BlockIndex map[uint64][32]byte + dalcKV store.KVStore } var _ da.DataAvailabilityLayerClient = &MockDataAvailabilityLayerClient{} var _ da.BlockRetriever = &MockDataAvailabilityLayerClient{} // Init is called once to allow DA client to read configuration and initialize resources. -func (m *MockDataAvailabilityLayerClient) Init(config []byte, kvStore store.KVStore, logger log.Logger) error { +func (m *MockDataAvailabilityLayerClient) Init(config []byte, dalcKV store.KVStore, logger log.Logger) error { m.logger = logger - m.Blocks = make(map[[32]byte]*types.Block) - m.BlockIndex = make(map[uint64][32]byte) + m.dalcKV = dalcKV return nil } @@ -46,8 +43,13 @@ func (m *MockDataAvailabilityLayerClient) SubmitBlock(block *types.Block) da.Res m.logger.Debug("Submitting block to DA layer!", "height", block.Header.Height) hash := block.Header.Hash() - m.Blocks[hash] = block - m.BlockIndex[block.Header.Height] = hash + blob, err := block.MarshalBinary() + if err != nil { + return da.ResultSubmitBlock{DAResult: da.DAResult{Code: da.StatusError, Message: err.Error()}} + } + + m.dalcKV.Set(types.Uint64ToByteSlice(block.Header.Height), hash[:]) + m.dalcKV.Set(hash[:], blob) return da.ResultSubmitBlock{ DAResult: da.DAResult{ @@ -59,12 +61,30 @@ func (m *MockDataAvailabilityLayerClient) SubmitBlock(block *types.Block) da.Res // CheckBlockAvailability queries DA layer to check data availability of block corresponding to given header. func (m *MockDataAvailabilityLayerClient) CheckBlockAvailability(header *types.Header) da.ResultCheckBlock { - _, ok := m.Blocks[header.Hash()] - return da.ResultCheckBlock{DAResult: da.DAResult{Code: da.StatusSuccess}, DataAvailable: ok} + hash := header.Hash() + _, err := m.dalcKV.Get(hash[:]) + if err != nil { + return da.ResultCheckBlock{DAResult: da.DAResult{Code: da.StatusSuccess}, DataAvailable: false} + } + return da.ResultCheckBlock{DAResult: da.DAResult{Code: da.StatusSuccess}, DataAvailable: true} } // RetrieveBlock returns block at given height from data availability layer. func (m *MockDataAvailabilityLayerClient) RetrieveBlock(height uint64) da.ResultRetrieveBlock { - hash := m.BlockIndex[height] - return da.ResultRetrieveBlock{DAResult: da.DAResult{Code: da.StatusSuccess}, Block: m.Blocks[hash]} + hash, err := m.dalcKV.Get(types.Uint64ToByteSlice(height)) + if err != nil { + return da.ResultRetrieveBlock{DAResult: da.DAResult{Code: da.StatusError, Message: err.Error()}} + } + blob, err := m.dalcKV.Get(hash) + if err != nil { + return da.ResultRetrieveBlock{DAResult: da.DAResult{Code: da.StatusError, Message: err.Error()}} + } + + block := &types.Block{} + err = block.UnmarshalBinary(blob) + if err != nil { + return da.ResultRetrieveBlock{DAResult: da.DAResult{Code: da.StatusError, Message: err.Error()}} + } + + return da.ResultRetrieveBlock{DAResult: da.DAResult{Code: da.StatusSuccess}, Block: block} } diff --git a/da/mock/mock_test.go b/da/mock/mock_test.go index 79e1862c90..64a2101873 100644 --- a/da/mock/mock_test.go +++ b/da/mock/mock_test.go @@ -9,15 +9,17 @@ import ( "github.com/celestiaorg/optimint/da" "github.com/celestiaorg/optimint/log/test" + "github.com/celestiaorg/optimint/store" "github.com/celestiaorg/optimint/types" ) func TestLifecycle(t *testing.T) { var da da.DataAvailabilityLayerClient = &MockDataAvailabilityLayerClient{} + dalcKV := store.NewInMemoryKVStore() require := require.New(t) - err := da.Init([]byte{}, nil, &test.TestLogger{T: t}) + err := da.Init([]byte{}, dalcKV, &test.TestLogger{T: t}) require.NoError(err) err = da.Start() @@ -29,11 +31,12 @@ func TestLifecycle(t *testing.T) { func TestMockDALC(t *testing.T) { var dalc da.DataAvailabilityLayerClient = &MockDataAvailabilityLayerClient{} + dalcKV := store.NewInMemoryKVStore() require := require.New(t) assert := assert.New(t) - err := dalc.Init([]byte{}, nil, &test.TestLogger{T: t}) + err := dalc.Init([]byte{}, dalcKV, &test.TestLogger{T: t}) require.NoError(err) err = dalc.Start() @@ -69,10 +72,12 @@ func TestRetrieve(t *testing.T) { var dalc da.DataAvailabilityLayerClient = mock var retriever da.BlockRetriever = mock + dalcKV := store.NewInMemoryKVStore() + require := require.New(t) assert := assert.New(t) - err := dalc.Init([]byte{}, nil, &test.TestLogger{T: t}) + err := dalc.Init([]byte{}, dalcKV, &test.TestLogger{T: t}) require.NoError(err) err = dalc.Start() @@ -109,6 +114,13 @@ func getRandomBlock(height uint64, nTxs int) *types.Block { block.Data.IntermediateStateRoots.RawRootsList[i] = getRandomBytes(32) } + // TODO(https://github.com/celestiaorg/optimint/issues/143) + // This is a hack to get around equality checks on serialization round trips + if nTxs == 0 { + block.Data.Txs = nil + block.Data.IntermediateStateRoots.RawRootsList = nil + } + return block } diff --git a/types/serialization.go b/types/serialization.go index 8f7188ec79..7f68edb368 100644 --- a/types/serialization.go +++ b/types/serialization.go @@ -1,6 +1,7 @@ package types import ( + "encoding/binary" "errors" pb "github.com/celestiaorg/optimint/types/pb/optimint" @@ -182,6 +183,13 @@ func (c *Commit) FromProto(other *pb.Commit) error { return nil } +// Uint64ToByteSlice converts a uint64 into an 8 byte little endian slice +func Uint64ToByteSlice(v uint64) []byte { + b := make([]byte, 8) + binary.LittleEndian.PutUint64(b, v) + return b +} + func txsToByteSlices(txs Txs) [][]byte { bytes := make([][]byte, len(txs)) for i := range txs {