github.com/electroneum/electroneum-sc@v0.0.0-20230105223411-3bc1d078281e/consensus/istanbul/backend/handler_test.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package backend
    18  
    19  import (
    20  	"bytes"
    21  	"io"
    22  	"math/big"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/electroneum/electroneum-sc/common"
    27  	"github.com/electroneum/electroneum-sc/consensus/istanbul"
    28  	"github.com/electroneum/electroneum-sc/core/types"
    29  	"github.com/electroneum/electroneum-sc/p2p"
    30  	"github.com/electroneum/electroneum-sc/rlp"
    31  	"github.com/electroneum/electroneum-sc/trie"
    32  )
    33  
    34  func tryUntilMessageIsHandled(backend *Backend, arbitraryAddress common.Address, arbitraryP2PMessage p2p.Msg) (handled bool, err error) {
    35  	for i := 0; i < 5; i++ { // make 5 tries if a little wait
    36  		handled, err = backend.HandleMsg(arbitraryAddress, arbitraryP2PMessage)
    37  		if handled && err == nil {
    38  			return
    39  		}
    40  		time.Sleep(2 * time.Millisecond)
    41  	}
    42  	return
    43  }
    44  
    45  func TestHandleNewBlockMessage_whenTypical(t *testing.T) {
    46  	_, backend := newBlockChain(1)
    47  	defer backend.Stop()
    48  	arbitraryAddress := common.StringToAddress("arbitrary")
    49  	arbitraryBlock, arbitraryP2PMessage := buildArbitraryP2PNewBlockMessage(t, false)
    50  	postAndWait(backend, arbitraryBlock, t)
    51  
    52  	handled, err := tryUntilMessageIsHandled(backend, arbitraryAddress, arbitraryP2PMessage)
    53  	if err != nil {
    54  		t.Errorf("expected message being handled successfully but got %s", err)
    55  	}
    56  	if !handled {
    57  		t.Errorf("expected message being handled but not")
    58  	}
    59  	if _, err := io.ReadAll(arbitraryP2PMessage.Payload); err != nil {
    60  		t.Errorf("expected p2p message payload is restored")
    61  	}
    62  }
    63  
    64  func TestHandleNewBlockMessage_whenNotAProposedBlock(t *testing.T) {
    65  	_, backend := newBlockChain(1)
    66  	defer backend.Stop()
    67  	arbitraryAddress := common.StringToAddress("arbitrary")
    68  	_, arbitraryP2PMessage := buildArbitraryP2PNewBlockMessage(t, false)
    69  	postAndWait(backend, types.NewBlock(&types.Header{
    70  		Number:    big.NewInt(1),
    71  		Root:      common.StringToHash("someroot"),
    72  		GasLimit:  1,
    73  		MixDigest: types.IstanbulDigest,
    74  	}, nil, nil, nil, new(trie.Trie)), t)
    75  
    76  	handled, err := tryUntilMessageIsHandled(backend, arbitraryAddress, arbitraryP2PMessage)
    77  	if err != nil {
    78  		t.Errorf("expected message being handled successfully but got %s", err)
    79  	}
    80  	if handled {
    81  		t.Errorf("expected message not being handled")
    82  	}
    83  	if _, err := io.ReadAll(arbitraryP2PMessage.Payload); err != nil {
    84  		t.Errorf("expected p2p message payload is restored")
    85  	}
    86  }
    87  
    88  func TestHandleNewBlockMessage_whenFailToDecode(t *testing.T) {
    89  	_, backend := newBlockChain(1)
    90  	defer backend.Stop()
    91  	arbitraryAddress := common.StringToAddress("arbitrary")
    92  	_, arbitraryP2PMessage := buildArbitraryP2PNewBlockMessage(t, true)
    93  	postAndWait(backend, types.NewBlock(&types.Header{
    94  		Number:    big.NewInt(1),
    95  		GasLimit:  1,
    96  		MixDigest: types.IstanbulDigest,
    97  	}, nil, nil, nil, new(trie.Trie)), t)
    98  
    99  	handled, err := tryUntilMessageIsHandled(backend, arbitraryAddress, arbitraryP2PMessage)
   100  	if err != nil {
   101  		t.Errorf("expected message being handled successfully but got %s", err)
   102  	}
   103  	if handled {
   104  		t.Errorf("expected message not being handled")
   105  	}
   106  	if _, err := io.ReadAll(arbitraryP2PMessage.Payload); err != nil {
   107  		t.Errorf("expected p2p message payload is restored")
   108  	}
   109  }
   110  
   111  func postAndWait(backend *Backend, block *types.Block, t *testing.T) {
   112  	eventSub := backend.EventMux().Subscribe(istanbul.RequestEvent{})
   113  	defer eventSub.Unsubscribe()
   114  	stop := make(chan struct{}, 1)
   115  	eventLoop := func() {
   116  		<-eventSub.Chan()
   117  		stop <- struct{}{}
   118  	}
   119  	go eventLoop()
   120  	if err := backend.EventMux().Post(istanbul.RequestEvent{
   121  		Proposal: block,
   122  	}); err != nil {
   123  		t.Fatalf("%s", err)
   124  	}
   125  	<-stop
   126  }
   127  
   128  func buildArbitraryP2PNewBlockMessage(t *testing.T, invalidMsg bool) (*types.Block, p2p.Msg) {
   129  	arbitraryBlock := types.NewBlock(&types.Header{
   130  		Number:    big.NewInt(1),
   131  		GasLimit:  0,
   132  		MixDigest: types.IstanbulDigest,
   133  	}, nil, nil, nil, new(trie.Trie))
   134  	request := []interface{}{&arbitraryBlock, big.NewInt(1)}
   135  	if invalidMsg {
   136  		request = []interface{}{"invalid msg"}
   137  	}
   138  	size, r, err := rlp.EncodeToReader(request)
   139  	if err != nil {
   140  		t.Fatalf("can't encode due to %s", err)
   141  	}
   142  	payload, err := io.ReadAll(r)
   143  	if err != nil {
   144  		t.Fatalf("can't read payload due to %s", err)
   145  	}
   146  	arbitraryP2PMessage := p2p.Msg{Code: 0x07, Size: uint32(size), Payload: bytes.NewReader(payload)}
   147  	return arbitraryBlock, arbitraryP2PMessage
   148  }