diff --git a/.golangci.yml b/.golangci.yml index 981aa9c91..902f974a0 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -6,10 +6,10 @@ run: - mempool - state/indexer - state/txindex + - third_party linters: enable: - - deadcode - errcheck - gofmt - goimports @@ -20,13 +20,14 @@ linters: - misspell - revive - staticcheck - - structcheck - typecheck - unused - - varcheck issues: exclude-use-default: false + include: + - EXC0012 # EXC0012 revive: Annoying issue about not having a comment. The rare codebase has such comments + - EXC0014 # EXC0014 revive: Annoying issue about not having a comment. The rare codebase has such comments linters-settings: revive: @@ -35,6 +36,9 @@ linters-settings: disabled: true - name: duplicated-imports severity: warning + - name: exported + arguments: + - disableStutteringCheck goimports: local-prefixes: github.com/rollkit diff --git a/block/block_cache.go b/block/block_cache.go index 661e4a78b..9f305e4ca 100644 --- a/block/block_cache.go +++ b/block/block_cache.go @@ -6,6 +6,7 @@ import ( "github.com/rollkit/rollkit/types" ) +// BlockCache maintains blocks that are seen and hard confirmed type BlockCache struct { blocks map[uint64]*types.Block hashes map[string]bool @@ -13,6 +14,7 @@ type BlockCache struct { mtx *sync.RWMutex } +// NewBlockCache returns a new BlockCache struct func NewBlockCache() *BlockCache { return &BlockCache{ blocks: make(map[uint64]*types.Block), diff --git a/block/block_sync.go b/block/block_sync.go index 36846bc3f..4eda839fd 100644 --- a/block/block_sync.go +++ b/block/block_sync.go @@ -24,8 +24,8 @@ import ( "github.com/rollkit/rollkit/types" ) -// P2P Sync Service for block that implements the go-header interface. -// Contains a block store where synced blocks are stored. +// BlockSyncService is the P2P Sync Service for block that implements the +// go-header interface. Contains a block store where synced blocks are stored. // Uses the go-header library for handling all P2P logic. type BlockSyncService struct { conf config.NodeConfig @@ -43,6 +43,7 @@ type BlockSyncService struct { ctx context.Context } +// NewBlockSyncService returns a new BlockSyncService. func NewBlockSyncService(ctx context.Context, store ds.TxnDatastore, conf config.NodeConfig, genesis *cmtypes.GenesisDoc, p2p *p2p.Client, logger log.Logger) (*BlockSyncService, error) { if genesis == nil { return nil, errors.New("genesis doc cannot be nil") @@ -90,8 +91,10 @@ func (bSyncService *BlockSyncService) initBlockStoreAndStartSyncer(ctx context.C return nil } -// Initialize block store if needed and broadcasts provided block. -// Note: Only returns an error in case block store can't be initialized. Logs error if there's one while broadcasting. +// WriteToBlockStoreAndBroadcast initializes block store if needed and broadcasts +// provided block. +// Note: Only returns an error in case block store can't be initialized. Logs +// error if there's one while broadcasting. func (bSyncService *BlockSyncService) WriteToBlockStoreAndBroadcast(ctx context.Context, block *types.Block) error { // For genesis block initialize the store and start the syncer if int64(block.Height()) == bSyncService.genesis.InitialHeight { @@ -205,7 +208,7 @@ func (bSyncService *BlockSyncService) Start() error { return nil } -// OnStop is a part of Service interface. +// Stop is a part of Service interface. func (bSyncService *BlockSyncService) Stop() error { err := bSyncService.blockStore.Stop(bSyncService.ctx) err = multierr.Append(err, bSyncService.p2pServer.Stop(bSyncService.ctx)) @@ -254,6 +257,7 @@ func newBlockSyncer( return goheadersync.NewSyncer[*types.Block](ex, store, sub, opts...) } +// StartSyncer starts the BlockSyncService's syncer func (bSyncService *BlockSyncService) StartSyncer() error { bSyncService.syncerStatus.m.Lock() defer bSyncService.syncerStatus.m.Unlock() diff --git a/block/header_sync.go b/block/header_sync.go index 17f72ef1d..91f5b3fea 100644 --- a/block/header_sync.go +++ b/block/header_sync.go @@ -24,10 +24,11 @@ import ( "github.com/rollkit/rollkit/types" ) -// P2P Sync Service for header that implements the go-header interface. +// HeaderSyncService is the P2P Sync Service for header that implements the +// go-header interface. // Contains a header store where synced headers are stored. // Uses the go-header library for handling all P2P logic. -type HeaderSynceService struct { +type HeaderSyncService struct { conf config.NodeConfig genesis *cmtypes.GenesisDoc p2p *p2p.Client @@ -43,7 +44,8 @@ type HeaderSynceService struct { ctx context.Context } -func NewHeaderSynceService(ctx context.Context, store ds.TxnDatastore, conf config.NodeConfig, genesis *cmtypes.GenesisDoc, p2p *p2p.Client, logger log.Logger) (*HeaderSynceService, error) { +// NewHeaderSyncService returns a new HeaderSyncService. +func NewHeaderSyncService(ctx context.Context, store ds.TxnDatastore, conf config.NodeConfig, genesis *cmtypes.GenesisDoc, p2p *p2p.Client, logger log.Logger) (*HeaderSyncService, error) { if genesis == nil { return nil, errors.New("genesis doc cannot be nil") } @@ -61,7 +63,7 @@ func NewHeaderSynceService(ctx context.Context, store ds.TxnDatastore, conf conf return nil, fmt.Errorf("failed to initialize the header store: %w", err) } - return &HeaderSynceService{ + return &HeaderSyncService{ conf: conf, genesis: genesis, p2p: p2p, @@ -73,11 +75,11 @@ func NewHeaderSynceService(ctx context.Context, store ds.TxnDatastore, conf conf } // HeaderStore returns the headerstore of the HeaderSynceService -func (hSyncService *HeaderSynceService) HeaderStore() *goheaderstore.Store[*types.SignedHeader] { +func (hSyncService *HeaderSyncService) HeaderStore() *goheaderstore.Store[*types.SignedHeader] { return hSyncService.headerStore } -func (hSyncService *HeaderSynceService) initHeaderStoreAndStartSyncer(ctx context.Context, initial *types.SignedHeader) error { +func (hSyncService *HeaderSyncService) initHeaderStoreAndStartSyncer(ctx context.Context, initial *types.SignedHeader) error { if initial == nil { return fmt.Errorf("failed to initialize the headerstore and start syncer") } @@ -90,9 +92,9 @@ func (hSyncService *HeaderSynceService) initHeaderStoreAndStartSyncer(ctx contex return nil } -// Initialize header store if needed and broadcasts provided header. +// WriteToHeaderStoreAndBroadcast initializes header store if needed and broadcasts provided header. // Note: Only returns an error in case header store can't be initialized. Logs error if there's one while broadcasting. -func (hSyncService *HeaderSynceService) WriteToHeaderStoreAndBroadcast(ctx context.Context, signedHeader *types.SignedHeader) error { +func (hSyncService *HeaderSyncService) WriteToHeaderStoreAndBroadcast(ctx context.Context, signedHeader *types.SignedHeader) error { // For genesis header initialize the store and start the syncer if int64(signedHeader.Height()) == hSyncService.genesis.InitialHeight { if err := hSyncService.headerStore.Init(ctx, signedHeader); err != nil { @@ -111,12 +113,12 @@ func (hSyncService *HeaderSynceService) WriteToHeaderStoreAndBroadcast(ctx conte return nil } -func (hSyncService *HeaderSynceService) isInitialized() bool { +func (hSyncService *HeaderSyncService) isInitialized() bool { return hSyncService.headerStore.Height() > 0 } -// OnStart is a part of Service interface. -func (hSyncService *HeaderSynceService) Start() error { +// Start is a part of Service interface. +func (hSyncService *HeaderSyncService) Start() error { // have to do the initializations here to utilize the p2p node which is created on start ps := hSyncService.p2p.PubSub() @@ -203,8 +205,8 @@ func (hSyncService *HeaderSynceService) Start() error { return nil } -// OnStop is a part of Service interface. -func (hSyncService *HeaderSynceService) Stop() error { +// Stop is a part of Service interface. +func (hSyncService *HeaderSyncService) Stop() error { err := hSyncService.headerStore.Stop(hSyncService.ctx) err = multierr.Append(err, hSyncService.p2pServer.Stop(hSyncService.ctx)) err = multierr.Append(err, hSyncService.ex.Stop(hSyncService.ctx)) @@ -253,7 +255,8 @@ func newSyncer( return goheadersync.NewSyncer[*types.SignedHeader](ex, store, sub, opts...) } -func (hSyncService *HeaderSynceService) StartSyncer() error { +// StartSyncer starts the HeaderSyncService's syncer +func (hSyncService *HeaderSyncService) StartSyncer() error { hSyncService.syncerStatus.m.Lock() defer hSyncService.syncerStatus.m.Unlock() if hSyncService.syncerStatus.started { diff --git a/block/manager.go b/block/manager.go index e77935491..04ffad68b 100644 --- a/block/manager.go +++ b/block/manager.go @@ -562,6 +562,7 @@ func (m *Manager) getCommit(header types.Header) (*types.Commit, error) { }, nil } +// IsProposer returns whether or not the manager is a proposer func (m *Manager) IsProposer() (bool, error) { m.lastStateMtx.RLock() defer m.lastStateMtx.RUnlock() diff --git a/block/pending_blocks.go b/block/pending_blocks.go index f1c1305f8..258d0ad64 100644 --- a/block/pending_blocks.go +++ b/block/pending_blocks.go @@ -6,12 +6,13 @@ import ( "github.com/rollkit/rollkit/types" ) -// Maintains blocks that need to be published to DA layer +// PendingBlocks maintains blocks that need to be published to DA layer type PendingBlocks struct { pendingBlocks []*types.Block mtx *sync.RWMutex } +// NewPendingBlocks returns a new PendingBlocks struct func NewPendingBlocks() *PendingBlocks { return &PendingBlocks{ pendingBlocks: make([]*types.Block, 0), diff --git a/block/syncer_status.go b/block/syncer_status.go index da15efc62..d0f5b7ad9 100644 --- a/block/syncer_status.go +++ b/block/syncer_status.go @@ -4,8 +4,8 @@ import ( "sync" ) -// Used by header and block exchange service for keeping track of -// the status of the syncer in them. +// SyncerStatus is used by header and block exchange service for keeping track +// of the status of the syncer in them. type SyncerStatus struct { started bool m sync.RWMutex diff --git a/config/defaults.go b/config/defaults.go index 52ffd65dc..15d87947c 100644 --- a/config/defaults.go +++ b/config/defaults.go @@ -9,7 +9,8 @@ import ( const ( // DefaultListenAddress is a default listen address for P2P client. DefaultListenAddress = "/ip4/0.0.0.0/tcp/7676" - Version = "0.4.0" + // Version is the current rollkit version and is used for checking RPC compatibility?? + Version = "0.4.0" ) // DefaultNodeConfig keeps default values of NodeConfig diff --git a/da/celestia/mock/server.go b/da/celestia/mock/server.go index 49cc8b82f..711a4a7c2 100644 --- a/da/celestia/mock/server.go +++ b/da/celestia/mock/server.go @@ -19,6 +19,7 @@ import ( "github.com/rollkit/rollkit/types" ) +// ErrorCode represents RPC error code. type ErrorCode int type respError struct { @@ -27,6 +28,7 @@ type respError struct { Meta json.RawMessage `json:"meta,omitempty"` } +// Error returns error message string. func (e *respError) Error() string { if e.Code >= -32768 && e.Code <= -32000 { return fmt.Sprintf("RPC error (%d): %s", e.Code, e.Message) diff --git a/da/da.go b/da/da.go index 89b6a986c..49f2d2a65 100644 --- a/da/da.go +++ b/da/da.go @@ -15,8 +15,10 @@ var ( ErrDataNotFound = errors.New("data not found") // ErrNamespaceNotFound is used to indicate that the block contains data, but not for the requested namespace. ErrNamespaceNotFound = errors.New("namespace not found in data") - ErrBlobNotFound = errors.New("blob: not found") - ErrEDSNotFound = errors.New("eds not found") + // ErrBlobNotFound is used to indicate that the blob was not found. + ErrBlobNotFound = errors.New("blob: not found") + // ErrEDSNotFound is used to indicate that the EDS was not found. + ErrEDSNotFound = errors.New("eds not found") ) // StatusCode is a type for DA layer return status. diff --git a/da/registry/registry_test.go b/da/registry/registry_test.go index a5f6f3ce7..9636cc2c6 100644 --- a/da/registry/registry_test.go +++ b/da/registry/registry_test.go @@ -9,7 +9,7 @@ import ( "github.com/rollkit/rollkit/da/mock" ) -func TestRegistery(t *testing.T) { +func TestRegistry(t *testing.T) { assert := assert.New(t) expected := []string{"mock", "grpc", "celestia"} diff --git a/mempool/clist/clist_test.go b/mempool/clist/clist_test.go index 686a3f9a4..02ec4caf6 100644 --- a/mempool/clist/clist_test.go +++ b/mempool/clist/clist_test.go @@ -68,8 +68,6 @@ func TestSmall(t *testing.T) { // This test is quite hacky because it relies on SetFinalizer // which isn't guaranteed to run at all. -// -//nolint:unused,deadcode func _TestGCFifo(t *testing.T) { if runtime.GOARCH != "amd64" { t.Skipf("Skipping on non-amd64 machine") @@ -118,8 +116,6 @@ func _TestGCFifo(t *testing.T) { // This test is quite hacky because it relies on SetFinalizer // which isn't guaranteed to run at all. -// -//nolint:unused,deadcode func _TestGCRandom(t *testing.T) { if runtime.GOARCH != "amd64" { t.Skipf("Skipping on non-amd64 machine") diff --git a/mempool/v1/mempool.go b/mempool/v1/mempool.go index c95caa6c6..1e6b08e19 100644 --- a/mempool/v1/mempool.go +++ b/mempool/v1/mempool.go @@ -336,7 +336,7 @@ func (txmp *TxMempool) allEntriesSorted() []*WrappedTx { func (txmp *TxMempool) ReapMaxBytesMaxGas(maxBytes, maxGas int64) types.Txs { var totalGas, totalBytes int64 - keep := make([]types.Tx, 0, len(txmp.allEntriesSorted())) + var keep []types.Tx for _, w := range txmp.allEntriesSorted() { // N.B. When computing byte size, we need to include the overhead for // encoding as protobuf to send to the application. This actually overestimates it @@ -369,7 +369,7 @@ func (txmp *TxMempool) TxsFront() *clist.CElement { return txmp.txs.Front() } // The result may have fewer than max elements (possibly zero) if the mempool // does not have that many transactions available. func (txmp *TxMempool) ReapMaxTxs(max int) types.Txs { - var keep []types.Tx //nolint:prealloc + var keep []types.Tx for _, w := range txmp.allEntriesSorted() { if max >= 0 && len(keep) >= max { diff --git a/node/full.go b/node/full.go index 4dbba6d04..32937a170 100644 --- a/node/full.go +++ b/node/full.go @@ -64,7 +64,7 @@ type FullNode struct { eventBus *cmtypes.EventBus dalc da.DataAvailabilityLayerClient p2pClient *p2p.Client - hSyncService *block.HeaderSynceService + hSyncService *block.HeaderSyncService bSyncService *block.BlockSyncService // TODO(tzdybal): consider extracting "mempool reactor" Mempool mempool.Mempool @@ -217,8 +217,8 @@ func initMempool(logger log.Logger, proxyApp proxy.AppConns) *mempoolv1.TxMempoo return mempool } -func initHeaderSyncService(ctx context.Context, mainKV ds.TxnDatastore, nodeConfig config.NodeConfig, genesis *cmtypes.GenesisDoc, p2pClient *p2p.Client, logger log.Logger) (*block.HeaderSynceService, error) { - headerSyncService, err := block.NewHeaderSynceService(ctx, mainKV, nodeConfig, genesis, p2pClient, logger.With("module", "HeaderSyncService")) +func initHeaderSyncService(ctx context.Context, mainKV ds.TxnDatastore, nodeConfig config.NodeConfig, genesis *cmtypes.GenesisDoc, p2pClient *p2p.Client, logger log.Logger) (*block.HeaderSyncService, error) { + headerSyncService, err := block.NewHeaderSyncService(ctx, mainKV, nodeConfig, genesis, p2pClient, logger.With("module", "HeaderSyncService")) if err != nil { return nil, fmt.Errorf("error while initializing HeaderSyncService: %w", err) } diff --git a/node/full_client.go b/node/full_client.go index 68ed322a6..9ccf8cd6a 100644 --- a/node/full_client.go +++ b/node/full_client.go @@ -60,6 +60,10 @@ func NewFullClient(node *FullNode) *FullClient { } } +// GetClient returns a new RPC client for the full node. +// +// TODO: should this be NewRPPCClient? Or should we add the client as a field of +// the FullNode so that it is just created once? func (n *FullNode) GetClient() rpcclient.Client { return NewFullClient(n) } @@ -796,11 +800,13 @@ func (c *FullClient) CheckTx(ctx context.Context, tx cmtypes.Tx) (*ctypes.Result return &ctypes.ResultCheckTx{ResponseCheckTx: *res}, nil } +// Header returns a cometbft ResultsHeader for the FullClient func (c *FullClient) Header(ctx context.Context, height *int64) (*ctypes.ResultHeader, error) { blockMeta := c.getBlockMeta(*height) return &ctypes.ResultHeader{Header: &blockMeta.Header}, nil } +// HeaderByHash loads the block for the provided hash and returns the header func (c *FullClient) HeaderByHash(ctx context.Context, hash cmbytes.HexBytes) (*ctypes.ResultHeader, error) { // N.B. The hash parameter is HexBytes so that the reflective parameter // decoding logic in the HTTP service will correctly translate from JSON. diff --git a/node/full_client_test.go b/node/full_client_test.go index d4d7826fe..7d6d93834 100644 --- a/node/full_client_test.go +++ b/node/full_client_test.go @@ -1189,3 +1189,27 @@ func TestHealth(t *testing.T) { assert.Nil(err) assert.Empty(resultHealth) } + +func TestNetInfo(t *testing.T) { + assert := assert.New(t) + require := require.New(t) + + mockApp, rpc := getRPC(t) + mockApp.On("BeginBlock", mock.Anything).Return(abci.ResponseBeginBlock{}) + mockApp.On("CheckTx", mock.Anything).Return(abci.ResponseCheckTx{}) + mockApp.On("EndBlock", mock.Anything).Return(abci.ResponseEndBlock{}) + mockApp.On("Commit", mock.Anything).Return(abci.ResponseCommit{}) + + err := rpc.node.Start() + require.NoError(err) + defer func() { + err := rpc.node.Stop() + require.NoError(err) + }() + + netInfo, err := rpc.NetInfo(context.Background()) + require.NoError(err) + assert.NotNil(netInfo) + assert.True(netInfo.Listening) + assert.Equal(0, len(netInfo.Peers)) +} diff --git a/node/test_helpers.go b/node/helpers.go similarity index 87% rename from node/test_helpers.go rename to node/helpers.go index b1142125d..e3cfc603c 100644 --- a/node/test_helpers.go +++ b/node/helpers.go @@ -8,7 +8,7 @@ import ( testutils "github.com/celestiaorg/utils/test" "github.com/cometbft/cometbft/crypto/ed25519" - "github.com/cometbft/cometbft/p2p" + p2p "github.com/cometbft/cometbft/p2p" cmtypes "github.com/cometbft/cometbft/types" "github.com/libp2p/go-libp2p/core/crypto" @@ -16,26 +16,35 @@ import ( "github.com/rollkit/rollkit/types" ) +// Source is an enum representing different sources of height type Source int const ( + // Header is the source of height from the header service Header Source = iota + // Block is the source of height from the block service Block + // Store is the source of height from the block manager store Store ) var genesisValidatorKey = ed25519.GenPrivKey() +// MockTester is a mock testing.T type MockTester struct { t *testing.T } +// Fail is used to fail the test func (m MockTester) Fail() {} +// FailNow is used to fail the test immediately func (m MockTester) FailNow() {} +// Logf is used to log a message to the test logger func (m MockTester) Logf(format string, args ...interface{}) {} +// Errorf is used to log an error to the test logger func (m MockTester) Errorf(format string, args ...interface{}) {} func waitForFirstBlock(node Node, source Source) error { diff --git a/node/light.go b/node/light.go index b5dd57d9c..3b977c63e 100644 --- a/node/light.go +++ b/node/light.go @@ -21,6 +21,7 @@ import ( var _ Node = &LightNode{} +// LightNode is a rollup node that only needs the header service type LightNode struct { service.BaseService @@ -28,12 +29,15 @@ type LightNode struct { proxyApp proxy.AppConns - hSyncService *block.HeaderSynceService + hSyncService *block.HeaderSyncService ctx context.Context cancel context.CancelFunc } +// GetClient returns a new rpcclient for the light node +// TODO: this should be renamed to NewRPCClient or some New variant since it is +// creating a new item func (ln *LightNode) GetClient() rpcclient.Client { return NewLightClient(ln) } @@ -62,7 +66,7 @@ func newLightNode( return nil, err } - headerSyncService, err := block.NewHeaderSynceService(ctx, datastore, conf, genesis, client, logger.With("module", "HeaderSyncService")) + headerSyncService, err := block.NewHeaderSyncService(ctx, datastore, conf, genesis, client, logger.With("module", "HeaderSyncService")) if err != nil { return nil, fmt.Errorf("error while initializing HeaderSyncService: %w", err) } @@ -97,6 +101,7 @@ func (n *LightNode) Cancel() { n.cancel() } +// OnStart starts the P2P and HeaderSync services func (ln *LightNode) OnStart() error { if err := ln.P2P.Start(ln.ctx); err != nil { return err @@ -109,6 +114,7 @@ func (ln *LightNode) OnStart() error { return nil } +// OnStop stops the light node func (ln *LightNode) OnStop() { ln.Logger.Info("halting light node...") ln.cancel() diff --git a/node/light_client.go b/node/light_client.go index d48ccab54..526270b01 100644 --- a/node/light_client.go +++ b/node/light_client.go @@ -11,11 +11,13 @@ import ( var _ rpcclient.Client = &LightClient{} +// LightClient is a Client interface for the LightNode type LightClient struct { types.EventBus node *LightNode } +// NewLightClient returns a new LightClient for the LightNode func NewLightClient(node *LightNode) *LightClient { return &LightClient{ node: node, @@ -179,10 +181,12 @@ func (c *LightClient) CheckTx(ctx context.Context, tx types.Tx) (*ctypes.ResultC panic("Not implemented") } +// Header satisfies the client interface but is not implemented func (c *LightClient) Header(ctx context.Context, height *int64) (*ctypes.ResultHeader, error) { panic("Not implemented") } +// HeaderByHash satisfies the client interface but is not implemented func (c *LightClient) HeaderByHash(ctx context.Context, hash cmbytes.HexBytes) (*ctypes.ResultHeader, error) { panic("Not implemented") } diff --git a/node/node.go b/node/node.go index 4d77d4443..3227ea05c 100644 --- a/node/node.go +++ b/node/node.go @@ -13,6 +13,7 @@ import ( "github.com/rollkit/rollkit/config" ) +// Node is the interface for a rollup node type Node interface { Start() error GetClient() rpcclient.Client @@ -21,8 +22,7 @@ type Node interface { Cancel() } -// Add Defaults? - +// NewNode returns a new Full or Light Node based on the config func NewNode( ctx context.Context, conf config.NodeConfig, diff --git a/p2p/client.go b/p2p/client.go index e08b66d65..fe49c52f9 100644 --- a/p2p/client.go +++ b/p2p/client.go @@ -184,6 +184,7 @@ func (c *Client) PubSub() *pubsub.PubSub { return c.ps } +// ConnectionGater returns the client's connection gater func (c *Client) ConnectionGater() *conngater.BasicConnectionGater { return c.gater } diff --git a/rpc/json/test_helpers.go b/rpc/json/helpers_test.go similarity index 100% rename from rpc/json/test_helpers.go rename to rpc/json/helpers_test.go diff --git a/state/executor.go b/state/executor.go index 13db53ee7..aff20309d 100644 --- a/state/executor.go +++ b/state/executor.go @@ -22,7 +22,10 @@ import ( abciconv "github.com/rollkit/rollkit/types/abci" ) +// ErrEmptyValSetGenerated is returned when applying the validator changes would result in empty set. var ErrEmptyValSetGenerated = errors.New("applying the validator changes would result in empty set") + +// ErrAddingValidatorToBased is returned when trying to add a validator to an empty validator set. var ErrAddingValidatorToBased = errors.New("cannot add validators to empty validator set") // BlockExecutor creates and applies blocks and maintains state. @@ -260,6 +263,7 @@ func (e *BlockExecutor) commit(ctx context.Context, state types.State, block *ty return resp.Data, uint64(resp.RetainHeight), err } +// Validate validates the state and the block for the executor func (e *BlockExecutor) Validate(state types.State, block *types.Block) error { err := block.ValidateBasic() if err != nil { diff --git a/test/log/loggers.go b/test/log/loggers.go index dbb6c05ad..721cad578 100644 --- a/test/log/loggers.go +++ b/test/log/loggers.go @@ -26,14 +26,14 @@ func TempLogFileName(t *testing.T, suffix string) string { return strings.ReplaceAll(t.Name(), "/", "_") + suffix + ".log" } -// NewLogger create a Logger using the name of the test as the filename. +// NewFileLogger create a Logger using the name of the test as the filename. func NewFileLogger(t *testing.T) *FileLogger { // Use the test name but strip out any slashes since they are not // allowed in filenames. return NewFileLoggerCustom(t, TempLogFileName(t, "")) } -// NewLoggerCustom create a Logger using the given filename. +// NewFileLoggerCustom create a Logger using the given filename. func NewFileLoggerCustom(t *testing.T, fileName string) *FileLogger { logFile, err := os.CreateTemp("", fileName) if err != nil { diff --git a/types/block.go b/types/block.go index a40e92024..19882bb88 100644 --- a/types/block.go +++ b/types/block.go @@ -11,6 +11,7 @@ import ( cmtypes "github.com/cometbft/cometbft/types" ) +// NamespaceID is a unique identifier of a namespace. type NamespaceID [8]byte // Version captures the consensus rules for processing a block in the blockchain, @@ -82,6 +83,7 @@ func (c *Commit) ToABCICommit(height uint64, hash Hash) *cmtypes.Commit { return &tmCommit } +// GetCommitHash returns hash of the commit. func (c *Commit) GetCommitHash(header *Header, proposerAddress []byte) []byte { lastABCICommit := c.ToABCICommit(header.Height(), header.Hash()) // Rollkit does not support a multi signature scheme so there can only be one signature @@ -124,35 +126,43 @@ func (b *Block) ValidateBasic() error { return nil } +// New returns a new Block. func (b *Block) New() *Block { return new(Block) } +// IsZero returns true if the block is nil. func (b *Block) IsZero() bool { return b == nil } +// ChainID returns chain ID of the block. func (b *Block) ChainID() string { return b.SignedHeader.ChainID() + "-block" } +// Height returns height of the block. func (b *Block) Height() uint64 { return b.SignedHeader.Height() } +// LastHeader returns last header hash of the block. func (b *Block) LastHeader() Hash { return b.SignedHeader.LastHeader() } +// Time returns time of the block. func (b *Block) Time() time.Time { return b.SignedHeader.Time() } +// Verify verifies the block. func (b *Block) Verify(*Block) error { //TODO: Update with new header verify method return nil } +// Validate performs basic validation of a block. func (b *Block) Validate() error { return b.ValidateBasic() } diff --git a/types/header.go b/types/header.go index c1a9e52d1..04438fa00 100644 --- a/types/header.go +++ b/types/header.go @@ -9,6 +9,7 @@ import ( "github.com/celestiaorg/go-header" ) +// Hash is a 32-byte array which is used to represent a hash result. type Hash = header.Hash // BaseHeader contains the most basic data of a header @@ -54,31 +55,37 @@ type Header struct { NextAggregatorsHash Hash } +// New creates a new Header. func (h *Header) New() *Header { return new(Header) } +// IsZero returns true if the header is nil. func (h *Header) IsZero() bool { return h == nil } +// ChainID returns chain ID of the header. func (h *Header) ChainID() string { return h.BaseHeader.ChainID } +// Height returns height of the header. func (h *Header) Height() uint64 { return h.BaseHeader.Height } +// LastHeader returns last header hash of the header. func (h *Header) LastHeader() Hash { return h.LastHeaderHash[:] } -// Returns unix time with nanosecond precision +// Time returns timestamp as unix time with nanosecond precision func (h *Header) Time() time.Time { return time.Unix(0, int64(h.BaseHeader.Time)) } +// Verify verifies the header. func (h *Header) Verify(untrstH *Header) error { // perform actual verification if untrstH.Height() == h.Height()+1 { @@ -103,6 +110,7 @@ func (h *Header) Verify(untrstH *Header) error { return nil } +// Validate performs basic validation of a header. func (h *Header) Validate() error { return h.ValidateBasic() } diff --git a/types/signed_header.go b/types/signed_header.go index 4d0d1c25d..b799919ec 100644 --- a/types/signed_header.go +++ b/types/signed_header.go @@ -19,21 +19,31 @@ type SignedHeader struct { Validators *cmtypes.ValidatorSet } +// New creates a new SignedHeader. func (sh *SignedHeader) New() *SignedHeader { return new(SignedHeader) } +// IsZero returns true if the SignedHeader is nil func (sh *SignedHeader) IsZero() bool { return sh == nil } var ( - ErrNonAdjacentHeaders = errors.New("non-adjacent headers") - ErrNoProposerAddress = errors.New("no proposer address") + // ErrNonAdjacentHeaders is returned when the headers are not adjacent. + ErrNonAdjacentHeaders = errors.New("non-adjacent headers") + + // ErrNoProposerAddress is returned when the proposer address is not set. + ErrNoProposerAddress = errors.New("no proposer address") + + // ErrLastHeaderHashMismatch is returned when the last header hash doesn't match. ErrLastHeaderHashMismatch = errors.New("last header hash mismatch") + + // ErrLastCommitHashMismatch is returned when the last commit hash doesn't match. ErrLastCommitHashMismatch = errors.New("last commit hash mismatch") ) +// Verify verifies the signed header. func (sh *SignedHeader) Verify(untrstH *SignedHeader) error { // go-header ensures untrustH already passed ValidateBasic. if err := sh.Header.Verify(&untrstH.Header); err != nil { @@ -75,7 +85,11 @@ func (sh *SignedHeader) Verify(untrstH *SignedHeader) error { } var ( - ErrAggregatorSetHashMismatch = errors.New("aggregator set hash in signed header and hash of validator set do not match") + // ErrAggregatorSetHashMismatch is returned when the aggregator set hash + // in the signed header doesn't match the hash of the validator set. + ErrAggregatorSetHashMismatch = errors.New("aggregator set hash in signed header and hash of validator set do not match") + // ErrSignatureVerificationFailed is returned when the signature + // verification fails ErrSignatureVerificationFailed = errors.New("signature verification failed") ) diff --git a/types/tx.go b/types/tx.go index 22e821025..564ae3bbc 100644 --- a/types/tx.go +++ b/types/tx.go @@ -68,6 +68,7 @@ func (txs Txs) ToTxsWithISRs(intermediateStateRoots IntermediateStateRoots) ([]p return txsWithISRs, nil } +// TxsWithISRsToShares converts a slice of TxWithISRs to a slice of shares. func TxsWithISRsToShares(txsWithISRs []pb.TxWithISRs) (txShares []shares.Share, err error) { byteSlices := make([][]byte, len(txsWithISRs)) for i, txWithISR := range txsWithISRs { @@ -81,6 +82,8 @@ func TxsWithISRsToShares(txsWithISRs []pb.TxWithISRs) (txShares []shares.Share, return txShares, err } +// SharesToPostableBytes converts a slice of shares to a slice of bytes that can +// be posted to the blockchain. func SharesToPostableBytes(txShares []shares.Share) (postableData []byte, err error) { for i := 0; i < len(txShares); i++ { raw, err := txShares[i].RawDataWithReserved() @@ -92,6 +95,8 @@ func SharesToPostableBytes(txShares []shares.Share) (postableData []byte, err er return postableData, nil } +// PostableBytesToShares converts a slice of bytes that can be posted to the +// blockchain to a slice of shares func PostableBytesToShares(postableData []byte) (txShares []shares.Share, err error) { css := shares.NewCompactShareSplitterWithIsCompactFalse(appns.TxNamespace, appconsts.ShareVersionZero) err = css.WriteWithNoReservedBytes(postableData) @@ -102,6 +107,7 @@ func PostableBytesToShares(postableData []byte) (txShares []shares.Share, err er return shares, err } +// SharesToTxsWithISRs converts a slice of shares to a slice of TxWithISRs. func SharesToTxsWithISRs(txShares []shares.Share) (txsWithISRs []pb.TxWithISRs, err error) { byteSlices, err := shares.ParseCompactShares(txShares) if err != nil { diff --git a/types/tx_test.go b/types/tx_test.go index 5ad26d3f7..88031ac3b 100644 --- a/types/tx_test.go +++ b/types/tx_test.go @@ -80,8 +80,8 @@ func TestTxWithISRSerializationOutOfContextRoundtrip(t *testing.T) { assert.Equal(txsWithISRs, newTxsWithISRs) for i := 0; i < 1000; i++ { - numShares := rand.Int() % len(txShares) //nolint: gosec - startShare := rand.Int() % (len(txShares) - numShares + 1) //nolint: gosec + numShares := rand.Int() % len(txShares) //nolint:gosec + startShare := rand.Int() % (len(txShares) - numShares + 1) //nolint:gosec newTxsWithISRs, err := SharesToTxsWithISRs(txShares[startShare : startShare+numShares]) require.NoError(err) assert.True(checkSubArray(txsWithISRs, newTxsWithISRs)) diff --git a/types/utils.go b/types/utils.go index 64ae46e4c..11e6a8221 100644 --- a/types/utils.go +++ b/types/utils.go @@ -8,14 +8,18 @@ import ( cmtypes "github.com/cometbft/cometbft/types" ) +// TestChainID is a constant used for testing purposes. It represents a mock chain ID. const TestChainID = "test" -// TODO: accept argument for number of validators / proposer index +// GetRandomValidatorSet returns the validator set from +// GetRandomValidatorSetWithPrivKey without the private key. func GetRandomValidatorSet() *cmtypes.ValidatorSet { valSet, _ := GetRandomValidatorSetWithPrivKey() return valSet } +// GetRandomValidatorSetWithPrivKey returns a validator set with a single +// validator func GetRandomValidatorSetWithPrivKey() (*cmtypes.ValidatorSet, ed25519.PrivKey) { privKey := ed25519.GenPrivKey() pubKey := privKey.PubKey() @@ -27,6 +31,7 @@ func GetRandomValidatorSetWithPrivKey() (*cmtypes.ValidatorSet, ed25519.PrivKey) }, privKey } +// GetRandomBlock returns a block with random data func GetRandomBlock(height uint64, nTxs int) *Block { header := GetRandomHeader() header.BaseHeader.Height = height @@ -58,6 +63,7 @@ func GetRandomBlock(height uint64, nTxs int) *Block { return block } +// GetRandomHeader returns a header with random fields and current time func GetRandomHeader() Header { return Header{ BaseHeader: BaseHeader{ @@ -80,6 +86,8 @@ func GetRandomHeader() Header { } } +// GetRandomNextHeader returns a header with random data and height of +1 from +// the provided Header func GetRandomNextHeader(header Header) Header { nextHeader := GetRandomHeader() nextHeader.BaseHeader.Height = header.Height() + 1 @@ -91,6 +99,7 @@ func GetRandomNextHeader(header Header) Header { return nextHeader } +// GetRandomSignedHeader returns a signed header with random data func GetRandomSignedHeader() (*SignedHeader, ed25519.PrivKey, error) { valSet, privKey := GetRandomValidatorSetWithPrivKey() signedHeader := &SignedHeader{ @@ -108,6 +117,8 @@ func GetRandomSignedHeader() (*SignedHeader, ed25519.PrivKey, error) { return signedHeader, privKey, nil } +// GetRandomNextSignedHeader returns a signed header with random data and height of +1 from +// the provided signed header func GetRandomNextSignedHeader(signedHeader *SignedHeader, privKey ed25519.PrivKey) (*SignedHeader, error) { valSet := signedHeader.Validators newSignedHeader := &SignedHeader{ @@ -125,11 +136,14 @@ func GetRandomNextSignedHeader(signedHeader *SignedHeader, privKey ed25519.PrivK return newSignedHeader, nil } +// GetRandomTx returns a transaction with a random size between 100 and 200 +// bytes. func GetRandomTx() Tx { size := rand.Int()%100 + 100 //nolint:gosec return Tx(GetRandomBytes(size)) } +// GetRandomBytes returns a byte slice of random bytes of length n. func GetRandomBytes(n int) []byte { data := make([]byte, n) _, _ = rand.Read(data) //nolint:gosec,staticcheck