fix: ethrpc: emit correct bloom filters (#10194)

This commit is contained in:
Łukasz Magiera 2023-02-09 00:14:53 +01:00 committed by GitHub
parent da2bb41aa3
commit 9339267e6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 70 additions and 7 deletions

View File

@ -155,8 +155,11 @@ type EthBlock struct {
Uncles []EthHash `json:"uncles"`
}
const EthBloomSize = 2048
var (
EmptyEthBloom = [256]byte{}
EmptyEthBloom = [EthBloomSize / 8]byte{}
FullEthBloom = [EthBloomSize / 8]byte{}
EmptyEthHash = EthHash{}
EmptyUncleHash = must.One(ParseEthHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")) // Keccak-256 of an RLP of an empty array
EmptyRootHash = must.One(ParseEthHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")) // Keccak-256 hash of the RLP of null
@ -164,6 +167,12 @@ var (
EmptyEthNonce = [8]byte{0, 0, 0, 0, 0, 0, 0, 0}
)
func init() {
for i := range FullEthBloom {
FullEthBloom[i] = 0xff
}
}
func NewEthBlock(hasTransactions bool) EthBlock {
b := EthBlock{
Sha3Uncles: EmptyUncleHash, // Sha3Uncles set to a hardcoded value which is used by some clients to determine if has no uncles.
@ -171,7 +180,7 @@ func NewEthBlock(hasTransactions bool) EthBlock {
TransactionsRoot: EmptyRootHash, // TransactionsRoot set to a hardcoded value which is used by some clients to determine if has no transactions.
ReceiptsRoot: EmptyEthHash,
Difficulty: EmptyEthInt,
LogsBloom: EmptyEthBloom[:],
LogsBloom: FullEthBloom[:],
Extradata: []byte{},
MixHash: EmptyEthHash,
Nonce: EmptyEthNonce,
@ -440,6 +449,17 @@ func EthHashFromTxBytes(b []byte) EthHash {
return ethHash
}
func EthBloomSet(f EthBytes, data []byte) {
hasher := sha3.NewLegacyKeccak256()
hasher.Write(data)
hash := hasher.Sum(nil)
for i := 0; i < 3; i++ {
n := binary.BigEndian.Uint16(hash[i*2:]) % EthBloomSize
f[(EthBloomSize/8)-(n/8)-1] |= 1 << (n % 8)
}
}
type EthFeeHistory struct {
OldestBlock EthUint64 `json:"oldestBlock"`
BaseFeePerGas []EthBigInt `json:"baseFeePerGas"`

View File

@ -7,6 +7,7 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
"math/bits"
"os"
"sort"
"strconv"
@ -423,6 +424,51 @@ func TestEthSubscribeLogsNoTopicSpec(t *testing.T) {
AssertEthLogs(t, elogs, expected, messages)
}
func TestTxReceiptBloom(t *testing.T) {
blockTime := 50 * time.Millisecond
client, _, ens := kit.EnsembleMinimal(
t,
kit.MockProofs(),
kit.ThroughRPC())
ens.InterconnectAll().BeginMining(blockTime)
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, "contracts/EventMatrix.hex")
_, ml, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "logEventZeroData()", nil)
require.NoError(t, err)
th, err := client.EthGetTransactionHashByCid(ctx, ml.Message)
require.NoError(t, err)
require.NotNil(t, th)
receipt, err := client.EthGetTransactionReceipt(ctx, *th)
require.NoError(t, err)
require.NotNil(t, receipt)
require.Len(t, receipt.Logs, 1)
// computed by calling EventMatrix/logEventZeroData in remix
// note this only contains topic bits
matchMask := "0x00000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
maskBytes, err := hex.DecodeString(matchMask[2:])
require.NoError(t, err)
bitsSet := 0
for i, maskByte := range maskBytes {
bitsSet += bits.OnesCount8(receipt.LogsBloom[i])
if maskByte > 0 {
require.True(t, maskByte&receipt.LogsBloom[i] > 0)
}
}
// 3 bits from the topic, 3 bits from the address
require.Equal(t, 6, bitsSet)
}
func TestEthGetLogs(t *testing.T) {
require := require.New(t)
kit.QuietAllLogsExcept("events", "messagepool")

View File

@ -1890,11 +1890,6 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook
}
if len(events) > 0 {
// TODO return a dummy non-zero bloom to signal that there are logs
// need to figure out how worth it is to populate with a real bloom
// should be feasible here since we are iterating over the logs anyway
receipt.LogsBloom[255] = 0x01
receipt.Logs = make([]ethtypes.EthLog, 0, len(events))
for i, evt := range events {
l := ethtypes.EthLog{
@ -1912,6 +1907,7 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook
continue
}
if entry.Key == ethtypes.EthTopic1 || entry.Key == ethtypes.EthTopic2 || entry.Key == ethtypes.EthTopic3 || entry.Key == ethtypes.EthTopic4 {
ethtypes.EthBloomSet(receipt.LogsBloom, entry.Value)
l.Topics = append(l.Topics, entry.Value)
} else {
l.Data = entry.Value
@ -1928,6 +1924,7 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook
return api.EthTxReceipt{}, xerrors.Errorf("failed to resolve Ethereum address: %w", err)
}
ethtypes.EthBloomSet(receipt.LogsBloom, l.Address[:])
receipt.Logs = append(receipt.Logs, l)
}
}