fix: Eth JSON-RPC API: return empty logs array in receipt when no logs.
This commit is contained in:
parent
c474aeee5e
commit
b8901ff5fd
@ -836,3 +836,117 @@ func (a *EthModule) newEthTxFromFilecoinMessageLookup(ctx context.Context, msgLo
|
|||||||
}
|
}
|
||||||
return tx, nil
|
return tx, nil
|
||||||
}
|
}
|
||||||
|
<<<<<<< Updated upstream
|
||||||
|
=======
|
||||||
|
|
||||||
|
func newEthTxReceipt(ctx context.Context, tx api.EthTx, lookup *api.MsgLookup, replay *api.InvocResult, events []types.Event, sa StateAPI) (api.EthTxReceipt, error) {
|
||||||
|
receipt := api.EthTxReceipt{
|
||||||
|
TransactionHash: tx.Hash,
|
||||||
|
TransactionIndex: tx.TransactionIndex,
|
||||||
|
BlockHash: tx.BlockHash,
|
||||||
|
BlockNumber: tx.BlockNumber,
|
||||||
|
From: tx.From,
|
||||||
|
To: tx.To,
|
||||||
|
Type: api.EthUint64(2),
|
||||||
|
Logs: []api.EthLog{}, // empty log array is compulsory when no logs, or libraries like ethers.js break
|
||||||
|
LogsBloom: []byte{0},
|
||||||
|
}
|
||||||
|
|
||||||
|
if receipt.To == nil && lookup.Receipt.ExitCode.IsSuccess() {
|
||||||
|
// Create and Create2 return the same things.
|
||||||
|
var ret eam.CreateReturn
|
||||||
|
if err := ret.UnmarshalCBOR(bytes.NewReader(lookup.Receipt.Return)); err != nil {
|
||||||
|
return api.EthTxReceipt{}, xerrors.Errorf("failed to parse contract creation result: %w", err)
|
||||||
|
}
|
||||||
|
addr := api.EthAddress(ret.EthAddress)
|
||||||
|
receipt.ContractAddress = &addr
|
||||||
|
}
|
||||||
|
|
||||||
|
if lookup.Receipt.ExitCode.IsSuccess() {
|
||||||
|
receipt.Status = 1
|
||||||
|
}
|
||||||
|
if lookup.Receipt.ExitCode.IsError() {
|
||||||
|
receipt.Status = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = make([]byte, 256)
|
||||||
|
receipt.LogsBloom[255] = 0x01
|
||||||
|
|
||||||
|
receipt.Logs = make([]api.EthLog, 0, len(events))
|
||||||
|
for i, evt := range events {
|
||||||
|
l := api.EthLog{
|
||||||
|
Removed: false,
|
||||||
|
LogIndex: api.EthUint64(i),
|
||||||
|
TransactionIndex: tx.TransactionIndex,
|
||||||
|
TransactionHash: tx.Hash,
|
||||||
|
BlockHash: tx.BlockHash,
|
||||||
|
BlockNumber: tx.BlockNumber,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, entry := range evt.Entries {
|
||||||
|
value := api.EthBytes(leftpad32(decodeLogBytes(entry.Value)))
|
||||||
|
if entry.Key == api.EthTopic1 || entry.Key == api.EthTopic2 || entry.Key == api.EthTopic3 || entry.Key == api.EthTopic4 {
|
||||||
|
l.Topics = append(l.Topics, value)
|
||||||
|
} else {
|
||||||
|
l.Data = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addr, err := address.NewIDAddress(uint64(evt.Emitter))
|
||||||
|
if err != nil {
|
||||||
|
return api.EthTxReceipt{}, xerrors.Errorf("failed to create ID address: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Address, err = lookupEthAddress(ctx, addr, sa)
|
||||||
|
if err != nil {
|
||||||
|
return api.EthTxReceipt{}, xerrors.Errorf("failed to resolve Ethereum address: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
receipt.Logs = append(receipt.Logs, l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
receipt.GasUsed = api.EthUint64(lookup.Receipt.GasUsed)
|
||||||
|
|
||||||
|
// TODO: handle CumulativeGasUsed
|
||||||
|
receipt.CumulativeGasUsed = api.EmptyEthInt
|
||||||
|
|
||||||
|
effectiveGasPrice := big.Div(replay.GasCost.TotalCost, big.NewInt(lookup.Receipt.GasUsed))
|
||||||
|
receipt.EffectiveGasPrice = api.EthBigInt(effectiveGasPrice)
|
||||||
|
|
||||||
|
return receipt, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// decodeLogBytes decodes a CBOR-serialized array into its original form.
|
||||||
|
//
|
||||||
|
// This function swallows errors and returns the original array if it failed
|
||||||
|
// to decode.
|
||||||
|
func decodeLogBytes(orig []byte) []byte {
|
||||||
|
if orig == nil {
|
||||||
|
return orig
|
||||||
|
}
|
||||||
|
decoded, err := cbg.ReadByteArray(bytes.NewReader(orig), uint64(len(orig)))
|
||||||
|
if err != nil {
|
||||||
|
return orig
|
||||||
|
}
|
||||||
|
return decoded
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO we could also emit full EVM words from the EVM runtime, but not doing so
|
||||||
|
// makes the contract slightly cheaper (and saves storage bytes), at the expense
|
||||||
|
// of having to left pad in the API, which is a pretty acceptable tradeoff at
|
||||||
|
// face value. There may be other protocol implications to consider.
|
||||||
|
func leftpad32(orig []byte) []byte {
|
||||||
|
needed := 32 - len(orig)
|
||||||
|
if needed <= 0 {
|
||||||
|
return orig
|
||||||
|
}
|
||||||
|
ret := make([]byte, 32)
|
||||||
|
copy(ret[needed:], orig)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
>>>>>>> Stashed changes
|
||||||
|
Loading…
Reference in New Issue
Block a user