github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/consensus/pbft/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  	"fmt"
    22  	"io/ioutil"
    23  	"math/big"
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/bigzoro/my_simplechain/common"
    28  	"github.com/bigzoro/my_simplechain/consensus/pbft"
    29  	"github.com/bigzoro/my_simplechain/core/types"
    30  	"github.com/bigzoro/my_simplechain/p2p"
    31  	"github.com/bigzoro/my_simplechain/rlp"
    32  	lru "github.com/hashicorp/golang-lru"
    33  )
    34  
    35  func TestIstanbulMessage(t *testing.T) {
    36  	_, backend := newBlockChain(1)
    37  
    38  	// generate one msg
    39  	data := []byte("data1")
    40  	hash := pbft.RLPHash(data)
    41  	msg := makeMsg(PbftMsg, data)
    42  	addr := common.BytesToAddress([]byte("address"))
    43  
    44  	// 1. this message should not be in cache
    45  	// for peers
    46  	if _, ok := backend.recentMessages.Get(addr); ok {
    47  		t.Fatalf("the cache of messages for this peer should be nil")
    48  	}
    49  
    50  	// for self
    51  	if _, ok := backend.knownMessages.Get(hash); ok {
    52  		t.Fatalf("the cache of messages should be nil")
    53  	}
    54  
    55  	// 2. this message should be in cache after we handle it
    56  	_, err := backend.HandleMsg(addr, msg)
    57  	if err != nil {
    58  		t.Fatalf("handle message failed: %v", err)
    59  	}
    60  	// for peers
    61  	if ms, ok := backend.recentMessages.Get(addr); ms == nil || !ok {
    62  		t.Fatalf("the cache of messages for this peer cannot be nil")
    63  	} else if m, ok := ms.(*lru.ARCCache); !ok {
    64  		t.Fatalf("the cache of messages for this peer cannot be casted")
    65  	} else if _, ok := m.Get(hash); !ok {
    66  		t.Fatalf("the cache of messages for this peer cannot be found")
    67  	}
    68  
    69  	// for self
    70  	if _, ok := backend.knownMessages.Get(hash); !ok {
    71  		t.Fatalf("the cache of messages cannot be found")
    72  	}
    73  }
    74  
    75  func makeMsg(msgcode uint64, data interface{}) p2p.Msg {
    76  	size, r, _ := rlp.EncodeToReader(data)
    77  	return p2p.Msg{Code: msgcode, Size: uint32(size), Payload: r}
    78  }
    79  
    80  func TestHandleNewBlockMessage_whenTypical(t *testing.T) {
    81  	_, backend := newBlockChain(1)
    82  	arbitraryAddress := common.BytesToAddress([]byte("arbitrary"))
    83  	arbitraryBlock, arbitraryP2PMessage := buildArbitraryP2PNewBlockMessage(t, false)
    84  	postAndWait(backend, arbitraryBlock, t)
    85  
    86  	handled, err := backend.HandleMsg(arbitraryAddress, arbitraryP2PMessage)
    87  
    88  	if err != nil {
    89  		t.Errorf("expected message being handled successfully but got %s", err)
    90  	}
    91  	if !handled {
    92  		t.Errorf("expected message being handled but not")
    93  	}
    94  	if _, err := ioutil.ReadAll(arbitraryP2PMessage.Payload); err != nil {
    95  		t.Errorf("expected p2p message payload is restored")
    96  	}
    97  }
    98  
    99  func TestHandleNewBlockMessage_whenNotAProposedBlock(t *testing.T) {
   100  	_, backend := newBlockChain(1)
   101  	arbitraryAddress := common.BytesToAddress([]byte("arbitrary"))
   102  	arbitraryBlock, arbitraryP2PMessage := buildArbitraryP2PNewBlockMessage(t, false)
   103  
   104  	proposeBlock := types.NewBlock(&types.Header{
   105  		Number:    big.NewInt(1),
   106  		Root:      common.BytesToHash([]byte("someroot")),
   107  		GasLimit:  10000,
   108  		MixDigest: types.PbftDigest,
   109  	}, nil, nil, nil)
   110  
   111  	postAndWait(backend, proposeBlock, t)
   112  
   113  	fmt.Println(arbitraryBlock.PendingHash().String())
   114  	fmt.Println(proposeBlock.PendingHash().String())
   115  
   116  	handled, err := backend.HandleMsg(arbitraryAddress, arbitraryP2PMessage)
   117  
   118  	if err != nil {
   119  		t.Errorf("expected message being handled successfully but got %s", err)
   120  	}
   121  	if handled {
   122  		t.Errorf("expected message not being handled")
   123  	}
   124  	if _, err := ioutil.ReadAll(arbitraryP2PMessage.Payload); err != nil {
   125  		t.Errorf("expected p2p message payload is restored")
   126  	}
   127  }
   128  
   129  func TestHandleNewBlockMessage_whenFailToDecode(t *testing.T) {
   130  	_, backend := newBlockChain(1)
   131  	arbitraryAddress := common.BytesToAddress([]byte("arbitrary"))
   132  	_, arbitraryP2PMessage := buildArbitraryP2PNewBlockMessage(t, true)
   133  	postAndWait(backend, types.NewBlock(&types.Header{
   134  		Number:    big.NewInt(1),
   135  		GasLimit:  1,
   136  		MixDigest: types.PbftDigest,
   137  	}, nil, nil, nil), t)
   138  
   139  	handled, err := backend.HandleMsg(arbitraryAddress, arbitraryP2PMessage)
   140  
   141  	if err != nil {
   142  		t.Errorf("expected message being handled successfully but got %s", err)
   143  	}
   144  	if handled {
   145  		t.Errorf("expected message not being handled")
   146  	}
   147  	if _, err := ioutil.ReadAll(arbitraryP2PMessage.Payload); err != nil {
   148  		t.Errorf("expected p2p message payload is restored")
   149  	}
   150  }
   151  
   152  func postAndWait(backend *backend, block *types.Block, t *testing.T) {
   153  	eventSub := backend.EventMux().Subscribe(pbft.RequestEvent{})
   154  	defer eventSub.Unsubscribe()
   155  	stop := make(chan struct{}, 1)
   156  	eventLoop := func() {
   157  		<-eventSub.Chan()
   158  		// block until handleRequire finished
   159  		time.Sleep(time.Millisecond * 10)
   160  		stop <- struct{}{}
   161  	}
   162  	go eventLoop()
   163  	if err := backend.EventMux().Post(pbft.RequestEvent{
   164  		Proposal: block,
   165  	}); err != nil {
   166  		t.Fatalf("%s", err)
   167  	}
   168  	<-stop
   169  }
   170  
   171  func buildArbitraryP2PNewBlockMessage(t *testing.T, invalidMsg bool) (*types.Block, p2p.Msg) {
   172  	arbitraryBlock := types.NewBlock(&types.Header{
   173  		Number:    big.NewInt(1),
   174  		GasLimit:  0,
   175  		MixDigest: types.PbftDigest,
   176  	}, nil, nil, nil)
   177  	request := []interface{}{&arbitraryBlock, big.NewInt(1)}
   178  	if invalidMsg {
   179  		request = []interface{}{"invalid msg"}
   180  	}
   181  	size, r, err := rlp.EncodeToReader(request)
   182  	if err != nil {
   183  		t.Fatalf("can't encode due to %s", err)
   184  	}
   185  	payload, err := ioutil.ReadAll(r)
   186  	if err != nil {
   187  		t.Fatalf("can't read payload due to %s", err)
   188  	}
   189  	arbitraryP2PMessage := p2p.Msg{Code: 0x07, Size: uint32(size), Payload: bytes.NewReader(payload)}
   190  	return arbitraryBlock, arbitraryP2PMessage
   191  }