github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/evm/types/utils.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "encoding/hex" 6 "fmt" 7 abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types" 8 "math/big" 9 "math/bits" 10 "strings" 11 "sync" 12 13 "github.com/tendermint/go-amino" 14 15 ethcmn "github.com/ethereum/go-ethereum/common" 16 ethtypes "github.com/ethereum/go-ethereum/core/types" 17 ethcrypto "github.com/ethereum/go-ethereum/crypto" 18 "github.com/ethereum/go-ethereum/rlp" 19 "github.com/fibonacci-chain/fbc/app/crypto/ethsecp256k1" 20 "github.com/pkg/errors" 21 "golang.org/x/crypto/sha3" 22 ) 23 24 type KV struct { 25 Key []byte `json:"key"` 26 Value []byte `json:"value"` 27 } 28 29 // MarshalToAmino encode KV data to amino bytes 30 func (k *KV) MarshalToAmino(cdc *amino.Codec) ([]byte, error) { 31 var buf bytes.Buffer 32 var err error 33 fieldKeysType := [2]byte{1<<3 | 2, 2<<3 | 2} 34 for pos := 1; pos <= 2; pos++ { 35 switch pos { 36 case 1: 37 if len(k.Key) == 0 { 38 break 39 } 40 err = buf.WriteByte(fieldKeysType[pos-1]) 41 if err != nil { 42 return nil, err 43 } 44 err = amino.EncodeByteSliceToBuffer(&buf, k.Key) 45 if err != nil { 46 return nil, err 47 } 48 49 case 2: 50 if len(k.Value) == 0 { 51 break 52 } 53 err = buf.WriteByte(fieldKeysType[pos-1]) 54 if err != nil { 55 return nil, err 56 } 57 err = amino.EncodeByteSliceToBuffer(&buf, k.Value) 58 if err != nil { 59 return nil, err 60 } 61 62 default: 63 panic("unreachable") 64 } 65 } 66 return buf.Bytes(), nil 67 } 68 69 // UnmarshalFromAmino unmarshal amino bytes to this object 70 func (k *KV) UnmarshalFromAmino(_ *amino.Codec, data []byte) error { 71 var dataLen uint64 = 0 72 var subData []byte 73 74 for { 75 data = data[dataLen:] 76 if len(data) == 0 { 77 break 78 } 79 pos, pbType, err := amino.ParseProtoPosAndTypeMustOneByte(data[0]) 80 if err != nil { 81 return err 82 } 83 data = data[1:] 84 85 if pbType == amino.Typ3_ByteLength { 86 var n int 87 dataLen, n, _ = amino.DecodeUvarint(data) 88 89 data = data[n:] 90 if len(data) < int(dataLen) { 91 return errors.New("not enough data") 92 } 93 subData = data[:dataLen] 94 } 95 96 switch pos { 97 case 1: 98 k.Key = make([]byte, len(subData)) 99 copy(k.Key, subData) 100 101 case 2: 102 k.Value = make([]byte, len(subData)) 103 copy(k.Value, subData) 104 105 default: 106 return fmt.Errorf("unexpect feild num %d", pos) 107 } 108 } 109 return nil 110 } 111 112 // GenerateEthAddress generates an Ethereum address. 113 func GenerateEthAddress() ethcmn.Address { 114 priv, err := ethsecp256k1.GenerateKey() 115 if err != nil { 116 panic(err) 117 } 118 119 return ethcrypto.PubkeyToAddress(priv.ToECDSA().PublicKey) 120 } 121 122 // ValidateSigner attempts to validate a signer for a given slice of bytes over 123 // which a signature and signer is given. An error is returned if address 124 // derived from the signature and bytes signed does not match the given signer. 125 func ValidateSigner(signBytes, sig []byte, signer ethcmn.Address) error { 126 pk, err := ethcrypto.SigToPub(signBytes, sig) 127 128 if err != nil { 129 return errors.Wrap(err, "failed to derive public key from signature") 130 } else if ethcrypto.PubkeyToAddress(*pk) != signer { 131 return fmt.Errorf("invalid signature for signer: %s", signer) 132 } 133 134 return nil 135 } 136 137 func rlpHash(x interface{}) (hash ethcmn.Hash) { 138 hasher := sha3.NewLegacyKeccak256() 139 _ = rlp.Encode(hasher, x) 140 _ = hasher.Sum(hash[:0]) 141 142 return hash 143 } 144 145 func rlpHashTo(x interface{}, hash *ethcmn.Hash) { 146 hasher := keccakStatePool.Get().(ethcrypto.KeccakState) 147 defer keccakStatePool.Put(hasher) 148 hasher.Reset() 149 150 _ = rlp.Encode(hasher, x) 151 hasher.Read(hash[:]) 152 return 153 } 154 155 // ResultData represents the data returned in an sdk.Result 156 type ResultData struct { 157 ContractAddress ethcmn.Address `json:"contract_address"` 158 Bloom ethtypes.Bloom `json:"bloom"` 159 Logs []*ethtypes.Log `json:"logs"` 160 Ret []byte `json:"ret"` 161 TxHash ethcmn.Hash `json:"tx_hash"` 162 } 163 164 func UnmarshalEthLogFromAmino(data []byte) (*ethtypes.Log, error) { 165 var dataLen uint64 = 0 166 var subData []byte 167 log := ðtypes.Log{} 168 169 for { 170 data = data[dataLen:] 171 172 if len(data) == 0 { 173 break 174 } 175 176 pos, aminoType, err := amino.ParseProtoPosAndTypeMustOneByte(data[0]) 177 if err != nil { 178 return nil, err 179 } 180 data = data[1:] 181 182 if aminoType == amino.Typ3_ByteLength { 183 var n int 184 dataLen, n, err = amino.DecodeUvarint(data) 185 if err != nil { 186 return nil, err 187 } 188 189 data = data[n:] 190 if len(data) < int(dataLen) { 191 return nil, fmt.Errorf("invalid data length: %d", dataLen) 192 } 193 subData = data[:dataLen] 194 } 195 196 switch pos { 197 case 1: 198 if int(dataLen) != ethcmn.AddressLength { 199 return nil, fmt.Errorf("invalid address length: %d", dataLen) 200 } 201 copy(log.Address[:], subData) 202 case 2: 203 if int(dataLen) != ethcmn.HashLength { 204 return nil, fmt.Errorf("invalid topic hash length: %d", dataLen) 205 } 206 var hash ethcmn.Hash 207 copy(hash[:], subData) 208 log.Topics = append(log.Topics, hash) 209 case 3: 210 log.Data = make([]byte, dataLen) 211 copy(log.Data, subData) 212 case 4: 213 var n int 214 log.BlockNumber, n, err = amino.DecodeUvarint(data) 215 if err != nil { 216 return nil, err 217 } 218 dataLen = uint64(n) 219 case 5: 220 if int(dataLen) != ethcmn.HashLength { 221 return nil, fmt.Errorf("invalid topic hash length: %d", dataLen) 222 } 223 copy(log.TxHash[:], subData) 224 case 6: 225 var n int 226 var uv uint64 227 uv, n, err = amino.DecodeUvarint(data) 228 log.TxIndex = uint(uv) 229 if err != nil { 230 return nil, err 231 } 232 dataLen = uint64(n) 233 case 7: 234 if int(dataLen) != ethcmn.HashLength { 235 return nil, fmt.Errorf("invalid topic hash length: %d", dataLen) 236 } 237 copy(log.BlockHash[:], subData) 238 case 8: 239 var n int 240 var uv uint64 241 uv, n, err = amino.DecodeUvarint(data) 242 log.Index = uint(uv) 243 if err != nil { 244 return nil, err 245 } 246 dataLen = uint64(n) 247 case 9: 248 if data[0] == 0 { 249 log.Removed = false 250 } else if data[0] == 1 { 251 log.Removed = true 252 } else { 253 return nil, fmt.Errorf("invalid removed flag: %d", data[0]) 254 } 255 dataLen = 1 256 } 257 } 258 return log, nil 259 } 260 261 var ethLogBufferPool = amino.NewBufferPool() 262 263 func MarshalEthLogToAmino(log *ethtypes.Log) ([]byte, error) { 264 if log == nil { 265 return nil, nil 266 } 267 var buf = ethLogBufferPool.Get() 268 defer ethLogBufferPool.Put(buf) 269 fieldKeysType := [9]byte{1<<3 | 2, 2<<3 | 2, 3<<3 | 2, 4 << 3, 5<<3 | 2, 6 << 3, 7<<3 | 2, 8 << 3, 9 << 3} 270 for pos := 1; pos < 10; pos++ { 271 lBeforeKey := buf.Len() 272 var noWrite bool 273 err := buf.WriteByte(fieldKeysType[pos-1]) 274 if err != nil { 275 return nil, err 276 } 277 278 switch pos { 279 case 1: 280 err := buf.WriteByte(byte(ethcmn.AddressLength)) 281 if err != nil { 282 return nil, err 283 } 284 _, err = buf.Write(log.Address.Bytes()) 285 if err != nil { 286 return nil, err 287 } 288 case 2: 289 topicsLen := len(log.Topics) 290 if topicsLen == 0 { 291 noWrite = true 292 break 293 } 294 err = buf.WriteByte(byte(ethcmn.HashLength)) 295 if err != nil { 296 return nil, err 297 } 298 _, err = buf.Write(log.Topics[0].Bytes()) 299 if err != nil { 300 return nil, err 301 } 302 303 for i := 1; i < topicsLen; i++ { 304 err = buf.WriteByte(fieldKeysType[pos-1]) 305 if err != nil { 306 return nil, err 307 } 308 309 err = buf.WriteByte(byte(ethcmn.HashLength)) 310 if err != nil { 311 return nil, err 312 } 313 _, err = buf.Write(log.Topics[i].Bytes()) 314 if err != nil { 315 return nil, err 316 } 317 } 318 case 3: 319 dataLen := len(log.Data) 320 if dataLen == 0 { 321 noWrite = true 322 break 323 } 324 err = amino.EncodeUvarintToBuffer(buf, uint64(dataLen)) 325 if err != nil { 326 return nil, err 327 } 328 _, err = buf.Write(log.Data) 329 if err != nil { 330 return nil, err 331 } 332 case 4: 333 if log.BlockNumber == 0 { 334 noWrite = true 335 break 336 } 337 err = amino.EncodeUvarintToBuffer(buf, log.BlockNumber) 338 if err != nil { 339 return nil, err 340 } 341 case 5: 342 err := buf.WriteByte(byte(ethcmn.HashLength)) 343 if err != nil { 344 return nil, err 345 } 346 _, err = buf.Write(log.TxHash.Bytes()) 347 if err != nil { 348 return nil, err 349 } 350 case 6: 351 if log.TxIndex == 0 { 352 noWrite = true 353 break 354 } 355 err := amino.EncodeUvarintToBuffer(buf, uint64(log.TxIndex)) 356 if err != nil { 357 return nil, err 358 } 359 case 7: 360 err := buf.WriteByte(byte(ethcmn.HashLength)) 361 if err != nil { 362 return nil, err 363 } 364 _, err = buf.Write(log.BlockHash.Bytes()) 365 if err != nil { 366 return nil, err 367 } 368 case 8: 369 if log.Index == 0 { 370 noWrite = true 371 break 372 } 373 err := amino.EncodeUvarintToBuffer(buf, uint64(log.Index)) 374 if err != nil { 375 return nil, err 376 } 377 case 9: 378 if log.Removed { 379 err = buf.WriteByte(byte(1)) 380 if err != nil { 381 return nil, err 382 } 383 } else { 384 noWrite = true 385 break 386 } 387 default: 388 panic("unreachable") 389 } 390 391 if noWrite { 392 buf.Truncate(lBeforeKey) 393 } 394 } 395 return amino.GetBytesBufferCopy(buf), nil 396 } 397 398 func (rd *ResultData) UnmarshalFromAmino(_ *amino.Codec, data []byte) error { 399 var dataLen uint64 = 0 400 var subData []byte 401 402 for { 403 data = data[dataLen:] 404 405 if len(data) == 0 { 406 break 407 } 408 409 pos, aminoType, err := amino.ParseProtoPosAndTypeMustOneByte(data[0]) 410 if err != nil { 411 return err 412 } 413 if aminoType != amino.Typ3_ByteLength { 414 return fmt.Errorf("unexpect proto type %d", aminoType) 415 } 416 data = data[1:] 417 418 var n int 419 dataLen, n, err = amino.DecodeUvarint(data) 420 if err != nil { 421 return err 422 } 423 424 data = data[n:] 425 if len(data) < int(dataLen) { 426 return errors.New("invalid data len") 427 } 428 subData = data[:dataLen] 429 430 switch pos { 431 case 1: 432 if int(dataLen) != ethcmn.AddressLength { 433 return fmt.Errorf("invalid contract address length: %d", dataLen) 434 } 435 copy(rd.ContractAddress[:], subData) 436 case 2: 437 if int(dataLen) != ethtypes.BloomByteLength { 438 return fmt.Errorf("invalid bloom length: %d", dataLen) 439 } 440 copy(rd.Bloom[:], subData) 441 case 3: 442 var log *ethtypes.Log 443 if dataLen == 0 { 444 log, err = nil, nil 445 } else { 446 log, err = UnmarshalEthLogFromAmino(subData) 447 } 448 if err != nil { 449 return err 450 } 451 rd.Logs = append(rd.Logs, log) 452 case 4: 453 rd.Ret = make([]byte, dataLen) 454 copy(rd.Ret, subData) 455 case 5: 456 if dataLen != ethcmn.HashLength { 457 return fmt.Errorf("invalid tx hash length %d", dataLen) 458 } 459 copy(rd.TxHash[:], subData) 460 } 461 } 462 return nil 463 } 464 465 var resultDataBufferPool = amino.NewBufferPool() 466 467 func (rd *ResultData) MarshalToAmino(_ *amino.Codec) ([]byte, error) { 468 var buf = resultDataBufferPool.Get() 469 defer resultDataBufferPool.Put(buf) 470 fieldKeysType := [5]byte{1<<3 | 2, 2<<3 | 2, 3<<3 | 2, 4<<3 | 2, 5<<3 | 2} 471 for pos := 1; pos < 6; pos++ { 472 lBeforeKey := buf.Len() 473 var noWrite bool 474 err := buf.WriteByte(fieldKeysType[pos-1]) 475 if err != nil { 476 return nil, err 477 } 478 479 switch pos { 480 case 1: 481 err := buf.WriteByte(byte(ethcmn.AddressLength)) 482 if err != nil { 483 return nil, err 484 } 485 _, err = buf.Write(rd.ContractAddress.Bytes()) 486 if err != nil { 487 return nil, err 488 } 489 case 2: 490 _, err := buf.Write([]byte{0b10000000, 0b00000010}) // bloom length 256 491 if err != nil { 492 return nil, err 493 } 494 _, err = buf.Write(rd.Bloom.Bytes()) 495 if err != nil { 496 return nil, err 497 } 498 case 3: 499 logsLen := len(rd.Logs) 500 if logsLen == 0 { 501 noWrite = true 502 break 503 } 504 data, err := MarshalEthLogToAmino(rd.Logs[0]) 505 if err != nil { 506 return nil, err 507 } 508 err = amino.EncodeUvarintToBuffer(buf, uint64(len(data))) 509 if err != nil { 510 return nil, err 511 } 512 _, err = buf.Write(data) 513 if err != nil { 514 return nil, err 515 } 516 for i := 1; i < logsLen; i++ { 517 err = buf.WriteByte(fieldKeysType[pos-1]) 518 if err != nil { 519 return nil, err 520 } 521 data, err = MarshalEthLogToAmino(rd.Logs[i]) 522 if err != nil { 523 return nil, err 524 } 525 err = amino.EncodeUvarintToBuffer(buf, uint64(len(data))) 526 if err != nil { 527 return nil, err 528 } 529 _, err = buf.Write(data) 530 if err != nil { 531 return nil, err 532 } 533 } 534 case 4: 535 retLen := len(rd.Ret) 536 if retLen == 0 { 537 noWrite = true 538 break 539 } 540 err := amino.EncodeUvarintToBuffer(buf, uint64(retLen)) 541 if err != nil { 542 return nil, err 543 } 544 _, err = buf.Write(rd.Ret) 545 if err != nil { 546 return nil, err 547 } 548 case 5: 549 err := buf.WriteByte(byte(ethcmn.HashLength)) 550 if err != nil { 551 return nil, err 552 } 553 _, err = buf.Write(rd.TxHash.Bytes()) 554 if err != nil { 555 return nil, err 556 } 557 default: 558 panic("unreachable") 559 } 560 561 if noWrite { 562 buf.Truncate(lBeforeKey) 563 } 564 } 565 return amino.GetBytesBufferCopy(buf), nil 566 } 567 568 // String implements fmt.Stringer interface. 569 func (rd ResultData) String() string { 570 var logsStr string 571 logsLen := len(rd.Logs) 572 for i := 0; i < logsLen; i++ { 573 logsStr = fmt.Sprintf("%s\t\t%v\n ", logsStr, *rd.Logs[i]) 574 } 575 576 return strings.TrimSpace(fmt.Sprintf(`ResultData: 577 ContractAddress: %s 578 Bloom: %s 579 Ret: %v 580 TxHash: %s 581 Logs: 582 %s`, rd.ContractAddress.String(), rd.Bloom.Big().String(), rd.Ret, rd.TxHash.String(), logsStr)) 583 } 584 585 // EncodeResultData takes all of the necessary data from the EVM execution 586 // and returns the data as a byte slice encoded with amino 587 func EncodeResultData(data *ResultData) ([]byte, error) { 588 var buf = new(bytes.Buffer) 589 590 bz, err := data.MarshalToAmino(ModuleCdc) 591 if err != nil { 592 bz, err = ModuleCdc.MarshalBinaryBare(*data) 593 if err != nil { 594 return nil, err 595 } 596 } 597 598 // Write uvarint(len(bz)). 599 err = amino.EncodeUvarintToBuffer(buf, uint64(len(bz))) 600 if err != nil { 601 return nil, err 602 } 603 604 // Write bz. 605 _, err = buf.Write(bz) 606 if err != nil { 607 return nil, err 608 } 609 610 return buf.Bytes(), nil 611 } 612 613 func IsEvmEvent(txResult *abci.ResponseDeliverTx) bool { 614 for _, event := range txResult.Events { 615 if event.Type != "message" { 616 continue 617 } 618 619 for _, attr := range event.Attributes { 620 if string(attr.Key) == "module" && string(attr.Value) == "evm" { 621 return true 622 } 623 } 624 } 625 626 return false 627 } 628 629 // DecodeResultData decodes an amino-encoded byte slice into ResultData 630 func DecodeResultData(in []byte) (ResultData, error) { 631 if len(in) > 0 { 632 bz, err := amino.GetBinaryBareFromBinaryLengthPrefixed(in) 633 if err == nil { 634 var data ResultData 635 err = data.UnmarshalFromAmino(ModuleCdc, bz) 636 if err == nil { 637 return data, nil 638 } 639 } 640 } 641 var data ResultData 642 err := ModuleCdc.UnmarshalBinaryLengthPrefixed(in, &data) 643 if err != nil { 644 return ResultData{}, err 645 } 646 return data, nil 647 } 648 649 type recoverEthSigData struct { 650 Buffer bytes.Buffer 651 Sig [65]byte 652 SigHash ethcmn.Hash 653 } 654 655 var recoverEthSigDataPool = sync.Pool{ 656 New: func() interface{} { 657 return &recoverEthSigData{} 658 }, 659 } 660 661 func getZeroPrefixLen(buf []byte) int { 662 var i int 663 for i < len(buf) && buf[i] == 0 { 664 i++ 665 } 666 return i 667 } 668 669 func getSigRSData(d *big.Int, buffer *bytes.Buffer) []byte { 670 const _S = (bits.UintSize / 8) 671 672 bzLen := len(d.Bits()) * _S 673 674 buffer.Reset() 675 buffer.Grow(bzLen) 676 var buf = buffer.Bytes()[:bzLen] 677 678 d.FillBytes(buf) 679 return buf[getZeroPrefixLen(buf):] 680 } 681 682 // recoverEthSig recovers a signature according to the Ethereum specification and 683 // returns the sender or an error. 684 // 685 // Ref: Ethereum Yellow Paper (BYZANTIUM VERSION 69351d5) Appendix F 686 // nolint: gocritic 687 func recoverEthSig(R, S, Vb *big.Int, sigHash *ethcmn.Hash) (ethcmn.Address, error) { 688 if Vb.BitLen() > 8 { 689 return ethcmn.Address{}, errors.New("invalid signature") 690 } 691 692 V := byte(Vb.Uint64() - 27) 693 if !ethcrypto.ValidateSignatureValues(V, R, S, true) { 694 return ethcmn.Address{}, errors.New("invalid signature") 695 } 696 697 ethSigData := recoverEthSigDataPool.Get().(*recoverEthSigData) 698 defer recoverEthSigDataPool.Put(ethSigData) 699 sig := (ðSigData.Sig)[:] 700 for i := range sig { 701 sig[i] = 0 702 } 703 704 // encode the signature in uncompressed format 705 buffer := ðSigData.Buffer 706 r := getSigRSData(R, buffer) 707 708 copy(sig[32-len(r):32], r) 709 710 s := getSigRSData(S, buffer) 711 712 copy(sig[64-len(s):64], s) 713 sig[64] = V 714 715 ethSigData.SigHash = *sigHash 716 717 // recover the public key from the signature 718 pub, err := ethcrypto.Ecrecover(ethSigData.SigHash[:], sig) 719 if err != nil { 720 return ethcmn.Address{}, err 721 } 722 723 if len(pub) == 0 || pub[0] != 4 { 724 return ethcmn.Address{}, errors.New("invalid public key") 725 } 726 727 var addr ethcmn.Address 728 copy(addr[:], keccak256To(sig[:32], pub[1:])[12:]) 729 730 return addr, nil 731 } 732 733 // keccak256 calculates and returns the Keccak256 hash of the input data. 734 func keccak256(data ...[]byte) []byte { 735 b := make([]byte, 32) 736 // d := ethcrypto.NewKeccakState() 737 d := keccakStatePool.Get().(ethcrypto.KeccakState) 738 d.Reset() 739 for _, b := range data { 740 d.Write(b) 741 } 742 d.Read(b) 743 keccakStatePool.Put(d) 744 return b 745 } 746 747 func keccak256To(target []byte, data ...[]byte) []byte { 748 if len(target) != 32 { 749 panic("target size mismatch") 750 } 751 752 d := keccakStatePool.Get().(ethcrypto.KeccakState) 753 d.Reset() 754 for _, b := range data { 755 d.Write(b) 756 } 757 d.Read(target) 758 keccakStatePool.Put(d) 759 return target 760 } 761 762 var ethAddrStringPool = &sync.Pool{ 763 New: func() interface{} { 764 return &[32]byte{} 765 }, 766 } 767 768 type EthAddressStringer ethcmn.Address 769 770 func (address EthAddressStringer) String() string { 771 p := &address 772 return EthAddressToString((*ethcmn.Address)(p)) 773 } 774 775 func EthAddressToString(address *ethcmn.Address) string { 776 var buf [len(address)*2 + 2]byte 777 buf[0] = '0' 778 buf[1] = 'x' 779 hex.Encode(buf[2:], address[:]) 780 781 // compute checksum 782 sha := keccakStatePool.Get().(ethcrypto.KeccakState) 783 sha.Reset() 784 sha.Write(buf[2:]) 785 786 hash := ethAddrStringPool.Get().(*[32]byte) 787 sha.Read(hash[:]) 788 789 for i := 2; i < len(buf); i++ { 790 hashByte := hash[(i-2)/2] 791 if i%2 == 0 { 792 hashByte = hashByte >> 4 793 } else { 794 hashByte &= 0xf 795 } 796 if buf[i] > '9' && hashByte > 7 { 797 buf[i] -= 32 798 } 799 } 800 ethAddrStringPool.Put(hash) 801 keccakStatePool.Put(sha) 802 return amino.BytesToStr(buf[:]) 803 } 804 805 type EthHashStringer ethcmn.Hash 806 807 func (h EthHashStringer) String() string { 808 var enc [len(h)*2 + 2]byte 809 enc[0] = '0' 810 enc[1] = 'x' 811 hex.Encode(enc[2:], h[:]) 812 return amino.BytesToStr(enc[:]) 813 }