Merge remote-tracking branch 'origin/master' into feat/go-data-transfer-v2
This commit is contained in:
+4
-15
@@ -193,25 +193,14 @@ func (a *ChainAPI) ChainGetParentReceipts(ctx context.Context, bcid cid.Cid) ([]
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// TODO: need to get the number of messages better than this
|
||||
pts, err := a.Chain.LoadTipSet(ctx, types.NewTipSetKey(b.Parents...))
|
||||
receipts, err := a.Chain.ReadReceipts(ctx, b.ParentMessageReceipts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cm, err := a.Chain.MessagesForTipset(ctx, pts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var out []*types.MessageReceipt
|
||||
for i := 0; i < len(cm); i++ {
|
||||
r, err := a.Chain.GetParentReceipt(ctx, b, i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out = append(out, r)
|
||||
out := make([]*types.MessageReceipt, len(receipts))
|
||||
for i := range receipts {
|
||||
out[i] = &receipts[i]
|
||||
}
|
||||
|
||||
return out, nil
|
||||
|
||||
+124
-103
@@ -39,9 +39,12 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
)
|
||||
|
||||
var ErrUnsupported = errors.New("unsupported method")
|
||||
|
||||
type EthModuleAPI interface {
|
||||
EthBlockNumber(ctx context.Context) (ethtypes.EthUint64, error)
|
||||
EthAccounts(ctx context.Context) ([]ethtypes.EthAddress, error)
|
||||
@@ -54,8 +57,6 @@ type EthModuleAPI interface {
|
||||
EthGetTransactionHashByCid(ctx context.Context, cid cid.Cid) (*ethtypes.EthHash, error)
|
||||
EthGetTransactionCount(ctx context.Context, sender ethtypes.EthAddress, blkOpt string) (ethtypes.EthUint64, error)
|
||||
EthGetTransactionReceipt(ctx context.Context, txHash ethtypes.EthHash) (*api.EthTxReceipt, error)
|
||||
EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash ethtypes.EthHash, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error)
|
||||
EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum ethtypes.EthUint64, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error)
|
||||
EthGetCode(ctx context.Context, address ethtypes.EthAddress, blkOpt string) (ethtypes.EthBytes, error)
|
||||
EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error)
|
||||
EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error)
|
||||
@@ -153,6 +154,8 @@ type EthAPI struct {
|
||||
EthEventAPI
|
||||
}
|
||||
|
||||
var ErrNullRound = errors.New("requested epoch was a null round")
|
||||
|
||||
func (a *EthModule) StateNetworkName(ctx context.Context) (dtypes.NetworkName, error) {
|
||||
return stmgr.GetNetworkName(ctx, a.StateManager, a.Chain.GetHeaviestTipSet().ParentState())
|
||||
}
|
||||
@@ -231,15 +234,14 @@ func (a *EthModule) EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthH
|
||||
return newEthBlockFromFilecoinTipSet(ctx, ts, fullTxInfo, a.Chain, a.StateAPI)
|
||||
}
|
||||
|
||||
func (a *EthModule) parseBlkParam(ctx context.Context, blkParam string) (tipset *types.TipSet, err error) {
|
||||
if blkParam == "earliest" {
|
||||
return nil, fmt.Errorf("block param \"earliest\" is not supported")
|
||||
func (a *EthModule) parseBlkParam(ctx context.Context, blkParam string, strict bool) (tipset *types.TipSet, err error) {
|
||||
switch blkParam {
|
||||
case "earliest", "pending":
|
||||
return nil, fmt.Errorf("block param %q is not supported", blkParam)
|
||||
}
|
||||
|
||||
head := a.Chain.GetHeaviestTipSet()
|
||||
switch blkParam {
|
||||
case "pending":
|
||||
return head, nil
|
||||
case "latest":
|
||||
parent, err := a.Chain.GetTipSetFromKey(ctx, head.Parents())
|
||||
if err != nil {
|
||||
@@ -252,16 +254,22 @@ func (a *EthModule) parseBlkParam(ctx context.Context, blkParam string) (tipset
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse block number: %v", err)
|
||||
}
|
||||
ts, err := a.Chain.GetTipsetByHeight(ctx, abi.ChainEpoch(num), nil, false)
|
||||
if abi.ChainEpoch(num) > head.Height()-1 {
|
||||
return nil, fmt.Errorf("requested a future epoch (beyond 'latest')")
|
||||
}
|
||||
ts, err := a.ChainAPI.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(num), head.Key())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot get tipset at height: %v", num)
|
||||
}
|
||||
if strict && ts.Height() != abi.ChainEpoch(num) {
|
||||
return nil, ErrNullRound
|
||||
}
|
||||
return ts, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (a *EthModule) EthGetBlockByNumber(ctx context.Context, blkParam string, fullTxInfo bool) (ethtypes.EthBlock, error) {
|
||||
ts, err := a.parseBlkParam(ctx, blkParam)
|
||||
ts, err := a.parseBlkParam(ctx, blkParam, true)
|
||||
if err != nil {
|
||||
return ethtypes.EthBlock{}, err
|
||||
}
|
||||
@@ -335,13 +343,13 @@ func (a *EthModule) EthGetMessageCidByTransactionHash(ctx context.Context, txHas
|
||||
c = txHash.ToCid()
|
||||
}
|
||||
|
||||
_, err = a.StateAPI.Chain.GetSignedMessage(ctx, c)
|
||||
_, err = a.Chain.GetSignedMessage(ctx, c)
|
||||
if err == nil {
|
||||
// This is an Eth Tx, Secp message, Or BLS message in the mpool
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
_, err = a.StateAPI.Chain.GetMessage(ctx, c)
|
||||
_, err = a.Chain.GetMessage(ctx, c)
|
||||
if err == nil {
|
||||
// This is a BLS message
|
||||
return &c, nil
|
||||
@@ -367,7 +375,7 @@ func (a *EthModule) EthGetTransactionCount(ctx context.Context, sender ethtypes.
|
||||
return ethtypes.EthUint64(0), nil
|
||||
}
|
||||
|
||||
ts, err := a.parseBlkParam(ctx, blkParam)
|
||||
ts, err := a.parseBlkParam(ctx, blkParam, false)
|
||||
if err != nil {
|
||||
return ethtypes.EthUint64(0), xerrors.Errorf("cannot parse block param: %s", blkParam)
|
||||
}
|
||||
@@ -420,20 +428,15 @@ func (a *EthModule) EthGetTransactionReceipt(ctx context.Context, txHash ethtype
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
replay, err := a.StateAPI.StateReplay(ctx, types.EmptyTSK, c)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var events []types.Event
|
||||
if rct := replay.MsgRct; rct != nil && rct.EventsRoot != nil {
|
||||
if rct := msgLookup.Receipt; rct.EventsRoot != nil {
|
||||
events, err = a.ChainAPI.ChainGetEvents(ctx, *rct.EventsRoot)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
receipt, err := newEthTxReceipt(ctx, tx, msgLookup, replay, events, a.StateAPI)
|
||||
receipt, err := newEthTxReceipt(ctx, tx, msgLookup, events, a.Chain, a.StateAPI)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -441,12 +444,12 @@ func (a *EthModule) EthGetTransactionReceipt(ctx context.Context, txHash ethtype
|
||||
return &receipt, nil
|
||||
}
|
||||
|
||||
func (a *EthModule) EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash ethtypes.EthHash, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error) {
|
||||
return ethtypes.EthTx{}, nil
|
||||
func (a *EthAPI) EthGetTransactionByBlockHashAndIndex(context.Context, ethtypes.EthHash, ethtypes.EthUint64) (ethtypes.EthTx, error) {
|
||||
return ethtypes.EthTx{}, ErrUnsupported
|
||||
}
|
||||
|
||||
func (a *EthModule) EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum ethtypes.EthUint64, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error) {
|
||||
return ethtypes.EthTx{}, nil
|
||||
func (a *EthAPI) EthGetTransactionByBlockNumberAndIndex(context.Context, ethtypes.EthUint64, ethtypes.EthUint64) (ethtypes.EthTx, error) {
|
||||
return ethtypes.EthTx{}, ErrUnsupported
|
||||
}
|
||||
|
||||
// EthGetCode returns string value of the compiled bytecode
|
||||
@@ -456,7 +459,7 @@ func (a *EthModule) EthGetCode(ctx context.Context, ethAddr ethtypes.EthAddress,
|
||||
return nil, xerrors.Errorf("cannot get Filecoin address: %w", err)
|
||||
}
|
||||
|
||||
ts, err := a.parseBlkParam(ctx, blkParam)
|
||||
ts, err := a.parseBlkParam(ctx, blkParam, false)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("cannot parse block param: %s", blkParam)
|
||||
}
|
||||
@@ -535,7 +538,7 @@ func (a *EthModule) EthGetCode(ctx context.Context, ethAddr ethtypes.EthAddress,
|
||||
}
|
||||
|
||||
func (a *EthModule) EthGetStorageAt(ctx context.Context, ethAddr ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error) {
|
||||
ts, err := a.parseBlkParam(ctx, blkParam)
|
||||
ts, err := a.parseBlkParam(ctx, blkParam, false)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("cannot parse block param: %s", blkParam)
|
||||
}
|
||||
@@ -631,7 +634,7 @@ func (a *EthModule) EthGetBalance(ctx context.Context, address ethtypes.EthAddre
|
||||
return ethtypes.EthBigInt{}, err
|
||||
}
|
||||
|
||||
ts, err := a.parseBlkParam(ctx, blkParam)
|
||||
ts, err := a.parseBlkParam(ctx, blkParam, false)
|
||||
if err != nil {
|
||||
return ethtypes.EthBigInt{}, xerrors.Errorf("cannot parse block param: %s", blkParam)
|
||||
}
|
||||
@@ -676,57 +679,48 @@ func (a *EthModule) EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (eth
|
||||
}
|
||||
}
|
||||
|
||||
ts, err := a.parseBlkParam(ctx, params.NewestBlkNum)
|
||||
ts, err := a.parseBlkParam(ctx, params.NewestBlkNum, false)
|
||||
if err != nil {
|
||||
return ethtypes.EthFeeHistory{}, fmt.Errorf("bad block parameter %s: %s", params.NewestBlkNum, err)
|
||||
}
|
||||
|
||||
// Deal with the case that the chain is shorter than the number of requested blocks.
|
||||
oldestBlkHeight := uint64(1)
|
||||
if abi.ChainEpoch(params.BlkCount) <= ts.Height() {
|
||||
oldestBlkHeight = uint64(ts.Height()) - uint64(params.BlkCount) + 1
|
||||
}
|
||||
var (
|
||||
basefee = ts.Blocks()[0].ParentBaseFee
|
||||
oldestBlkHeight = uint64(1)
|
||||
|
||||
// NOTE: baseFeePerGas should include the next block after the newest of the returned range,
|
||||
// because the next base fee can be inferred from the messages in the newest block.
|
||||
// However, this is NOT the case in Filecoin due to deferred execution, so the best
|
||||
// we can do is duplicate the last value.
|
||||
baseFeeArray := []ethtypes.EthBigInt{ethtypes.EthBigInt(ts.Blocks()[0].ParentBaseFee)}
|
||||
gasUsedRatioArray := []float64{}
|
||||
rewardsArray := make([][]ethtypes.EthBigInt, 0)
|
||||
// NOTE: baseFeePerGas should include the next block after the newest of the returned range,
|
||||
// because the next base fee can be inferred from the messages in the newest block.
|
||||
// However, this is NOT the case in Filecoin due to deferred execution, so the best
|
||||
// we can do is duplicate the last value.
|
||||
baseFeeArray = []ethtypes.EthBigInt{ethtypes.EthBigInt(basefee)}
|
||||
rewardsArray = make([][]ethtypes.EthBigInt, 0)
|
||||
gasUsedRatioArray = []float64{}
|
||||
blocksIncluded int
|
||||
)
|
||||
|
||||
for ts.Height() >= abi.ChainEpoch(oldestBlkHeight) {
|
||||
// Unfortunately we need to rebuild the full message view so we can
|
||||
// totalize gas used in the tipset.
|
||||
msgs, err := a.Chain.MessagesForTipset(ctx, ts)
|
||||
for blocksIncluded < int(params.BlkCount) && ts.Height() > 0 {
|
||||
msgs, rcpts, err := messagesAndReceipts(ctx, ts, a.Chain, a.StateAPI)
|
||||
if err != nil {
|
||||
return ethtypes.EthFeeHistory{}, xerrors.Errorf("error loading messages for tipset: %v: %w", ts, err)
|
||||
return ethtypes.EthFeeHistory{}, xerrors.Errorf("failed to retrieve messages and receipts for height %d: %w", ts.Height(), err)
|
||||
}
|
||||
|
||||
txGasRewards := gasRewardSorter{}
|
||||
for txIdx, msg := range msgs {
|
||||
msgLookup, err := a.StateAPI.StateSearchMsg(ctx, types.EmptyTSK, msg.Cid(), api.LookbackNoLimit, false)
|
||||
if err != nil || msgLookup == nil {
|
||||
return ethtypes.EthFeeHistory{}, nil
|
||||
}
|
||||
|
||||
tx, err := newEthTxFromMessageLookup(ctx, msgLookup, txIdx, a.Chain, a.StateAPI)
|
||||
if err != nil {
|
||||
return ethtypes.EthFeeHistory{}, nil
|
||||
}
|
||||
|
||||
for i, msg := range msgs {
|
||||
effectivePremium := msg.VMMessage().EffectiveGasPremium(basefee)
|
||||
txGasRewards = append(txGasRewards, gasRewardTuple{
|
||||
reward: tx.Reward(ts.Blocks()[0].ParentBaseFee),
|
||||
gas: uint64(msgLookup.Receipt.GasUsed),
|
||||
premium: effectivePremium,
|
||||
gasUsed: rcpts[i].GasUsed,
|
||||
})
|
||||
}
|
||||
|
||||
rewards, totalGasUsed := calculateRewardsAndGasUsed(rewardPercentiles, txGasRewards)
|
||||
|
||||
// arrays should be reversed at the end
|
||||
baseFeeArray = append(baseFeeArray, ethtypes.EthBigInt(ts.Blocks()[0].ParentBaseFee))
|
||||
baseFeeArray = append(baseFeeArray, ethtypes.EthBigInt(basefee))
|
||||
gasUsedRatioArray = append(gasUsedRatioArray, float64(totalGasUsed)/float64(build.BlockGasLimit))
|
||||
rewardsArray = append(rewardsArray, rewards)
|
||||
oldestBlkHeight = uint64(ts.Height())
|
||||
blocksIncluded++
|
||||
|
||||
parentTsKey := ts.Parents()
|
||||
ts, err = a.Chain.LoadTipSet(ctx, parentTsKey)
|
||||
@@ -757,13 +751,8 @@ func (a *EthModule) EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (eth
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (a *EthModule) NetVersion(ctx context.Context) (string, error) {
|
||||
// Note that networkId is not encoded in hex
|
||||
nv, err := a.StateNetworkVersion(ctx, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strconv.FormatUint(uint64(nv), 10), nil
|
||||
func (a *EthModule) NetVersion(_ context.Context) (string, error) {
|
||||
return strconv.FormatInt(build.Eip155ChainId, 10), nil
|
||||
}
|
||||
|
||||
func (a *EthModule) NetListening(ctx context.Context) (bool, error) {
|
||||
@@ -1066,7 +1055,7 @@ func (a *EthModule) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam s
|
||||
return nil, xerrors.Errorf("failed to convert ethcall to filecoin message: %w", err)
|
||||
}
|
||||
|
||||
ts, err := a.parseBlkParam(ctx, blkParam)
|
||||
ts, err := a.parseBlkParam(ctx, blkParam, false)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("cannot parse block param: %s", blkParam)
|
||||
}
|
||||
@@ -1783,37 +1772,37 @@ func newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTx
|
||||
return ethtypes.EthBlock{}, err
|
||||
}
|
||||
|
||||
msgs, err := cs.MessagesForTipset(ctx, ts)
|
||||
msgs, rcpts, err := messagesAndReceipts(ctx, ts, cs, sa)
|
||||
if err != nil {
|
||||
return ethtypes.EthBlock{}, xerrors.Errorf("error loading messages for tipset: %v: %w", ts, err)
|
||||
return ethtypes.EthBlock{}, xerrors.Errorf("failed to retrieve messages and receipts: %w", err)
|
||||
}
|
||||
|
||||
block := ethtypes.NewEthBlock(len(msgs) > 0)
|
||||
|
||||
gasUsed := int64(0)
|
||||
compOutput, err := sa.StateCompute(ctx, ts.Height(), nil, ts.Key())
|
||||
if err != nil {
|
||||
return ethtypes.EthBlock{}, xerrors.Errorf("failed to compute state: %w", err)
|
||||
}
|
||||
|
||||
for txIdx, msg := range compOutput.Trace {
|
||||
// skip system messages like reward application and cron
|
||||
if msg.Msg.From == builtintypes.SystemActorAddr {
|
||||
continue
|
||||
for i, msg := range msgs {
|
||||
rcpt := rcpts[i]
|
||||
ti := ethtypes.EthUint64(i)
|
||||
gasUsed += rcpt.GasUsed
|
||||
var smsg *types.SignedMessage
|
||||
switch msg := msg.(type) {
|
||||
case *types.SignedMessage:
|
||||
smsg = msg
|
||||
case *types.Message:
|
||||
smsg = &types.SignedMessage{
|
||||
Message: *msg,
|
||||
Signature: crypto.Signature{
|
||||
Type: crypto.SigTypeBLS,
|
||||
},
|
||||
}
|
||||
default:
|
||||
return ethtypes.EthBlock{}, xerrors.Errorf("failed to get signed msg %s: %w", msg.Cid(), err)
|
||||
}
|
||||
|
||||
gasUsed += msg.MsgRct.GasUsed
|
||||
smsgCid, err := getSignedMessage(ctx, cs, msg.MsgCid)
|
||||
if err != nil {
|
||||
return ethtypes.EthBlock{}, xerrors.Errorf("failed to get signed msg %s: %w", msg.MsgCid, err)
|
||||
}
|
||||
tx, err := newEthTxFromSignedMessage(ctx, smsgCid, sa)
|
||||
tx, err := newEthTxFromSignedMessage(ctx, smsg, sa)
|
||||
if err != nil {
|
||||
return ethtypes.EthBlock{}, xerrors.Errorf("failed to convert msg to ethTx: %w", err)
|
||||
}
|
||||
|
||||
ti := ethtypes.EthUint64(txIdx)
|
||||
|
||||
tx.ChainID = ethtypes.EthUint64(build.Eip155ChainId)
|
||||
tx.BlockHash = &blkHash
|
||||
tx.BlockNumber = &bn
|
||||
@@ -1835,6 +1824,29 @@ func newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTx
|
||||
return block, nil
|
||||
}
|
||||
|
||||
func messagesAndReceipts(ctx context.Context, ts *types.TipSet, cs *store.ChainStore, sa StateAPI) ([]types.ChainMsg, []types.MessageReceipt, error) {
|
||||
msgs, err := cs.MessagesForTipset(ctx, ts)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("error loading messages for tipset: %v: %w", ts, err)
|
||||
}
|
||||
|
||||
_, rcptRoot, err := sa.StateManager.TipSetState(ctx, ts)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("failed to compute state: %w", err)
|
||||
}
|
||||
|
||||
rcpts, err := cs.ReadReceipts(ctx, rcptRoot)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("error loading receipts for tipset: %v: %w", ts, err)
|
||||
}
|
||||
|
||||
if len(msgs) != len(rcpts) {
|
||||
return nil, nil, xerrors.Errorf("receipts and message array lengths didn't match for tipset: %v: %w", ts, err)
|
||||
}
|
||||
|
||||
return msgs, rcpts, nil
|
||||
}
|
||||
|
||||
// lookupEthAddress makes its best effort at finding the Ethereum address for a
|
||||
// Filecoin address. It does the following:
|
||||
//
|
||||
@@ -2030,7 +2042,7 @@ func newEthTxFromMessageLookup(ctx context.Context, msgLookup *api.MsgLookup, tx
|
||||
return tx, nil
|
||||
}
|
||||
|
||||
func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLookup, replay *api.InvocResult, events []types.Event, sa StateAPI) (api.EthTxReceipt, error) {
|
||||
func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLookup, events []types.Event, cs *store.ChainStore, sa StateAPI) (api.EthTxReceipt, error) {
|
||||
var (
|
||||
transactionIndex ethtypes.EthUint64
|
||||
blockHash ethtypes.EthHash
|
||||
@@ -2061,8 +2073,7 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook
|
||||
|
||||
if lookup.Receipt.ExitCode.IsSuccess() {
|
||||
receipt.Status = 1
|
||||
}
|
||||
if lookup.Receipt.ExitCode.IsError() {
|
||||
} else {
|
||||
receipt.Status = 0
|
||||
}
|
||||
|
||||
@@ -2071,7 +2082,17 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook
|
||||
// TODO: handle CumulativeGasUsed
|
||||
receipt.CumulativeGasUsed = ethtypes.EmptyEthInt
|
||||
|
||||
effectiveGasPrice := big.Div(replay.GasCost.TotalCost, big.NewInt(lookup.Receipt.GasUsed))
|
||||
// TODO: avoid loading the tipset twice (once here, once when we convert the message to a txn)
|
||||
ts, err := cs.GetTipSetFromKey(ctx, lookup.TipSet)
|
||||
if err != nil {
|
||||
return api.EthTxReceipt{}, xerrors.Errorf("failed to lookup tipset %s when constructing the eth txn receipt: %w", lookup.TipSet, err)
|
||||
}
|
||||
|
||||
baseFee := ts.Blocks()[0].ParentBaseFee
|
||||
gasOutputs := vm.ComputeGasOutputs(lookup.Receipt.GasUsed, int64(tx.Gas), baseFee, big.Int(tx.MaxFeePerGas), big.Int(tx.MaxPriorityFeePerGas), true)
|
||||
totalSpent := big.Sum(gasOutputs.BaseFeeBurn, gasOutputs.MinerTip, gasOutputs.OverEstimationBurn)
|
||||
|
||||
effectiveGasPrice := big.Div(totalSpent, big.NewInt(lookup.Receipt.GasUsed))
|
||||
receipt.EffectiveGasPrice = ethtypes.EthBigInt(effectiveGasPrice)
|
||||
|
||||
if receipt.To == nil && lookup.Receipt.ExitCode.IsSuccess() {
|
||||
@@ -2335,35 +2356,35 @@ func parseEthRevert(ret []byte) string {
|
||||
return ethtypes.EthBytes(cbytes).String()
|
||||
}
|
||||
|
||||
func calculateRewardsAndGasUsed(rewardPercentiles []float64, txGasRewards gasRewardSorter) ([]ethtypes.EthBigInt, uint64) {
|
||||
var totalGasUsed uint64
|
||||
func calculateRewardsAndGasUsed(rewardPercentiles []float64, txGasRewards gasRewardSorter) ([]ethtypes.EthBigInt, int64) {
|
||||
var gasUsedTotal int64
|
||||
for _, tx := range txGasRewards {
|
||||
totalGasUsed += tx.gas
|
||||
gasUsedTotal += tx.gasUsed
|
||||
}
|
||||
|
||||
rewards := make([]ethtypes.EthBigInt, len(rewardPercentiles))
|
||||
for i := range rewards {
|
||||
rewards[i] = ethtypes.EthBigIntZero
|
||||
rewards[i] = ethtypes.EthBigInt(types.NewInt(MinGasPremium))
|
||||
}
|
||||
|
||||
if len(txGasRewards) == 0 {
|
||||
return rewards, totalGasUsed
|
||||
return rewards, gasUsedTotal
|
||||
}
|
||||
|
||||
sort.Stable(txGasRewards)
|
||||
|
||||
var idx int
|
||||
var sum uint64
|
||||
var sum int64
|
||||
for i, percentile := range rewardPercentiles {
|
||||
threshold := uint64(float64(totalGasUsed) * percentile / 100)
|
||||
threshold := int64(float64(gasUsedTotal) * percentile / 100)
|
||||
for sum < threshold && idx < len(txGasRewards)-1 {
|
||||
sum += txGasRewards[idx].gas
|
||||
sum += txGasRewards[idx].gasUsed
|
||||
idx++
|
||||
}
|
||||
rewards[i] = txGasRewards[idx].reward
|
||||
rewards[i] = ethtypes.EthBigInt(txGasRewards[idx].premium)
|
||||
}
|
||||
|
||||
return rewards, totalGasUsed
|
||||
return rewards, gasUsedTotal
|
||||
}
|
||||
|
||||
func getSignedMessage(ctx context.Context, cs *store.ChainStore, msgCid cid.Cid) (*types.SignedMessage, error) {
|
||||
@@ -2386,8 +2407,8 @@ func getSignedMessage(ctx context.Context, cs *store.ChainStore, msgCid cid.Cid)
|
||||
}
|
||||
|
||||
type gasRewardTuple struct {
|
||||
gas uint64
|
||||
reward ethtypes.EthBigInt
|
||||
gasUsed int64
|
||||
premium abi.TokenAmount
|
||||
}
|
||||
|
||||
// sorted in ascending order
|
||||
@@ -2398,5 +2419,5 @@ func (g gasRewardSorter) Swap(i, j int) {
|
||||
g[i], g[j] = g[j], g[i]
|
||||
}
|
||||
func (g gasRewardSorter) Less(i, j int) bool {
|
||||
return g[i].reward.Int.Cmp(g[j].reward.Int) == -1
|
||||
return g[i].premium.Int.Cmp(g[j].premium.Int) == -1
|
||||
}
|
||||
|
||||
+10
-13
@@ -117,11 +117,8 @@ func TestReward(t *testing.T) {
|
||||
{maxFeePerGas: big.NewInt(50), maxPriorityFeePerGas: big.NewInt(200), answer: big.NewInt(-50)},
|
||||
}
|
||||
for _, tc := range testcases {
|
||||
tx := ethtypes.EthTx{
|
||||
MaxFeePerGas: ethtypes.EthBigInt(tc.maxFeePerGas),
|
||||
MaxPriorityFeePerGas: ethtypes.EthBigInt(tc.maxPriorityFeePerGas),
|
||||
}
|
||||
reward := tx.Reward(baseFee)
|
||||
msg := &types.Message{GasFeeCap: tc.maxFeePerGas, GasPremium: tc.maxPriorityFeePerGas}
|
||||
reward := msg.EffectiveGasPremium(baseFee)
|
||||
require.Equal(t, 0, reward.Int.Cmp(tc.answer.Int), reward, tc.answer)
|
||||
}
|
||||
}
|
||||
@@ -135,25 +132,25 @@ func TestRewardPercentiles(t *testing.T) {
|
||||
{
|
||||
percentiles: []float64{25, 50, 75},
|
||||
txGasRewards: []gasRewardTuple{},
|
||||
answer: []int64{0, 0, 0},
|
||||
answer: []int64{MinGasPremium, MinGasPremium, MinGasPremium},
|
||||
},
|
||||
{
|
||||
percentiles: []float64{25, 50, 75, 100},
|
||||
txGasRewards: []gasRewardTuple{
|
||||
{gas: uint64(0), reward: ethtypes.EthBigInt(big.NewInt(300))},
|
||||
{gas: uint64(100), reward: ethtypes.EthBigInt(big.NewInt(200))},
|
||||
{gas: uint64(350), reward: ethtypes.EthBigInt(big.NewInt(100))},
|
||||
{gas: uint64(500), reward: ethtypes.EthBigInt(big.NewInt(600))},
|
||||
{gas: uint64(300), reward: ethtypes.EthBigInt(big.NewInt(700))},
|
||||
{gasUsed: int64(0), premium: big.NewInt(300)},
|
||||
{gasUsed: int64(100), premium: big.NewInt(200)},
|
||||
{gasUsed: int64(350), premium: big.NewInt(100)},
|
||||
{gasUsed: int64(500), premium: big.NewInt(600)},
|
||||
{gasUsed: int64(300), premium: big.NewInt(700)},
|
||||
},
|
||||
answer: []int64{200, 700, 700, 700},
|
||||
},
|
||||
}
|
||||
for _, tc := range testcases {
|
||||
rewards, totalGasUsed := calculateRewardsAndGasUsed(tc.percentiles, tc.txGasRewards)
|
||||
gasUsed := uint64(0)
|
||||
var gasUsed int64
|
||||
for _, tx := range tc.txGasRewards {
|
||||
gasUsed += tx.gas
|
||||
gasUsed += tx.gasUsed
|
||||
}
|
||||
ans := []ethtypes.EthBigInt{}
|
||||
for _, bi := range tc.answer {
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"math/rand"
|
||||
"sort"
|
||||
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
lru "github.com/hashicorp/golang-lru/v2"
|
||||
"go.uber.org/fx"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
@@ -61,7 +61,7 @@ type GasAPI struct {
|
||||
|
||||
func NewGasPriceCache() *GasPriceCache {
|
||||
// 50 because we usually won't access more than 40
|
||||
c, err := lru.New2Q(50)
|
||||
c, err := lru.New2Q[types.TipSetKey, []GasMeta](50)
|
||||
if err != nil {
|
||||
// err only if parameter is bad
|
||||
panic(err)
|
||||
@@ -73,7 +73,7 @@ func NewGasPriceCache() *GasPriceCache {
|
||||
}
|
||||
|
||||
type GasPriceCache struct {
|
||||
c *lru.TwoQueueCache
|
||||
c *lru.TwoQueueCache[types.TipSetKey, []GasMeta]
|
||||
}
|
||||
|
||||
type GasMeta struct {
|
||||
@@ -84,7 +84,7 @@ type GasMeta struct {
|
||||
func (g *GasPriceCache) GetTSGasStats(ctx context.Context, cstore *store.ChainStore, ts *types.TipSet) ([]GasMeta, error) {
|
||||
i, has := g.c.Get(ts.Key())
|
||||
if has {
|
||||
return i.([]GasMeta), nil
|
||||
return i, nil
|
||||
}
|
||||
|
||||
var prices []GasMeta
|
||||
|
||||
Reference in New Issue
Block a user