@@ -3,20 +3,28 @@ package block
33import (
44 "bytes"
55 "context"
6+ "crypto/rand"
67 "errors"
78 "fmt"
89 "os"
910 "strconv"
11+ "sync"
1012 "testing"
1113 "time"
1214
15+ abci "github.com/cometbft/cometbft/abci/types"
16+ cfg "github.com/cometbft/cometbft/config"
1317 cmcrypto "github.com/cometbft/cometbft/crypto"
1418 "github.com/cometbft/cometbft/crypto/ed25519"
1519 "github.com/cometbft/cometbft/crypto/secp256k1"
20+ "github.com/cometbft/cometbft/libs/log"
21+ cmproto "github.com/cometbft/cometbft/proto/tendermint/types"
22+ "github.com/cometbft/cometbft/proxy"
1623 cmtypes "github.com/cometbft/cometbft/types"
1724 ds "github.com/ipfs/go-datastore"
1825 "github.com/libp2p/go-libp2p/core/crypto"
1926 "github.com/stretchr/testify/assert"
27+ "github.com/stretchr/testify/mock"
2028 "github.com/stretchr/testify/require"
2129
2230 goDA "github.com/rollkit/go-da"
@@ -25,6 +33,8 @@ import (
2533 "github.com/rollkit/rollkit/config"
2634 "github.com/rollkit/rollkit/da"
2735 mockda "github.com/rollkit/rollkit/da/mock"
36+ "github.com/rollkit/rollkit/mempool"
37+ "github.com/rollkit/rollkit/state"
2838 "github.com/rollkit/rollkit/store"
2939 test "github.com/rollkit/rollkit/test/log"
3040 "github.com/rollkit/rollkit/test/mocks"
@@ -549,6 +559,121 @@ func Test_publishBlock_ManagerNotProposer(t *testing.T) {
549559 require .ErrorIs (err , ErrNotProposer )
550560}
551561
562+ func TestManager_publishBlock (t * testing.T ) {
563+ mockStore := new (mocks.Store )
564+ mockLogger := new (test.MockLogger )
565+ assert := assert .New (t )
566+ require := require .New (t )
567+
568+ logger := log .TestingLogger ()
569+
570+ var mockAppHash []byte
571+ _ , err := rand .Read (mockAppHash [:])
572+ require .NoError (err )
573+
574+ app := & mocks.Application {}
575+ app .On ("CheckTx" , mock .Anything , mock .Anything ).Return (& abci.ResponseCheckTx {}, nil )
576+ app .On ("Commit" , mock .Anything , mock .Anything ).Return (& abci.ResponseCommit {}, nil )
577+ app .On ("PrepareProposal" , mock .Anything , mock .Anything ).Return (func (_ context.Context , req * abci.RequestPrepareProposal ) (* abci.ResponsePrepareProposal , error ) {
578+ return & abci.ResponsePrepareProposal {
579+ Txs : req .Txs ,
580+ }, nil
581+ })
582+ app .On ("ProcessProposal" , mock .Anything , mock .Anything ).Return (& abci.ResponseProcessProposal {Status : abci .ResponseProcessProposal_ACCEPT }, nil )
583+ app .On ("FinalizeBlock" , mock .Anything , mock .Anything ).Return (
584+ func (_ context.Context , req * abci.RequestFinalizeBlock ) (* abci.ResponseFinalizeBlock , error ) {
585+ txResults := make ([]* abci.ExecTxResult , len (req .Txs ))
586+ for idx := range req .Txs {
587+ txResults [idx ] = & abci.ExecTxResult {
588+ Code : abci .CodeTypeOK ,
589+ }
590+ }
591+
592+ return & abci.ResponseFinalizeBlock {
593+ TxResults : txResults ,
594+ AppHash : mockAppHash ,
595+ }, nil
596+ },
597+ )
598+
599+ client , err := proxy .NewLocalClientCreator (app ).NewABCIClient ()
600+ require .NoError (err )
601+ require .NotNil (client )
602+
603+ vKey := ed25519 .GenPrivKey ()
604+ validators := []* cmtypes.Validator {
605+ {
606+ Address : vKey .PubKey ().Address (),
607+ PubKey : vKey .PubKey (),
608+ VotingPower : int64 (100 ),
609+ ProposerPriority : int64 (1 ),
610+ },
611+ }
612+
613+ lastState := types.State {}
614+ lastState .ConsensusParams .Block = & cmproto.BlockParams {}
615+ lastState .ConsensusParams .Block .MaxBytes = 100
616+ lastState .ConsensusParams .Block .MaxGas = 100000
617+ lastState .ConsensusParams .Abci = & cmproto.ABCIParams {VoteExtensionsEnableHeight : 0 }
618+ lastState .Validators = cmtypes .NewValidatorSet (validators )
619+ lastState .NextValidators = cmtypes .NewValidatorSet (validators )
620+ lastState .LastValidators = cmtypes .NewValidatorSet (validators )
621+
622+ mpool := mempool .NewCListMempool (cfg .DefaultMempoolConfig (), proxy .NewAppConnMempool (client , proxy .NopMetrics ()), 0 )
623+ executor := state .NewBlockExecutor (vKey .PubKey ().Address (), "test" , mpool , proxy .NewAppConnConsensus (client , proxy .NopMetrics ()), nil , 100 , logger , state .NopMetrics ())
624+
625+ signingKey , err := types .PrivKeyToSigningKey (vKey )
626+ require .NoError (err )
627+ m := & Manager {
628+ lastState : lastState ,
629+ lastStateMtx : new (sync.RWMutex ),
630+ blockCache : NewBlockCache (),
631+ executor : executor ,
632+ store : mockStore ,
633+ logger : mockLogger ,
634+ genesis : & cmtypes.GenesisDoc {
635+ ChainID : "myChain" ,
636+ InitialHeight : 1 ,
637+ AppHash : []byte ("app hash" ),
638+ },
639+ conf : config.BlockManagerConfig {
640+ BlockTime : time .Second ,
641+ LazyAggregator : false ,
642+ },
643+ isProposer : true ,
644+ proposerKey : signingKey ,
645+ metrics : NopMetrics (),
646+ }
647+
648+ t .Run ("height should not be updated if saving block responses fails" , func (t * testing.T ) {
649+ mockStore .On ("Height" ).Return (uint64 (0 ))
650+ signature := types .Signature ([]byte {1 , 1 , 1 })
651+ block , err := executor .CreateBlock (0 , & signature , abci.ExtendedCommitInfo {}, []byte {}, lastState )
652+ require .NoError (err )
653+ require .NotNil (block )
654+ assert .Equal (uint64 (0 ), block .Height ())
655+ dataHash , err := block .Data .Hash ()
656+ assert .NoError (err )
657+ block .SignedHeader .DataHash = dataHash
658+
659+ // Update the signature on the block to current from last
660+ voteBytes := block .SignedHeader .Header .MakeCometBFTVote ()
661+ signature , _ = vKey .Sign (voteBytes )
662+ block .SignedHeader .Signature = signature
663+ block .SignedHeader .Validators = lastState .Validators
664+
665+ mockStore .On ("GetBlock" , mock .Anything , uint64 (1 )).Return (block , nil ).Once ()
666+ mockStore .On ("SaveBlock" , mock .Anything , block , mock .Anything ).Return (nil ).Once ()
667+ mockStore .On ("SaveBlockResponses" , mock .Anything , uint64 (0 ), mock .Anything ).Return (errors .New ("failed to save block responses" )).Once ()
668+
669+ ctx := context .Background ()
670+ err = m .publishBlock (ctx )
671+ assert .ErrorContains (err , "failed to save block responses" )
672+
673+ mockStore .AssertExpectations (t )
674+ })
675+ }
676+
552677func TestManager_getRemainingSleep (t * testing.T ) {
553678 tests := []struct {
554679 name string
0 commit comments