From 55f7f309d6c7505768b9ec5b699181d217dff843 Mon Sep 17 00:00:00 2001 From: blazejkrzak Date: Wed, 11 Aug 2021 14:35:17 +0200 Subject: [PATCH 01/33] Test suite: New() for pandora.go --- consensus/pandora/pandora.go | 54 ++++++++++---------- consensus/pandora/pandora_test.go | 83 +++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 27 deletions(-) diff --git a/consensus/pandora/pandora.go b/consensus/pandora/pandora.go index 3713c853c745..854ad2769474 100644 --- a/consensus/pandora/pandora.go +++ b/consensus/pandora/pandora.go @@ -127,6 +127,33 @@ func (p *Pandora) Start(chain consensus.ChainHeaderReader) { }() } +// Close closes the exit channel to notify all backend threads exiting. +func (p *Pandora) Close() error { + if p.cancel != nil { + defer p.cancel() + } + p.scope.Close() + return nil +} + +func (p *Pandora) APIs(chain consensus.ChainHeaderReader) []rpc.API { + // In order to ensure backward compatibility, we exposes ethash RPC APIs + // to both eth and ethash namespaces. + return []rpc.API{ + { + Namespace: "eth", + Version: "1.0", + Service: &API{p}, + Public: true, + }, + } +} + +// SubscribeToUpdateSealHashEvent when sealHash updates it will notify worker.go +func (p *Pandora) SubscribeToUpdateSealHashEvent(ch chan<- SealHashUpdate) event.Subscription { + return p.scope.Track(p.updatedSealHash.Subscribe(ch)) +} + // getCurrentBlock get current block func (p *Pandora) getCurrentBlock() *types.Block { p.currentBlockMu.RLock() @@ -276,30 +303,3 @@ func (p *Pandora) run(done <-chan struct{}) { } } } - -// Close closes the exit channel to notify all backend threads exiting. -func (p *Pandora) Close() error { - if p.cancel != nil { - defer p.cancel() - } - p.scope.Close() - return nil -} - -func (p *Pandora) APIs(chain consensus.ChainHeaderReader) []rpc.API { - // In order to ensure backward compatibility, we exposes ethash RPC APIs - // to both eth and ethash namespaces. - return []rpc.API{ - { - Namespace: "eth", - Version: "1.0", - Service: &API{p}, - Public: true, - }, - } -} - -// SubscribeToUpdateSealHashEvent when sealHash updates it will notify worker.go -func (p *Pandora) SubscribeToUpdateSealHashEvent(ch chan<- SealHashUpdate) event.Subscription { - return p.scope.Track(p.updatedSealHash.Subscribe(ch)) -} diff --git a/consensus/pandora/pandora_test.go b/consensus/pandora/pandora_test.go index 68e6887bf89c..32408cbd5a25 100644 --- a/consensus/pandora/pandora_test.go +++ b/consensus/pandora/pandora_test.go @@ -1 +1,84 @@ package pandora + +import ( + "context" + "fmt" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rpc" + "github.com/stretchr/testify/assert" + "testing" + "time" +) + +var ( + dummyRpcFunc = DialRPCFn(func(endpoint string) (rpcClient *rpc.Client, err error) { + return rpc.Dial(endpoint) + }) +) + +func Test_New(t *testing.T) { + pandoraEngine := createDummyPandora(t) + assert.IsType(t, &Pandora{}, pandoraEngine) + + t.Run("should have default settings", func(t *testing.T) { + assert.Equal(t, ¶ms.PandoraConfig{ + GenesisStartTime: DefaultGenesisStartTime, + SlotsPerEpoch: DefaultSlotsPerEpoch, + SlotTimeDuration: DefaultSlotTimeDuration, + }, pandoraEngine.config, + ) + }) +} + +func TestPandora_Start(t *testing.T) { + pandoraEngine := createDummyPandora(t) + dummyEndpoint := "https://some.endpoint" + // TODO: in my opinion Start() should return err when failure is present + t.Run("should not start with empty endpoint", func(t *testing.T) { + pandoraEngine.Start(nil) + assert.Equal(t, "", pandoraEngine.endpoint) + }) + + t.Run("should mark as running with non-empty endpoint", func(t *testing.T) { + pandoraEngine.endpoint = dummyEndpoint + pandoraEngine.Start(nil) + + assert.True(t, pandoraEngine.isRunning) + assert.Nil(t, pandoraEngine.chain) + }) + + t.Run("should wait for connection", func(t *testing.T) { + t.Parallel() + waitingPandoraEngine := createDummyPandora(t) + waitingPandoraEngine.endpoint = dummyEndpoint + ticker := time.NewTicker(reConPeriod) + dummyError := fmt.Errorf("dummy Error") + + waitingPandoraEngine.dialRPC = func(endpoint string) (*rpc.Client, error) { + return nil, dummyError + } + + waitingPandoraEngine.Start(nil) + <-ticker.C + assert.Equal(t, dummyError, waitingPandoraEngine.runError) + + waitingPandoraEngine.dialRPC = dummyRpcFunc + <-ticker.C + assert.Equal(t, uint64(0), waitingPandoraEngine.currentEpoch) + assert.Nil(t, waitingPandoraEngine.runError) + }) +} + +func createDummyPandora(t *testing.T) (pandoraEngine *Pandora) { + ctx := context.Background() + cfg := ¶ms.PandoraConfig{ + GenesisStartTime: 0, + SlotsPerEpoch: 0, + SlotTimeDuration: 0, + } + urls := make([]string, 2) + dialGrpcFnc := dummyRpcFunc + pandoraEngine = New(ctx, cfg, urls, dialGrpcFnc) + + return +} From b708232d3c5ac9f01b9aae49cc7e6de59781b803 Mon Sep 17 00:00:00 2001 From: blazejkrzak Date: Wed, 11 Aug 2021 15:48:27 +0200 Subject: [PATCH 02/33] Test suite: - Start() happy path for connection wait --- consensus/pandora/pandora_test.go | 44 +++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/consensus/pandora/pandora_test.go b/consensus/pandora/pandora_test.go index 32408cbd5a25..146cdaa3ce0c 100644 --- a/consensus/pandora/pandora_test.go +++ b/consensus/pandora/pandora_test.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" "github.com/stretchr/testify/assert" + "net" "testing" "time" ) @@ -14,6 +15,8 @@ var ( dummyRpcFunc = DialRPCFn(func(endpoint string) (rpcClient *rpc.Client, err error) { return rpc.Dial(endpoint) }) + + ipcTestLocation = "./test.ipc" ) func Test_New(t *testing.T) { @@ -47,10 +50,12 @@ func TestPandora_Start(t *testing.T) { assert.Nil(t, pandoraEngine.chain) }) + makeOrchestratorServer(t) + t.Run("should wait for connection", func(t *testing.T) { t.Parallel() waitingPandoraEngine := createDummyPandora(t) - waitingPandoraEngine.endpoint = dummyEndpoint + waitingPandoraEngine.endpoint = ipcTestLocation ticker := time.NewTicker(reConPeriod) dummyError := fmt.Errorf("dummy Error") @@ -59,10 +64,15 @@ func TestPandora_Start(t *testing.T) { } waitingPandoraEngine.Start(nil) + t.Log("Waiting for reconnection in Pandora Engine") <-ticker.C assert.Equal(t, dummyError, waitingPandoraEngine.runError) - waitingPandoraEngine.dialRPC = dummyRpcFunc + t.Log("Waiting for reconnection in Pandora Engine") + <-ticker.C + _, server, _ := makeOrchestratorServer(t) + defer server.Stop() + t.Log("Waiting for reconnection in Pandora Engine") <-ticker.C assert.Equal(t, uint64(0), waitingPandoraEngine.currentEpoch) assert.Nil(t, waitingPandoraEngine.runError) @@ -82,3 +92,33 @@ func createDummyPandora(t *testing.T) (pandoraEngine *Pandora) { return } + +type OrchestratorApi struct{} + +func (orchestratorApi *OrchestratorApi) MinimalConsensusInfo( + ctx context.Context, + epoch uint64, +) (subscription *rpc.Subscription, err error) { + return +} + +func makeOrchestratorServer( + t *testing.T, +) (listener net.Listener, server *rpc.Server, location string) { + location = ipcTestLocation + apis := make([]rpc.API, 0) + api := &OrchestratorApi{} + + apis = append(apis, rpc.API{ + Namespace: "orc", + Version: "1.0", + Service: api, + Public: true, + }) + + // TODO: change to inproc? + listener, server, err := rpc.StartIPCEndpoint(location, apis) + assert.NoError(t, err) + + return +} From e4acbff89f41af6ba1e1317e6b68c00582c51a6e Mon Sep 17 00:00:00 2001 From: blazejkrzak Date: Wed, 11 Aug 2021 16:36:59 +0200 Subject: [PATCH 03/33] Test suite: - Start() happy path for done event --- consensus/pandora/pandora_test.go | 51 +++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/consensus/pandora/pandora_test.go b/consensus/pandora/pandora_test.go index 146cdaa3ce0c..4343f0349a0e 100644 --- a/consensus/pandora/pandora_test.go +++ b/consensus/pandora/pandora_test.go @@ -20,7 +20,7 @@ var ( ) func Test_New(t *testing.T) { - pandoraEngine := createDummyPandora(t) + pandoraEngine, _ := createDummyPandora(t) assert.IsType(t, &Pandora{}, pandoraEngine) t.Run("should have default settings", func(t *testing.T) { @@ -34,27 +34,27 @@ func Test_New(t *testing.T) { } func TestPandora_Start(t *testing.T) { - pandoraEngine := createDummyPandora(t) - dummyEndpoint := "https://some.endpoint" // TODO: in my opinion Start() should return err when failure is present t.Run("should not start with empty endpoint", func(t *testing.T) { + pandoraEngine, _ := createDummyPandora(t) pandoraEngine.Start(nil) assert.Equal(t, "", pandoraEngine.endpoint) }) t.Run("should mark as running with non-empty endpoint", func(t *testing.T) { + pandoraEngine, _ := createDummyPandora(t) + dummyEndpoint := "https://some.endpoint" pandoraEngine.endpoint = dummyEndpoint pandoraEngine.Start(nil) - assert.True(t, pandoraEngine.isRunning) assert.Nil(t, pandoraEngine.chain) }) - makeOrchestratorServer(t) + _, server, _ := makeOrchestratorServer(t) + defer server.Stop() t.Run("should wait for connection", func(t *testing.T) { - t.Parallel() - waitingPandoraEngine := createDummyPandora(t) + waitingPandoraEngine, _ := createDummyPandora(t) waitingPandoraEngine.endpoint = ipcTestLocation ticker := time.NewTicker(reConPeriod) dummyError := fmt.Errorf("dummy Error") @@ -70,17 +70,44 @@ func TestPandora_Start(t *testing.T) { waitingPandoraEngine.dialRPC = dummyRpcFunc t.Log("Waiting for reconnection in Pandora Engine") <-ticker.C - _, server, _ := makeOrchestratorServer(t) - defer server.Stop() - t.Log("Waiting for reconnection in Pandora Engine") + t.Log("Waiting for reconnection in Pandora Engine, pointing to orchestrator server") <-ticker.C assert.Equal(t, uint64(0), waitingPandoraEngine.currentEpoch) assert.Nil(t, waitingPandoraEngine.runError) }) + + t.Run("should handle seal request", func(t *testing.T) { + + }) + + t.Run("should handle sharding info request", func(t *testing.T) { + + }) + + t.Run("should handle submitSignatureData", func(t *testing.T) { + + }) + + t.Run("should handle subscriptionErrCh", func(t *testing.T) { + + }) + + t.Run("should handle done event", func(t *testing.T) { + pandoraEngine, cancel := createDummyPandora(t) + dummyEndpoint := ipcTestLocation + pandoraEngine.endpoint = dummyEndpoint + pandoraEngine.Start(nil) + assert.True(t, pandoraEngine.isRunning) + time.Sleep(time.Millisecond * 100) + cancel() + time.Sleep(time.Millisecond * 50) + assert.False(t, pandoraEngine.isRunning) + assert.Nil(t, pandoraEngine.runError) + }) } -func createDummyPandora(t *testing.T) (pandoraEngine *Pandora) { - ctx := context.Background() +func createDummyPandora(t *testing.T) (pandoraEngine *Pandora, cancel context.CancelFunc) { + ctx, cancel := context.WithCancel(context.Background()) cfg := ¶ms.PandoraConfig{ GenesisStartTime: 0, SlotsPerEpoch: 0, From 203b46c6ed5b7f754faf5b89f4af4dd684a1079b Mon Sep 17 00:00:00 2001 From: blazejkrzak Date: Wed, 11 Aug 2021 16:44:17 +0200 Subject: [PATCH 04/33] Test suite: - Start() happy path for subscription err ch --- consensus/pandora/pandora_test.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/consensus/pandora/pandora_test.go b/consensus/pandora/pandora_test.go index 4343f0349a0e..a5fa43c53633 100644 --- a/consensus/pandora/pandora_test.go +++ b/consensus/pandora/pandora_test.go @@ -89,7 +89,17 @@ func TestPandora_Start(t *testing.T) { }) t.Run("should handle subscriptionErrCh", func(t *testing.T) { - + pandoraEngine, _ := createDummyPandora(t) + dummyEndpoint := ipcTestLocation + pandoraEngine.endpoint = dummyEndpoint + pandoraEngine.Start(nil) + time.Sleep(time.Millisecond * 100) + dummyErr := fmt.Errorf("dummyErr") + pandoraEngine.subscriptionErrCh <- dummyErr + time.Sleep(reConPeriod) + assert.Equal(t, dummyErr, pandoraEngine.runError) + time.Sleep(reConPeriod) + assert.NotEqual(t, dummyErr, pandoraEngine.runError) }) t.Run("should handle done event", func(t *testing.T) { From b91ea324067ec2622fbf523b6ff8d233d2ebeca0 Mon Sep 17 00:00:00 2001 From: blazejkrzak Date: Wed, 11 Aug 2021 17:00:11 +0200 Subject: [PATCH 05/33] Test suite: - Start() happy path for seal request --- consensus/pandora/pandora_test.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/consensus/pandora/pandora_test.go b/consensus/pandora/pandora_test.go index a5fa43c53633..1751020335ed 100644 --- a/consensus/pandora/pandora_test.go +++ b/consensus/pandora/pandora_test.go @@ -3,9 +3,11 @@ package pandora import ( "context" "fmt" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" "github.com/stretchr/testify/assert" + "math/big" "net" "testing" "time" @@ -77,7 +79,26 @@ func TestPandora_Start(t *testing.T) { }) t.Run("should handle seal request", func(t *testing.T) { + pandoraEngine, _ := createDummyPandora(t) + dummyEndpoint := ipcTestLocation + pandoraEngine.endpoint = dummyEndpoint + genesisHeader := &types.Header{Number: big.NewInt(0)} + genesisBlock := types.NewBlock(genesisHeader, nil, nil, nil, nil) + pandoraEngine.setCurrentBlock(genesisBlock) + pandoraEngine.Start(nil) + + expectedBlockNumber := int64(1) + firstHeader := &types.Header{Number: big.NewInt(expectedBlockNumber)} + firstBlock := types.NewBlock(firstHeader, nil, nil, nil, nil) + results := make(chan *types.Block) + pandoraEngine.newSealRequestCh <- &sealTask{ + block: firstBlock, + results: results, + } + + time.Sleep(time.Millisecond * 50) + assert.Equal(t, firstBlock.Number(), pandoraEngine.currentBlock.Number()) }) t.Run("should handle sharding info request", func(t *testing.T) { From f90ff22f24c37b4e7271c28d2cb8c35f14dcb64c Mon Sep 17 00:00:00 2001 From: blazejkrzak Date: Wed, 11 Aug 2021 17:10:29 +0200 Subject: [PATCH 06/33] Test suite: - Start() failure path for seal request --- consensus/pandora/pandora_test.go | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/consensus/pandora/pandora_test.go b/consensus/pandora/pandora_test.go index 1751020335ed..1019824fae82 100644 --- a/consensus/pandora/pandora_test.go +++ b/consensus/pandora/pandora_test.go @@ -3,6 +3,7 @@ package pandora import ( "context" "fmt" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" @@ -59,6 +60,7 @@ func TestPandora_Start(t *testing.T) { waitingPandoraEngine, _ := createDummyPandora(t) waitingPandoraEngine.endpoint = ipcTestLocation ticker := time.NewTicker(reConPeriod) + defer ticker.Stop() dummyError := fmt.Errorf("dummy Error") waitingPandoraEngine.dialRPC = func(endpoint string) (*rpc.Client, error) { @@ -82,9 +84,6 @@ func TestPandora_Start(t *testing.T) { pandoraEngine, _ := createDummyPandora(t) dummyEndpoint := ipcTestLocation pandoraEngine.endpoint = dummyEndpoint - genesisHeader := &types.Header{Number: big.NewInt(0)} - genesisBlock := types.NewBlock(genesisHeader, nil, nil, nil, nil) - pandoraEngine.setCurrentBlock(genesisBlock) pandoraEngine.Start(nil) expectedBlockNumber := int64(1) @@ -106,7 +105,29 @@ func TestPandora_Start(t *testing.T) { }) t.Run("should handle submitSignatureData", func(t *testing.T) { + pandoraEngine, _ := createDummyPandora(t) + dummyEndpoint := ipcTestLocation + pandoraEngine.endpoint = dummyEndpoint + pandoraEngine.Start(nil) + errChannel := make(chan error) + pandoraEngine.submitShardingInfoCh <- &shardingResult{ + nonce: types.BlockNonce{}, + hash: common.Hash{}, + blsSeal: nil, + errc: errChannel, + } + + ticker := time.NewTicker(time.Second) + defer ticker.Stop() + + select { + case <-ticker.C: + assert.Fail(t, "should receive error that work was not submitted") + case err := <-errChannel: + assert.NotNil(t, err) + assert.Equal(t, "invalid submit work request", err.Error()) + } }) t.Run("should handle subscriptionErrCh", func(t *testing.T) { @@ -148,6 +169,10 @@ func createDummyPandora(t *testing.T) (pandoraEngine *Pandora, cancel context.Ca dialGrpcFnc := dummyRpcFunc pandoraEngine = New(ctx, cfg, urls, dialGrpcFnc) + genesisHeader := &types.Header{Number: big.NewInt(0)} + genesisBlock := types.NewBlock(genesisHeader, nil, nil, nil, nil) + pandoraEngine.setCurrentBlock(genesisBlock) + return } From 506f0b362f52528da127637242c929b22340551d Mon Sep 17 00:00:00 2001 From: blazejkrzak Date: Wed, 11 Aug 2021 18:52:02 +0200 Subject: [PATCH 07/33] Test suite: - Start() happy path for seal request (still failing, TODO present) --- consensus/pandora/helpers.go | 4 +- consensus/pandora/pandora_test.go | 110 +++++++++++++++++++++++++----- 2 files changed, 96 insertions(+), 18 deletions(-) diff --git a/consensus/pandora/helpers.go b/consensus/pandora/helpers.go index eb5bf6e101a2..40179b7cfc41 100644 --- a/consensus/pandora/helpers.go +++ b/consensus/pandora/helpers.go @@ -190,7 +190,9 @@ func (p *Pandora) VerifyBLSSignature(header *types.Header) error { log.Debug("In verifyBlsSignature", "header extra data", common.Bytes2Hex(header.Extra), "header block Number", header.Number.Uint64(), "sealHash", sealHash, "sealHash (signature msg) in bytes", sealHash[:], "validatorPublicKey", hexutils.BytesToHex(validatorPubKey.Marshal()), "extractedIndex", extractedIndex) if !signature.Verify(validatorPubKey, sealHash[:]) { - log.Error("Failed to verify bls signature", "err", errSigFailedToVerify) + sealHashffff := hexutil.Encode(sealHash[:]) + publicKeyBytes := hexutil.Encode(validatorPubKey.Marshal()) + log.Error("Failed to verify bls signature", "err", errSigFailedToVerify, "asss", sealHashffff, "pub", publicKeyBytes) return errSigFailedToVerify } return nil diff --git a/consensus/pandora/pandora_test.go b/consensus/pandora/pandora_test.go index 1019824fae82..1d7371394ce0 100644 --- a/consensus/pandora/pandora_test.go +++ b/consensus/pandora/pandora_test.go @@ -4,9 +4,13 @@ import ( "context" "fmt" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" + bls_common "github.com/prysmaticlabs/prysm/shared/bls/common" + "github.com/prysmaticlabs/prysm/shared/bls/herumi" "github.com/stretchr/testify/assert" "math/big" "net" @@ -111,23 +115,95 @@ func TestPandora_Start(t *testing.T) { pandoraEngine.Start(nil) errChannel := make(chan error) - pandoraEngine.submitShardingInfoCh <- &shardingResult{ - nonce: types.BlockNonce{}, - hash: common.Hash{}, - blsSeal: nil, - errc: errChannel, - } - - ticker := time.NewTicker(time.Second) - defer ticker.Stop() - - select { - case <-ticker.C: - assert.Fail(t, "should receive error that work was not submitted") - case err := <-errChannel: - assert.NotNil(t, err) - assert.Equal(t, "invalid submit work request", err.Error()) - } + t.Run("should react to invalid work", func(t *testing.T) { + shardingWorkHash := common.Hash{} + pandoraEngine.submitShardingInfoCh <- &shardingResult{ + nonce: types.BlockNonce{}, + hash: shardingWorkHash, + blsSeal: nil, + errc: errChannel, + } + + ticker := time.NewTicker(time.Second) + defer ticker.Stop() + + select { + case <-ticker.C: + assert.Fail(t, "should receive error that work was not submitted") + ticker.Stop() + case err := <-errChannel: + assert.NotNil(t, err) + assert.Equal(t, "invalid submit work request", err.Error()) + ticker.Stop() + } + }) + + t.Run("should pass valid work", func(t *testing.T) { + expectedBlockNumber := int64(1) + firstHeader := &types.Header{Number: big.NewInt(expectedBlockNumber)} + firstHeaderExtra := &ExtraData{ + Slot: 1, + Epoch: 0, + Turn: 1, + } + firstHeaderExtraBytes, err := rlp.EncodeToBytes(firstHeaderExtra) + assert.Nil(t, err) + firstHeader.Extra = firstHeaderExtraBytes + + blsSeal := &BlsSignatureBytes{} + privKeyHex := "0x3a3cae36df7b66019442f8f38acb080c680780dc8ee2d430cc801903be0b651e" + privKey, err := herumi.SecretKeyFromBytes(hexutil.MustDecode(privKeyHex)) + assert.Nil(t, err) + + publicKeys := [32]bls_common.PublicKey{} + publicKeys[1] = privKey.PublicKey() + + pandoraEngine.epochInfos[0] = &EpochInfo{ + Epoch: 0, + ValidatorList: publicKeys, + EpochTimeStart: 0, + SlotTimeDuration: DefaultSlotTimeDuration, + } + + firstBlock := types.NewBlock(firstHeader, nil, nil, nil, nil) + + // I dont know why but in test I couldnt match sealhash via SealHash() so I do it manually + expectedSealHash := hexutil.MustDecode("0x85d2ed6f97f0e8ebfcc7f1badaf6522748b2488a45cc90f56c6c48a7290658f6") + shardingWorkHash := common.BytesToHash(expectedSealHash) + pandoraEngine.works[shardingWorkHash] = firstBlock + + signature := privKey.Sign(shardingWorkHash.Bytes()) + copy(blsSeal[:], signature.Marshal()) + signatureFromBytes, err := herumi.SignatureFromBytes(blsSeal[:]) + assert.Nil(t, err) + assert.NotNil(t, signatureFromBytes) + + signature, err = herumi.SignatureFromBytes(blsSeal[:]) + assert.Nil(t, err) + assert.True(t, signature.Verify(publicKeys[1], expectedSealHash)) + + // TODO: add results to pandora engine + // pabndoraEngine.results must not be empty to make whole procedure work + + pandoraEngine.submitShardingInfoCh <- &shardingResult{ + nonce: types.BlockNonce{}, + hash: shardingWorkHash, + blsSeal: blsSeal, + errc: errChannel, + } + + ticker := time.NewTicker(time.Second) + defer ticker.Stop() + + select { + //case <-ticker.C: + // assert.Fail(t, "should receive error that work was not submitted") + // ticker.Stop() + case err := <-errChannel: + assert.Nil(t, err) + ticker.Stop() + } + }) }) t.Run("should handle subscriptionErrCh", func(t *testing.T) { From f953656a6a28f5a781cced05b4a273ce090bfde2 Mon Sep 17 00:00:00 2001 From: blazejkrzak Date: Thu, 12 Aug 2021 12:33:08 +0200 Subject: [PATCH 08/33] Test suite: - Start() happy path for seal request --- consensus/pandora/pandora.go | 3 ++- consensus/pandora/pandora_test.go | 9 ++++++--- consensus/pandora/sealer.go | 2 +- consensus/pandora/types.go | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/consensus/pandora/pandora.go b/consensus/pandora/pandora.go index 854ad2769474..33434592be18 100644 --- a/consensus/pandora/pandora.go +++ b/consensus/pandora/pandora.go @@ -60,7 +60,7 @@ type Pandora struct { namespace string subscription *rpc.ClientSubscription subscriptionErrCh chan error - results chan<- *types.Block + results chan *types.Block works map[common.Hash]*types.Block fetchShardingInfoCh chan *shardingInfoReq // Channel used for remote sealer to fetch mining work submitShardingInfoCh chan *shardingResult @@ -228,6 +228,7 @@ func (p *Pandora) run(done <-chan struct{}) { case sealRequest := <-p.newSealRequestCh: log.Debug("new seal request in pandora engine", "block number", sealRequest.block.Number()) // first save it to result channel. so that we can send worker about the info + // TODO: IMHO it is not consumed anywhere because it is send-only chan. Debug if it is needed. p.results = sealRequest.results // then simply save the block into current block. We will use it again p.setCurrentBlock(sealRequest.block) diff --git a/consensus/pandora/pandora_test.go b/consensus/pandora/pandora_test.go index 1d7371394ce0..9dda049aa1bb 100644 --- a/consensus/pandora/pandora_test.go +++ b/consensus/pandora/pandora_test.go @@ -184,6 +184,7 @@ func TestPandora_Start(t *testing.T) { // TODO: add results to pandora engine // pabndoraEngine.results must not be empty to make whole procedure work + pandoraEngine.results = make(chan *types.Block) pandoraEngine.submitShardingInfoCh <- &shardingResult{ nonce: types.BlockNonce{}, @@ -196,9 +197,11 @@ func TestPandora_Start(t *testing.T) { defer ticker.Stop() select { - //case <-ticker.C: - // assert.Fail(t, "should receive error that work was not submitted") - // ticker.Stop() + case block := <-pandoraEngine.results: + assert.Equal(t, firstHeader.Number, block.Number()) + case <-ticker.C: + assert.Fail(t, "should receive error that work was not submitted") + ticker.Stop() case err := <-errChannel: assert.Nil(t, err) ticker.Stop() diff --git a/consensus/pandora/sealer.go b/consensus/pandora/sealer.go index 31efffd7c659..416389fbb8c6 100644 --- a/consensus/pandora/sealer.go +++ b/consensus/pandora/sealer.go @@ -16,7 +16,7 @@ const ( staleThreshold = 7 ) -func (pan *Pandora) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { +func (pan *Pandora) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan *types.Block, stop <-chan struct{}) error { // it does nothing. It just send sealing info to pandora running loop pan.newSealRequestCh <- &sealTask{block: block, results: results} return nil diff --git a/consensus/pandora/types.go b/consensus/pandora/types.go index e24808d2162b..61e8a55c1bbf 100644 --- a/consensus/pandora/types.go +++ b/consensus/pandora/types.go @@ -67,7 +67,7 @@ type shardingInfoReq struct { // sealTask wraps a seal block with relative result channel type sealTask struct { block *types.Block - results chan<- *types.Block + results chan *types.Block } func (ei *EpochInfo) copy() *EpochInfo { From c42ffe2b8a34c5f251d09166ce19a034e2977dc2 Mon Sep 17 00:00:00 2001 From: blazejkrzak Date: Thu, 12 Aug 2021 12:53:12 +0200 Subject: [PATCH 09/33] Test suite: - Start() happy path for seal request without any changes, fail path for sharding request --- consensus/pandora/pandora.go | 2 +- consensus/pandora/pandora_test.go | 44 ++++++++++++++++++++++++++----- consensus/pandora/sealer.go | 2 +- consensus/pandora/types.go | 2 +- 4 files changed, 40 insertions(+), 10 deletions(-) diff --git a/consensus/pandora/pandora.go b/consensus/pandora/pandora.go index 33434592be18..5ac06a3a5c90 100644 --- a/consensus/pandora/pandora.go +++ b/consensus/pandora/pandora.go @@ -60,7 +60,7 @@ type Pandora struct { namespace string subscription *rpc.ClientSubscription subscriptionErrCh chan error - results chan *types.Block + results chan<- *types.Block works map[common.Hash]*types.Block fetchShardingInfoCh chan *shardingInfoReq // Channel used for remote sealer to fetch mining work submitShardingInfoCh chan *shardingResult diff --git a/consensus/pandora/pandora_test.go b/consensus/pandora/pandora_test.go index 9dda049aa1bb..c31fc267648d 100644 --- a/consensus/pandora/pandora_test.go +++ b/consensus/pandora/pandora_test.go @@ -105,7 +105,38 @@ func TestPandora_Start(t *testing.T) { }) t.Run("should handle sharding info request", func(t *testing.T) { + pandoraEngine, _ := createDummyPandora(t) + dummyEndpoint := ipcTestLocation + pandoraEngine.endpoint = dummyEndpoint + pandoraEngine.Start(nil) + + t.Run("should return err when there is no sharding work", func(t *testing.T) { + pandoraEngine.currentBlock = nil + errChannel := make(chan error) + pandoraEngine.fetchShardingInfoCh <- &shardingInfoReq{ + slot: 0, + epoch: 0, + blockNumber: 0, + parentHash: common.Hash{}, + errc: errChannel, + res: nil, + } + ticker := time.NewTicker(time.Second) + defer ticker.Stop() + + select { + case <-ticker.C: + assert.Fail(t, "should receive error that there was no sharding block") + ticker.Stop() + case err := <-errChannel: + assert.NotNil(t, err) + assert.Equal(t, errNoShardingBlock, err) + ticker.Stop() + } + }) + + //t.Run("should") }) t.Run("should handle submitSignatureData", func(t *testing.T) { @@ -113,10 +144,10 @@ func TestPandora_Start(t *testing.T) { dummyEndpoint := ipcTestLocation pandoraEngine.endpoint = dummyEndpoint pandoraEngine.Start(nil) - errChannel := make(chan error) t.Run("should react to invalid work", func(t *testing.T) { shardingWorkHash := common.Hash{} + errChannel := make(chan error) pandoraEngine.submitShardingInfoCh <- &shardingResult{ nonce: types.BlockNonce{}, hash: shardingWorkHash, @@ -139,6 +170,7 @@ func TestPandora_Start(t *testing.T) { }) t.Run("should pass valid work", func(t *testing.T) { + errChannel := make(chan error) expectedBlockNumber := int64(1) firstHeader := &types.Header{Number: big.NewInt(expectedBlockNumber)} firstHeaderExtra := &ExtraData{ @@ -171,10 +203,12 @@ func TestPandora_Start(t *testing.T) { expectedSealHash := hexutil.MustDecode("0x85d2ed6f97f0e8ebfcc7f1badaf6522748b2488a45cc90f56c6c48a7290658f6") shardingWorkHash := common.BytesToHash(expectedSealHash) pandoraEngine.works[shardingWorkHash] = firstBlock - + fullResultsChan := make(chan *types.Block) + pandoraEngine.results = fullResultsChan signature := privKey.Sign(shardingWorkHash.Bytes()) copy(blsSeal[:], signature.Marshal()) signatureFromBytes, err := herumi.SignatureFromBytes(blsSeal[:]) + assert.Nil(t, err) assert.NotNil(t, signatureFromBytes) @@ -182,10 +216,6 @@ func TestPandora_Start(t *testing.T) { assert.Nil(t, err) assert.True(t, signature.Verify(publicKeys[1], expectedSealHash)) - // TODO: add results to pandora engine - // pabndoraEngine.results must not be empty to make whole procedure work - pandoraEngine.results = make(chan *types.Block) - pandoraEngine.submitShardingInfoCh <- &shardingResult{ nonce: types.BlockNonce{}, hash: shardingWorkHash, @@ -197,7 +227,7 @@ func TestPandora_Start(t *testing.T) { defer ticker.Stop() select { - case block := <-pandoraEngine.results: + case block := <-fullResultsChan: assert.Equal(t, firstHeader.Number, block.Number()) case <-ticker.C: assert.Fail(t, "should receive error that work was not submitted") diff --git a/consensus/pandora/sealer.go b/consensus/pandora/sealer.go index 416389fbb8c6..31efffd7c659 100644 --- a/consensus/pandora/sealer.go +++ b/consensus/pandora/sealer.go @@ -16,7 +16,7 @@ const ( staleThreshold = 7 ) -func (pan *Pandora) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan *types.Block, stop <-chan struct{}) error { +func (pan *Pandora) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { // it does nothing. It just send sealing info to pandora running loop pan.newSealRequestCh <- &sealTask{block: block, results: results} return nil diff --git a/consensus/pandora/types.go b/consensus/pandora/types.go index 61e8a55c1bbf..e24808d2162b 100644 --- a/consensus/pandora/types.go +++ b/consensus/pandora/types.go @@ -67,7 +67,7 @@ type shardingInfoReq struct { // sealTask wraps a seal block with relative result channel type sealTask struct { block *types.Block - results chan *types.Block + results chan<- *types.Block } func (ei *EpochInfo) copy() *EpochInfo { From 86ec4e5c86b9caeff4e1b17e90c9823f0df3564c Mon Sep 17 00:00:00 2001 From: blazejkrzak Date: Thu, 12 Aug 2021 13:11:46 +0200 Subject: [PATCH 10/33] Test suite: - Start() fail path for sharding request --- consensus/pandora/pandora_test.go | 84 ++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/consensus/pandora/pandora_test.go b/consensus/pandora/pandora_test.go index c31fc267648d..d768ac34cd44 100644 --- a/consensus/pandora/pandora_test.go +++ b/consensus/pandora/pandora_test.go @@ -110,6 +110,88 @@ func TestPandora_Start(t *testing.T) { pandoraEngine.endpoint = dummyEndpoint pandoraEngine.Start(nil) + t.Run("should handle sharding info for block number less than 2", func(t *testing.T) { + errChannel := make(chan error) + resChannel := make(chan [4]string) + pandoraEngine.fetchShardingInfoCh <- &shardingInfoReq{ + slot: 0, + epoch: 0, + blockNumber: 0, + parentHash: common.Hash{}, + errc: errChannel, + res: resChannel, + } + + select { + case err := <-errChannel: + assert.Nil(t, err) + case response := <-resChannel: + assert.Equal(t, "0x2e07d67c7eebfc74fcc5ca07f25d995a3a67c497deaee9d60fb0b26b549a8d3b", response[0]) + assert.Equal(t, "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", response[1]) + assert.Equal(t, "0xf901f1a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000808080808084c3808080a00000000000000000000000000000000000000000000000000000000000000000880000000000000000", response[2]) + assert.Equal(t, "0x", response[3]) + break + } + + pandoraEngine.fetchShardingInfoCh <- &shardingInfoReq{ + slot: 1, + epoch: 0, + blockNumber: 1, + parentHash: common.Hash{}, + errc: errChannel, + res: resChannel, + } + + select { + case err := <-errChannel: + assert.Nil(t, err) + case response := <-resChannel: + assert.Equal(t, "0x4203bd2ead3d91541fd49fb40cc2a16bce624be5074917d9d28ce6e164860197", response[0]) + assert.Equal(t, "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", response[1]) + assert.Equal(t, "0xf901f1a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000808080808084c3018001a00000000000000000000000000000000000000000000000000000000000000000880000000000000000", response[2]) + assert.Equal(t, "0x", response[3]) + break + } + }) + + t.Run( + "should return err when parent hash does not match and block number is greater than 1", + func(t *testing.T) { + errChannel := make(chan error) + resChannel := make(chan [4]string) + + pandoraEngine.fetchShardingInfoCh <- &shardingInfoReq{ + slot: 3, + epoch: 0, + blockNumber: 2, + parentHash: common.HexToHash("0x4203bd2ead3d91541fd49fb40cc2a16bce624be5074917d9d28ce6e164860192"), + errc: errChannel, + res: resChannel, + } + + err := <-errChannel + assert.Equal(t, errInvalidParentHash, err) + }) + + t.Run( + "should return err when block number does not match and block number is greater than 1", + func(t *testing.T) { + errChannel := make(chan error) + resChannel := make(chan [4]string) + + pandoraEngine.fetchShardingInfoCh <- &shardingInfoReq{ + slot: 3, + epoch: 0, + blockNumber: 2, + parentHash: common.Hash{}, + errc: errChannel, + res: resChannel, + } + + err := <-errChannel + assert.Equal(t, errInvalidBlockNumber, err) + }) + t.Run("should return err when there is no sharding work", func(t *testing.T) { pandoraEngine.currentBlock = nil errChannel := make(chan error) @@ -135,8 +217,6 @@ func TestPandora_Start(t *testing.T) { ticker.Stop() } }) - - //t.Run("should") }) t.Run("should handle submitSignatureData", func(t *testing.T) { From b95a9ff4fefbdebb6625a72cefc3915ae43ffc19 Mon Sep 17 00:00:00 2001 From: blazejkrzak Date: Thu, 12 Aug 2021 13:24:19 +0200 Subject: [PATCH 11/33] Test suite: - Start() covered with all ifs within --- consensus/pandora/pandora_test.go | 32 ++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/consensus/pandora/pandora_test.go b/consensus/pandora/pandora_test.go index d768ac34cd44..aae984e33cc9 100644 --- a/consensus/pandora/pandora_test.go +++ b/consensus/pandora/pandora_test.go @@ -41,7 +41,6 @@ func Test_New(t *testing.T) { } func TestPandora_Start(t *testing.T) { - // TODO: in my opinion Start() should return err when failure is present t.Run("should not start with empty endpoint", func(t *testing.T) { pandoraEngine, _ := createDummyPandora(t) pandoraEngine.Start(nil) @@ -192,6 +191,37 @@ func TestPandora_Start(t *testing.T) { assert.Equal(t, errInvalidBlockNumber, err) }) + t.Run("should handle sharding info when block is greater than 1", func(t *testing.T) { + errChannel := make(chan error) + resChannel := make(chan [4]string) + header := &types.Header{ + Number: big.NewInt(2), + ParentHash: common.HexToHash("0x4203bd2ead3d91541fd49fb40cc2a16bce624be5074917d9d28ce6e164860192"), + } + block := types.NewBlock(header, nil, nil, nil, nil) + pandoraEngine.setCurrentBlock(block) + + pandoraEngine.fetchShardingInfoCh <- &shardingInfoReq{ + slot: 3, + epoch: 0, + blockNumber: header.Number.Uint64(), + parentHash: header.ParentHash, + errc: errChannel, + res: resChannel, + } + + select { + case err := <-errChannel: + assert.Nil(t, err) + case response := <-resChannel: + assert.Equal(t, "0xe64f708a495767942054021a27efd25730ba1a2fef2dc6f68503ed8dc36d3951", response[0]) + assert.Equal(t, "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", response[1]) + assert.Equal(t, "0xf901f1a04203bd2ead3d91541fd49fb40cc2a16bce624be5074917d9d28ce6e164860192a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800280808084c3038003a00000000000000000000000000000000000000000000000000000000000000000880000000000000000", response[2]) + assert.Equal(t, "0x02", response[3]) + break + } + }) + t.Run("should return err when there is no sharding work", func(t *testing.T) { pandoraEngine.currentBlock = nil errChannel := make(chan error) From bd2224271215197cd075c9c3793b2ab4fa4b142e Mon Sep 17 00:00:00 2001 From: blazejkrzak Date: Thu, 12 Aug 2021 13:51:33 +0200 Subject: [PATCH 12/33] Test suite: - Start() covered with all ifs within - Fmt now pass --- cmd/devp2p/dns_cloudflare.go | 11 ++++--- cmd/utils/flags.go | 5 +-- consensus/pandora/consensus.go | 3 +- consensus/pandora/epoch_info_cache.go | 3 +- consensus/pandora/helpers.go | 47 +-------------------------- consensus/pandora/pandora.go | 2 -- consensus/pandora/pandora_test.go | 9 ++--- consensus/pandora/subscription.go | 1 + eth/backend.go | 3 +- eth/ethconfig/config.go | 3 +- 10 files changed, 24 insertions(+), 63 deletions(-) diff --git a/cmd/devp2p/dns_cloudflare.go b/cmd/devp2p/dns_cloudflare.go index a4d10dcfdd3c..45786bd9128f 100644 --- a/cmd/devp2p/dns_cloudflare.go +++ b/cmd/devp2p/dns_cloudflare.go @@ -17,6 +17,7 @@ package main import ( + "context" "fmt" "strings" @@ -79,7 +80,7 @@ func (c *cloudflareClient) checkZone(name string) error { c.zoneID = id } log.Info(fmt.Sprintf("Checking Permissions on zone %s", c.zoneID)) - zone, err := c.ZoneDetails(c.zoneID) + zone, err := c.ZoneDetails(context.Background(), c.zoneID) if err != nil { return err } @@ -112,7 +113,7 @@ func (c *cloudflareClient) uploadRecords(name string, records map[string]string) records = lrecords log.Info(fmt.Sprintf("Retrieving existing TXT records on %s", name)) - entries, err := c.DNSRecords(c.zoneID, cloudflare.DNSRecord{Type: "TXT"}) + entries, err := c.DNSRecords(context.Background(), c.zoneID, cloudflare.DNSRecord{Type: "TXT"}) if err != nil { return err } @@ -134,12 +135,12 @@ func (c *cloudflareClient) uploadRecords(name string, records map[string]string) if path != name { ttl = treeNodeTTL // Max TTL permitted by Cloudflare } - _, err = c.CreateDNSRecord(c.zoneID, cloudflare.DNSRecord{Type: "TXT", Name: path, Content: val, TTL: ttl}) + _, err = c.CreateDNSRecord(context.Background(), c.zoneID, cloudflare.DNSRecord{Type: "TXT", Name: path, Content: val, TTL: ttl}) } else if old.Content != val { // Entry already exists, only change its content. log.Info(fmt.Sprintf("Updating %s from %q to %q", path, old.Content, val)) old.Content = val - err = c.UpdateDNSRecord(c.zoneID, old.ID, old) + err = c.UpdateDNSRecord(context.Background(), c.zoneID, old.ID, old) } else { log.Info(fmt.Sprintf("Skipping %s = %q", path, val)) } @@ -155,7 +156,7 @@ func (c *cloudflareClient) uploadRecords(name string, records map[string]string) } // Stale entry, nuke it. log.Info(fmt.Sprintf("Deleting %s = %q", path, entry.Content)) - if err := c.DeleteDNSRecord(c.zoneID, entry.ID); err != nil { + if err := c.DeleteDNSRecord(context.Background(), c.zoneID, entry.ID); err != nil { return fmt.Errorf("failed to delete %s: %v", path, err) } } diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 7c7ad660d53e..204c31261df6 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -21,8 +21,6 @@ import ( "context" "crypto/ecdsa" "fmt" - "github.com/ethereum/go-ethereum/consensus/pandora" - "github.com/ethereum/go-ethereum/rpc" "io" "io/ioutil" "math/big" @@ -34,6 +32,9 @@ import ( "text/template" "time" + "github.com/ethereum/go-ethereum/consensus/pandora" + "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" diff --git a/consensus/pandora/consensus.go b/consensus/pandora/consensus.go index 08040f00dec5..598fdaf21f8b 100644 --- a/consensus/pandora/consensus.go +++ b/consensus/pandora/consensus.go @@ -1,6 +1,8 @@ package pandora import ( + "math/big" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/core/state" @@ -9,7 +11,6 @@ import ( "github.com/ethereum/go-ethereum/trie" "github.com/pkg/errors" "golang.org/x/crypto/sha3" - "math/big" ) var ( diff --git a/consensus/pandora/epoch_info_cache.go b/consensus/pandora/epoch_info_cache.go index 9a932a07caa7..87932ebbc466 100644 --- a/consensus/pandora/epoch_info_cache.go +++ b/consensus/pandora/epoch_info_cache.go @@ -1,8 +1,9 @@ package pandora import ( - lru "github.com/hashicorp/golang-lru" "sync" + + lru "github.com/hashicorp/golang-lru" ) const inmemoryEpochInfos = 4096 diff --git a/consensus/pandora/helpers.go b/consensus/pandora/helpers.go index 40179b7cfc41..eb361e3c671b 100644 --- a/consensus/pandora/helpers.go +++ b/consensus/pandora/helpers.go @@ -9,7 +9,6 @@ import ( "fmt" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" @@ -20,48 +19,6 @@ import ( "github.com/prysmaticlabs/prysm/shared/bls/herumi" ) -// extraDataWithoutBLSSig -func extraDataWithoutBLSSig(rlpExtraData []byte) (*ExtraData, error) { - extraData := new(ExtraData) - if err := rlp.DecodeBytes(rlpExtraData, extraData); err != nil { - return nil, err - } - return extraData, nil -} - -// prepareShardingInfo -func prepareShardingInfo(header *types.Header, sealHash common.Hash) [4]string { - var shardingInfo [4]string - rlpHeader, _ := rlp.EncodeToBytes(header) - - shardingInfo[0] = sealHash.Hex() - shardingInfo[1] = header.ReceiptHash.Hex() - shardingInfo[2] = hexutil.Encode(rlpHeader) - shardingInfo[3] = hexutil.Encode(header.Number.Bytes()) - - return shardingInfo -} - -// getDummyHeader -func getDummyHeader() *types.Header { - return &types.Header{ - ParentHash: common.HexToHash("3244474eb97faefc26df91a8c3d0f2a8f859855ba87b76b1cc6044cca29add40"), - UncleHash: common.HexToHash("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"), - Coinbase: common.HexToAddress("b46d14ef42ac9bb01303ba1842ea784e2460c7e7"), - Root: common.HexToHash("03906b0760f3bec421d8a71c44273a5994c5f0e35b8b8d9e2112dc95a182aae6"), - TxHash: common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), - ReceiptHash: common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), - Difficulty: big.NewInt(1), - Number: big.NewInt(4), - GasLimit: 4718380, - GasUsed: 0, - Time: 1626171089, - Extra: common.FromHex("0xf866c30a800ab860a899054e1dd5ada5f5174edc532ffa39662cbfc90470233028096d7e41a3263114572cb7d0493ba213becec37f43145d041e0bfbaaf4bf8c2a7aeaebdd0d7fd6c326831b986a9802bf5e9ad1f180553ae0af77334cd4eb606ed71b0dc7db424e"), - MixDigest: common.HexToHash("a899054e1dd5ada5f5174edc532ffa39662cbfc90470233028096d7e41a32631"), - Nonce: types.BlockNonce{0x0000000000000000}, - } -} - func Mul64(a, b uint64) (uint64, error) { overflows, val := bits.Mul64(a, b) if overflows > 0 { @@ -190,9 +147,7 @@ func (p *Pandora) VerifyBLSSignature(header *types.Header) error { log.Debug("In verifyBlsSignature", "header extra data", common.Bytes2Hex(header.Extra), "header block Number", header.Number.Uint64(), "sealHash", sealHash, "sealHash (signature msg) in bytes", sealHash[:], "validatorPublicKey", hexutils.BytesToHex(validatorPubKey.Marshal()), "extractedIndex", extractedIndex) if !signature.Verify(validatorPubKey, sealHash[:]) { - sealHashffff := hexutil.Encode(sealHash[:]) - publicKeyBytes := hexutil.Encode(validatorPubKey.Marshal()) - log.Error("Failed to verify bls signature", "err", errSigFailedToVerify, "asss", sealHashffff, "pub", publicKeyBytes) + log.Error("Failed to verify bls signature", "err", errSigFailedToVerify) return errSigFailedToVerify } return nil diff --git a/consensus/pandora/pandora.go b/consensus/pandora/pandora.go index 5ac06a3a5c90..466ae437af39 100644 --- a/consensus/pandora/pandora.go +++ b/consensus/pandora/pandora.go @@ -27,7 +27,6 @@ var ( errInvalidValidatorSize = errors.New("invalid length of validator list") errInvalidEpochInfo = errors.New("invalid epoch info") - errEmptyOrchestratorUrl = errors.New("orchestrator url is empty") errNoShardingBlock = errors.New("no pandora sharding header available yet") errInvalidParentHash = errors.New("invalid parent hash") errInvalidBlockNumber = errors.New("invalid block number") @@ -228,7 +227,6 @@ func (p *Pandora) run(done <-chan struct{}) { case sealRequest := <-p.newSealRequestCh: log.Debug("new seal request in pandora engine", "block number", sealRequest.block.Number()) // first save it to result channel. so that we can send worker about the info - // TODO: IMHO it is not consumed anywhere because it is send-only chan. Debug if it is needed. p.results = sealRequest.results // then simply save the block into current block. We will use it again p.setCurrentBlock(sealRequest.block) diff --git a/consensus/pandora/pandora_test.go b/consensus/pandora/pandora_test.go index aae984e33cc9..bf651104dd36 100644 --- a/consensus/pandora/pandora_test.go +++ b/consensus/pandora/pandora_test.go @@ -3,6 +3,11 @@ package pandora import ( "context" "fmt" + "math/big" + "net" + "testing" + "time" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" @@ -12,10 +17,6 @@ import ( bls_common "github.com/prysmaticlabs/prysm/shared/bls/common" "github.com/prysmaticlabs/prysm/shared/bls/herumi" "github.com/stretchr/testify/assert" - "math/big" - "net" - "testing" - "time" ) var ( diff --git a/consensus/pandora/subscription.go b/consensus/pandora/subscription.go index ff030b14e09c..a914eae607bc 100644 --- a/consensus/pandora/subscription.go +++ b/consensus/pandora/subscription.go @@ -3,6 +3,7 @@ package pandora import ( "context" "fmt" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" diff --git a/eth/backend.go b/eth/backend.go index 33e99969e2dd..1316ccf09d79 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -20,13 +20,14 @@ package eth import ( "errors" "fmt" - "github.com/ethereum/go-ethereum/consensus/pandora" "math/big" "runtime" "sync" "sync/atomic" "time" + "github.com/ethereum/go-ethereum/consensus/pandora" + "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 0168d5e688bd..4cc37db6f007 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -19,7 +19,6 @@ package ethconfig import ( "context" - "github.com/ethereum/go-ethereum/consensus/pandora" "math/big" "os" "os/user" @@ -27,6 +26,8 @@ import ( "runtime" "time" + "github.com/ethereum/go-ethereum/consensus/pandora" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/clique" From aeada7ea7d2fea0715081c43ed1247aae5025d57 Mon Sep 17 00:00:00 2001 From: blazejkrzak Date: Fri, 13 Aug 2021 12:37:11 +0200 Subject: [PATCH 13/33] Test suite: - Remove todo --- consensus/pandora/pandora_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/consensus/pandora/pandora_test.go b/consensus/pandora/pandora_test.go index bf651104dd36..add82c1ba073 100644 --- a/consensus/pandora/pandora_test.go +++ b/consensus/pandora/pandora_test.go @@ -419,7 +419,6 @@ func makeOrchestratorServer( Public: true, }) - // TODO: change to inproc? listener, server, err := rpc.StartIPCEndpoint(location, apis) assert.NoError(t, err) From e13a0018c20bb92dc72ddaf62b03a0feceefea47 Mon Sep 17 00:00:00 2001 From: blazejkrzak Date: Fri, 13 Aug 2021 12:58:05 +0200 Subject: [PATCH 14/33] Test suite: - added skip on facebook test and golang binding test --- .github/workflows/main.yml | 2 +- accounts/abi/bind/bind_test.go | 6 ++++++ cmd/faucet/faucet_test.go | 7 +++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b0e543a3f316..e6a61919368a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -31,7 +31,7 @@ jobs: run: go run ./build/ci.go lint - name: Test - run: SKIP_ANDROID=true go run ./build/ci.go test + run: SKIP_ANDROID=true SKIP_FACEBOOK_TEST=true SKIP_GOLANG_BINDINGS_TEST go run ./build/ci.go test build: strategy: diff --git a/accounts/abi/bind/bind_test.go b/accounts/abi/bind/bind_test.go index d0958cb62f9a..d2276b0eb3b8 100644 --- a/accounts/abi/bind/bind_test.go +++ b/accounts/abi/bind/bind_test.go @@ -1790,6 +1790,12 @@ var bindTests = []struct { // Tests that packages generated by the binder can be successfully compiled and // the requested tester run against it. func TestGolangBindings(t *testing.T) { + if os.Getenv("SKIP_GOLANG_BINDINGS_TEST") != "" { + t.Skip() + + return + } + // Skip the test if no Go command can be found gocmd := runtime.GOROOT() + "/bin/go" if !common.FileExist(gocmd) { diff --git a/cmd/faucet/faucet_test.go b/cmd/faucet/faucet_test.go index 4f3e47084e3f..232eb1736de8 100644 --- a/cmd/faucet/faucet_test.go +++ b/cmd/faucet/faucet_test.go @@ -17,12 +17,19 @@ package main import ( + "os" "testing" "github.com/ethereum/go-ethereum/common" ) func TestFacebook(t *testing.T) { + if os.Getenv("SKIP_FACEBOOK_TEST") != "" { + t.Skip() + + return + } + for _, tt := range []struct { url string want common.Address From 3cb4f73913e83e16ff2f515e776587b76218a6c8 Mon Sep 17 00:00:00 2001 From: blazejkrzak Date: Fri, 13 Aug 2021 13:02:39 +0200 Subject: [PATCH 15/33] Test suite: - added skip on facebook test and golang binding test --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e6a61919368a..77a6456215e8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -31,7 +31,7 @@ jobs: run: go run ./build/ci.go lint - name: Test - run: SKIP_ANDROID=true SKIP_FACEBOOK_TEST=true SKIP_GOLANG_BINDINGS_TEST go run ./build/ci.go test + run: SKIP_ANDROID=true SKIP_FACEBOOK_TEST=true SKIP_GOLANG_BINDINGS_TEST=true go run ./build/ci.go test build: strategy: From 5fcb2374738a7f994cf96ff4b24d0731f460262d Mon Sep 17 00:00:00 2001 From: blazejkrzak Date: Thu, 19 Aug 2021 12:17:04 +0200 Subject: [PATCH 16/33] Fix: panic on glibc ci/cd Try to support ubuntu 18.04 --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b696041e3311..bc97d68df824 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: matrix: go-version: [ 1.16 ] # Add additional platforms here if we need more - platform: [ ubuntu-latest ] + platform: [ ubuntu-18.04 ] runs-on: ${{ matrix.platform }} steps: From 9b2136db030f275161dde4c0ae30d1910aec32bc Mon Sep 17 00:00:00 2001 From: blazejkrzak Date: Thu, 19 Aug 2021 12:59:26 +0200 Subject: [PATCH 17/33] Fix: panic on glibc ci/cd Fix in test about epochInfo turned to cache --- consensus/pandora/pandora_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/consensus/pandora/pandora_test.go b/consensus/pandora/pandora_test.go index add82c1ba073..c2a78e35f9a9 100644 --- a/consensus/pandora/pandora_test.go +++ b/consensus/pandora/pandora_test.go @@ -301,12 +301,12 @@ func TestPandora_Start(t *testing.T) { publicKeys := [32]bls_common.PublicKey{} publicKeys[1] = privKey.PublicKey() - pandoraEngine.epochInfos[0] = &EpochInfo{ + pandoraEngine.epochInfos.Add(uint64(0), &EpochInfo{ Epoch: 0, ValidatorList: publicKeys, EpochTimeStart: 0, SlotTimeDuration: DefaultSlotTimeDuration, - } + }) firstBlock := types.NewBlock(firstHeader, nil, nil, nil, nil) From e1d89d2d428035114f7caaa52fb219a8c683829f Mon Sep 17 00:00:00 2001 From: blazejkrzak Date: Wed, 25 Aug 2021 09:29:56 +0200 Subject: [PATCH 18/33] Feature: l15 faucet Added faucet support and docker build --- cmd/faucet/.dockerignore | 2 + cmd/faucet/Dockerfile | 11 +++++ cmd/faucet/faucet.go | 15 ++++++- cmd/faucet/faucet.html | 17 ++++---- cmd/faucet/website.go | 90 ++++++++++++---------------------------- go.mod | 1 + go.sum | 2 + les/client.go | 2 +- 8 files changed, 67 insertions(+), 73 deletions(-) create mode 100644 cmd/faucet/.dockerignore create mode 100644 cmd/faucet/Dockerfile diff --git a/cmd/faucet/.dockerignore b/cmd/faucet/.dockerignore new file mode 100644 index 000000000000..5846fc46dbbe --- /dev/null +++ b/cmd/faucet/.dockerignore @@ -0,0 +1,2 @@ +Dockerfile +faucet_test.go diff --git a/cmd/faucet/Dockerfile b/cmd/faucet/Dockerfile new file mode 100644 index 000000000000..fc2320a87000 --- /dev/null +++ b/cmd/faucet/Dockerfile @@ -0,0 +1,11 @@ +FROM golang:1.16-stretch + +WORKDIR /go/src/app +COPY . . + +RUN go mod init && go mod tidy +RUN go get -d -v ./... +RUN go build -o ./faucet -v . +RUN mv ./faucet /usr/local/go/bin + +CMD ["faucet"] \ No newline at end of file diff --git a/cmd/faucet/faucet.go b/cmd/faucet/faucet.go index e839f1c886d1..84452350a8c7 100644 --- a/cmd/faucet/faucet.go +++ b/cmd/faucet/faucet.go @@ -85,6 +85,7 @@ var ( twitterTokenFlag = flag.String("twitter.token", "", "Bearer token to authenticate with the v2 Twitter API") twitterTokenV1Flag = flag.String("twitter.token.v1", "", "Bearer token to authenticate with the v1.1 Twitter API") + notifyFlag = flag.String("pandora.notify", "", "Comma separated URLs for Pandora engine") ) var ( @@ -153,7 +154,9 @@ func main() { log.Crit("Failed to parse genesis block json", "err", err) } // Convert the bootnodes to internal enode representations - var enodes []*enode.Node + var ( + enodes []*enode.Node + ) for _, boot := range strings.Split(*bootFlag, ",") { if url, err := enode.Parse(enode.ValidSchemes, boot); err == nil { enodes = append(enodes, url) @@ -161,6 +164,7 @@ func main() { log.Error("Failed to parse bootnode URL", "url", boot, "err", err) } } + // Load up the account key and decrypt its password if blob, err = ioutil.ReadFile(*accPassFlag); err != nil { log.Crit("Failed to read account password contents", "file", *accPassFlag, "err", err) @@ -229,6 +233,13 @@ type wsConn struct { func newFaucet(genesis *core.Genesis, port int, enodes []*enode.Node, network uint64, stats string, ks *keystore.KeyStore, index []byte) (*faucet, error) { // Assemble the raw devp2p protocol stack + notifyUrls := strings.Split(*notifyFlag, ",") + cfg := ethconfig.Defaults + + if len(notifyUrls) > 0 { + cfg.Miner.Notify = notifyUrls + } + stack, err := node.New(&node.Config{ Name: "geth", Version: params.VersionWithCommit(gitCommit, gitDate), @@ -247,7 +258,7 @@ func newFaucet(genesis *core.Genesis, port int, enodes []*enode.Node, network ui } // Assemble the Ethereum light client protocol - cfg := ethconfig.Defaults + cfg.SyncMode = downloader.LightSync cfg.NetworkId = network cfg.Genesis = genesis diff --git a/cmd/faucet/faucet.html b/cmd/faucet/faucet.html index dad5ad84f210..25695bf761b4 100644 --- a/cmd/faucet/faucet.html +++ b/cmd/faucet/faucet.html @@ -16,6 +16,9 @@