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 }