github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/native/event_serializer_test.go (about)

     1  package native
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"math"
     7  	"math/big"
     8  	"math/rand"
     9  	"testing"
    10  
    11  	"github.com/stretchr/testify/require"
    12  	"github.com/unicornultrafoundation/go-u2u/common"
    13  	"github.com/unicornultrafoundation/go-u2u/core/types"
    14  	"github.com/unicornultrafoundation/go-u2u/rlp"
    15  
    16  	"github.com/unicornultrafoundation/go-helios/hash"
    17  	"github.com/unicornultrafoundation/go-helios/native/idx"
    18  )
    19  
    20  func emptyEvent(ver uint8) EventPayload {
    21  	empty := MutableEventPayload{}
    22  	empty.SetVersion(ver)
    23  	if ver == 0 {
    24  		empty.SetEpoch(256)
    25  	}
    26  	empty.SetParents(hash.Events{})
    27  	empty.SetExtra([]byte{})
    28  	empty.SetTxs(types.Transactions{})
    29  	empty.SetPayloadHash(EmptyPayloadHash(ver))
    30  	return *empty.Build()
    31  }
    32  
    33  func TestEventPayloadSerialization(t *testing.T) {
    34  	max := MutableEventPayload{}
    35  	max.SetEpoch(math.MaxUint32)
    36  	max.SetSeq(idx.Event(math.MaxUint32))
    37  	max.SetLamport(idx.Lamport(math.MaxUint32))
    38  	h := hash.BytesToEvent(bytes.Repeat([]byte{math.MaxUint8}, 32))
    39  	max.SetParents(hash.Events{hash.Event(h), hash.Event(h), hash.Event(h)})
    40  	max.SetPayloadHash(hash.Hash(h))
    41  	max.SetSig(BytesToSignature(bytes.Repeat([]byte{math.MaxUint8}, SigSize)))
    42  	max.SetExtra(bytes.Repeat([]byte{math.MaxUint8}, 100))
    43  	max.SetCreationTime(math.MaxUint64)
    44  	max.SetMedianTime(math.MaxUint64)
    45  	tx1 := types.NewTx(&types.LegacyTx{
    46  		Nonce:    math.MaxUint64,
    47  		GasPrice: h.Big(),
    48  		Gas:      math.MaxUint64,
    49  		To:       nil,
    50  		Value:    h.Big(),
    51  		Data:     []byte{},
    52  		V:        big.NewInt(0xff),
    53  		R:        h.Big(),
    54  		S:        h.Big(),
    55  	})
    56  	tx2 := types.NewTx(&types.LegacyTx{
    57  		Nonce:    math.MaxUint64,
    58  		GasPrice: h.Big(),
    59  		Gas:      math.MaxUint64,
    60  		To:       &common.Address{},
    61  		Value:    h.Big(),
    62  		Data:     max.extra,
    63  		V:        big.NewInt(0xff),
    64  		R:        h.Big(),
    65  		S:        h.Big(),
    66  	})
    67  	txs := types.Transactions{}
    68  	for i := 0; i < 200; i++ {
    69  		txs = append(txs, tx1)
    70  		txs = append(txs, tx2)
    71  	}
    72  	max.SetTxs(txs)
    73  
    74  	ee := map[string]EventPayload{
    75  		"empty0": emptyEvent(0),
    76  		"empty1": emptyEvent(1),
    77  		"max":    *max.Build(),
    78  		"random": *FakeEvent(12, 1, 1, true),
    79  	}
    80  
    81  	t.Run("ok", func(t *testing.T) {
    82  		require := require.New(t)
    83  
    84  		for name, header0 := range ee {
    85  			buf, err := rlp.EncodeToBytes(&header0)
    86  			require.NoError(err)
    87  
    88  			var header1 EventPayload
    89  			err = rlp.DecodeBytes(buf, &header1)
    90  			require.NoError(err, name)
    91  
    92  			require.EqualValues(header0.extEventData, header1.extEventData, name)
    93  			require.EqualValues(header0.sigData, header1.sigData, name)
    94  			for i := range header0.payloadData.txs {
    95  				require.EqualValues(header0.payloadData.txs[i].Hash(), header1.payloadData.txs[i].Hash(), name)
    96  			}
    97  			require.EqualValues(header0.baseEvent, header1.baseEvent, name)
    98  			require.EqualValues(header0.ID(), header1.ID(), name)
    99  			require.EqualValues(header0.HashToSign(), header1.HashToSign(), name)
   100  			require.EqualValues(header0.Size(), header1.Size(), name)
   101  		}
   102  	})
   103  
   104  	t.Run("err", func(t *testing.T) {
   105  		require := require.New(t)
   106  
   107  		for name, header0 := range ee {
   108  			bin, err := header0.MarshalBinary()
   109  			require.NoError(err, name)
   110  
   111  			n := rand.Intn(len(bin) - len(header0.Extra()) - 1)
   112  			bin = bin[0:n]
   113  
   114  			buf, err := rlp.EncodeToBytes(bin)
   115  			require.NoError(err, name)
   116  
   117  			var header1 Event
   118  			err = rlp.DecodeBytes(buf, &header1)
   119  			require.Error(err, name)
   120  		}
   121  	})
   122  }
   123  
   124  func BenchmarkEventPayload_EncodeRLP_empty(b *testing.B) {
   125  	e := emptyEvent(0)
   126  
   127  	b.ResetTimer()
   128  
   129  	for i := 0; i < b.N; i++ {
   130  		buf, err := rlp.EncodeToBytes(&e)
   131  		if err != nil {
   132  			b.Fatal(err)
   133  		}
   134  		b.ReportMetric(float64(len(buf)), "size")
   135  	}
   136  }
   137  
   138  func BenchmarkEventPayload_EncodeRLP_NoPayload(b *testing.B) {
   139  	e := FakeEvent(0, 0, 0, false)
   140  
   141  	b.ResetTimer()
   142  
   143  	for i := 0; i < b.N; i++ {
   144  		buf, err := rlp.EncodeToBytes(&e)
   145  		if err != nil {
   146  			b.Fatal(err)
   147  		}
   148  		b.ReportMetric(float64(len(buf)), "size")
   149  	}
   150  }
   151  
   152  func BenchmarkEventPayload_EncodeRLP(b *testing.B) {
   153  	e := FakeEvent(1000, 0, 0, false)
   154  
   155  	b.ResetTimer()
   156  
   157  	for i := 0; i < b.N; i++ {
   158  		buf, err := rlp.EncodeToBytes(&e)
   159  		if err != nil {
   160  			b.Fatal(err)
   161  		}
   162  		b.ReportMetric(float64(len(buf)), "size")
   163  	}
   164  }
   165  
   166  func BenchmarkEventPayload_DecodeRLP_empty(b *testing.B) {
   167  	e := emptyEvent(0)
   168  	me := MutableEventPayload{}
   169  
   170  	buf, err := rlp.EncodeToBytes(&e)
   171  	if err != nil {
   172  		b.Fatal(err)
   173  	}
   174  
   175  	b.ResetTimer()
   176  
   177  	for i := 0; i < b.N; i++ {
   178  		err = rlp.DecodeBytes(buf, &me)
   179  		if err != nil {
   180  			b.Fatal(err)
   181  		}
   182  	}
   183  }
   184  
   185  func BenchmarkEventPayload_DecodeRLP_NoPayload(b *testing.B) {
   186  	e := FakeEvent(0, 0, 0, false)
   187  	me := MutableEventPayload{}
   188  
   189  	buf, err := rlp.EncodeToBytes(&e)
   190  	if err != nil {
   191  		b.Fatal(err)
   192  	}
   193  
   194  	b.ResetTimer()
   195  
   196  	for i := 0; i < b.N; i++ {
   197  		err = rlp.DecodeBytes(buf, &me)
   198  		if err != nil {
   199  			b.Fatal(err)
   200  		}
   201  	}
   202  }
   203  
   204  func BenchmarkEventPayload_DecodeRLP(b *testing.B) {
   205  	e := FakeEvent(1000, 0, 0, false)
   206  	me := MutableEventPayload{}
   207  
   208  	buf, err := rlp.EncodeToBytes(&e)
   209  	if err != nil {
   210  		b.Fatal(err)
   211  	}
   212  
   213  	b.ResetTimer()
   214  
   215  	for i := 0; i < b.N; i++ {
   216  		err = rlp.DecodeBytes(buf, &me)
   217  		if err != nil {
   218  			b.Fatal(err)
   219  		}
   220  	}
   221  }
   222  
   223  func TestEventRPCMarshaling(t *testing.T) {
   224  	t.Run("Event", func(t *testing.T) {
   225  		require := require.New(t)
   226  		for i := 0; i < 3; i++ {
   227  			var event0 EventI = &FakeEvent(i, i, i, i != 0).Event
   228  			mapping := RPCMarshalEvent(event0)
   229  			bb, err := json.Marshal(mapping)
   230  			require.NoError(err)
   231  
   232  			mapping = make(map[string]interface{})
   233  			err = json.Unmarshal(bb, &mapping)
   234  			require.NoError(err)
   235  			event1 := RPCUnmarshalEvent(mapping)
   236  
   237  			require.Equal(event0, event1, i)
   238  		}
   239  	})
   240  
   241  	t.Run("EventPayload", func(t *testing.T) {
   242  		require := require.New(t)
   243  		for i := 0; i < 3; i++ {
   244  			var event0 = FakeEvent(i, i, i, i != 0)
   245  			mapping, err := RPCMarshalEventPayload(event0, true, false)
   246  			require.NoError(err)
   247  			bb, err := json.Marshal(mapping)
   248  			require.NoError(err)
   249  
   250  			mapping = make(map[string]interface{})
   251  			err = json.Unmarshal(bb, &mapping)
   252  
   253  			event1 := RPCUnmarshalEvent(mapping)
   254  			require.Equal(&event0.SignedEvent.Event, event1, i)
   255  		}
   256  	})
   257  }
   258  
   259  func randBig(r *rand.Rand) *big.Int {
   260  	b := make([]byte, r.Intn(8))
   261  	_, _ = r.Read(b)
   262  	if len(b) == 0 {
   263  		b = []byte{0}
   264  	}
   265  	return new(big.Int).SetBytes(b)
   266  }
   267  
   268  func randAddr(r *rand.Rand) common.Address {
   269  	addr := common.Address{}
   270  	r.Read(addr[:])
   271  	return addr
   272  }
   273  
   274  func randBytes(r *rand.Rand, size int) []byte {
   275  	b := make([]byte, size)
   276  	r.Read(b)
   277  	return b
   278  }
   279  
   280  func randHash(r *rand.Rand) hash.Hash {
   281  	return hash.BytesToHash(randBytes(r, 32))
   282  }
   283  
   284  func randAddrPtr(r *rand.Rand) *common.Address {
   285  	addr := randAddr(r)
   286  	return &addr
   287  }
   288  
   289  func randAccessList(r *rand.Rand, maxAddrs, maxKeys int) types.AccessList {
   290  	accessList := make(types.AccessList, r.Intn(maxAddrs))
   291  	for i := range accessList {
   292  		accessList[i].Address = randAddr(r)
   293  		accessList[i].StorageKeys = make([]common.Hash, r.Intn(maxKeys))
   294  		for j := range accessList[i].StorageKeys {
   295  			r.Read(accessList[i].StorageKeys[j][:])
   296  		}
   297  	}
   298  	return accessList
   299  }
   300  
   301  // FakeEvent generates random event for testing purpose.
   302  func FakeEvent(txsNum, mpsNum, bvsNum int, ersNum bool) *EventPayload {
   303  	r := rand.New(rand.NewSource(int64(0)))
   304  	random := &MutableEventPayload{}
   305  	random.SetVersion(1)
   306  	random.SetNetForkID(uint16(r.Uint32() >> 16))
   307  	random.SetLamport(1000)
   308  	random.SetExtra([]byte{byte(r.Uint32())})
   309  	random.SetSeq(idx.Event(r.Uint32() >> 8))
   310  	random.SetCreator(idx.ValidatorID(r.Uint32()))
   311  	random.SetFrame(idx.Frame(r.Uint32() >> 16))
   312  	random.SetCreationTime(Timestamp(r.Uint64()))
   313  	random.SetMedianTime(Timestamp(r.Uint64()))
   314  	random.SetGasPowerUsed(r.Uint64())
   315  	random.SetGasPowerLeft(GasPowerLeft{[2]uint64{r.Uint64(), r.Uint64()}})
   316  	txs := types.Transactions{}
   317  	for i := 0; i < txsNum; i++ {
   318  		h := hash.Hash{}
   319  		r.Read(h[:])
   320  		if i%3 == 0 {
   321  			tx := types.NewTx(&types.LegacyTx{
   322  				Nonce:    r.Uint64(),
   323  				GasPrice: randBig(r),
   324  				Gas:      257 + r.Uint64(),
   325  				To:       nil,
   326  				Value:    randBig(r),
   327  				Data:     randBytes(r, r.Intn(300)),
   328  				V:        big.NewInt(int64(r.Intn(0xffffffff))),
   329  				R:        h.Big(),
   330  				S:        h.Big(),
   331  			})
   332  			txs = append(txs, tx)
   333  		} else if i%3 == 1 {
   334  			tx := types.NewTx(&types.AccessListTx{
   335  				ChainID:    randBig(r),
   336  				Nonce:      r.Uint64(),
   337  				GasPrice:   randBig(r),
   338  				Gas:        r.Uint64(),
   339  				To:         randAddrPtr(r),
   340  				Value:      randBig(r),
   341  				Data:       randBytes(r, r.Intn(300)),
   342  				AccessList: randAccessList(r, 300, 300),
   343  				V:          big.NewInt(int64(r.Intn(0xffffffff))),
   344  				R:          h.Big(),
   345  				S:          h.Big(),
   346  			})
   347  			txs = append(txs, tx)
   348  		} else {
   349  			tx := types.NewTx(&types.DynamicFeeTx{
   350  				ChainID:    randBig(r),
   351  				Nonce:      r.Uint64(),
   352  				GasTipCap:  randBig(r),
   353  				GasFeeCap:  randBig(r),
   354  				Gas:        r.Uint64(),
   355  				To:         randAddrPtr(r),
   356  				Value:      randBig(r),
   357  				Data:       randBytes(r, r.Intn(300)),
   358  				AccessList: randAccessList(r, 300, 300),
   359  				V:          big.NewInt(int64(r.Intn(0xffffffff))),
   360  				R:          h.Big(),
   361  				S:          h.Big(),
   362  			})
   363  			txs = append(txs, tx)
   364  		}
   365  	}
   366  	mps := []MisbehaviourProof{}
   367  	for i := 0; i < mpsNum; i++ {
   368  		// MPs are serialized with RLP, so no need to test extensively
   369  		mps = append(mps, MisbehaviourProof{
   370  			EventsDoublesign: &EventsDoublesign{
   371  				Pair: [2]SignedEventLocator{SignedEventLocator{}, SignedEventLocator{}},
   372  			},
   373  			BlockVoteDoublesign: nil,
   374  			WrongBlockVote:      nil,
   375  			EpochVoteDoublesign: nil,
   376  			WrongEpochVote:      nil,
   377  		})
   378  	}
   379  	bvs := LlrBlockVotes{}
   380  	if bvsNum > 0 {
   381  		bvs.Start = 1 + idx.Block(rand.Intn(1000))
   382  		bvs.Epoch = 1 + idx.Epoch(rand.Intn(1000))
   383  	}
   384  	for i := 0; i < bvsNum; i++ {
   385  		bvs.Votes = append(bvs.Votes, randHash(r))
   386  	}
   387  	ers := LlrEpochVote{}
   388  	if ersNum {
   389  		ers.Epoch = 1 + idx.Epoch(rand.Intn(1000))
   390  		ers.Vote = randHash(r)
   391  	}
   392  
   393  	random.SetTxs(txs)
   394  	random.SetMisbehaviourProofs(mps)
   395  	random.SetEpochVote(ers)
   396  	random.SetBlockVotes(bvs)
   397  	random.SetPayloadHash(CalcPayloadHash(random))
   398  
   399  	parent := MutableEventPayload{}
   400  	parent.SetVersion(1)
   401  	parent.SetLamport(random.Lamport() - 500)
   402  	parent.SetEpoch(random.Epoch())
   403  	random.SetParents(hash.Events{parent.Build().ID()})
   404  
   405  	return random.Build()
   406  }