all: rework trc21 (#1777)

This commit is contained in:
Daniel Liu 2025-11-18 13:54:56 +08:00 committed by GitHub
parent f8553d5871
commit 0050bef807
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 56 additions and 48 deletions

View file

@ -754,7 +754,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
SkipNonceChecks: true,
SkipFromEOACheck: true,
}
feeCapacity := state.GetTRC21FeeCapacityFromState(stateDB)
feeCapacity := stateDB.GetTRC21FeeCapacityFromState()
if msg.To != nil {
if value, ok := feeCapacity[*msg.To]; ok {
msg.BalanceTokenFee = value

View file

@ -1915,7 +1915,7 @@ func (bc *BlockChain) processBlock(block *types.Block, parent *types.Header, sta
bc.reportBlock(block, nil, err)
return nil, err
}
feeCapacity := state.GetTRC21FeeCapacityFromStateWithCache(parent.Root, statedb)
feeCapacity := statedb.GetTRC21FeeCapacityFromStateWithCache(parent.Root)
receipts, logs, usedGas, err := bc.processor.Process(block, statedb, tradingState, bc.vmConfig, feeCapacity)
if err != nil {
bc.reportBlock(block, receipts, err)
@ -2200,7 +2200,7 @@ func (bc *BlockChain) getResultBlock(block *types.Block, verifiedM2 bool) (*Resu
bc.reportBlock(block, nil, err)
return nil, err
}
feeCapacity := state.GetTRC21FeeCapacityFromStateWithCache(parent.Root, statedb)
feeCapacity := statedb.GetTRC21FeeCapacityFromStateWithCache(parent.Root)
receipts, logs, usedGas, err := bc.processor.ProcessBlockNoValidator(calculatedBlock, statedb, tradingState, bc.vmConfig, feeCapacity)
process := time.Since(bstart)
if err != nil {

View file

@ -85,7 +85,7 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti
if b.gasPool == nil {
b.SetCoinbase(common.Address{})
}
feeCapacity := state.GetTRC21FeeCapacityFromState(b.statedb)
feeCapacity := b.statedb.GetTRC21FeeCapacityFromState()
b.statedb.SetTxContext(tx.Hash(), len(b.txs))
receipt, gas, tokenFeeUsed, err := ApplyTransaction(b.config, feeCapacity, bc, &b.header.Coinbase, b.gasPool, b.statedb, nil, b.header, tx, &b.header.GasUsed, vmConfig)
if err != nil {
@ -95,7 +95,7 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti
b.receipts = append(b.receipts, receipt)
if tokenFeeUsed {
fee := common.GetGasFee(b.header.Number.Uint64(), gas)
state.UpdateTRC21Fee(b.statedb, map[common.Address]*big.Int{*tx.To(): new(big.Int).Sub(feeCapacity[*tx.To()], new(big.Int).SetUint64(gas))}, fee)
b.statedb.UpdateTRC21Fee(map[common.Address]*big.Int{*tx.To(): new(big.Int).Sub(feeCapacity[*tx.To()], new(big.Int).SetUint64(gas))}, fee)
}
}

View file

@ -25,50 +25,56 @@ var (
cache = lru.NewCache[common.Hash, map[common.Address]*big.Int](128)
)
func GetTRC21FeeCapacityFromStateWithCache(trieRoot common.Hash, statedb *StateDB) map[common.Address]*big.Int {
if statedb == nil {
func (s *StateDB) GetTRC21FeeCapacityFromStateWithCache(trieRoot common.Hash) map[common.Address]*big.Int {
if s == nil {
return map[common.Address]*big.Int{}
}
info, ok := cache.Get(trieRoot)
if !ok || info == nil {
info = GetTRC21FeeCapacityFromState(statedb)
info = s.GetTRC21FeeCapacityFromState()
cache.Add(trieRoot, info)
}
tokensFee := map[common.Address]*big.Int{}
for key, value := range info {
tokensFee[key] = big.NewInt(0).SetBytes(value.Bytes())
}
return tokensFee
}
func GetTRC21FeeCapacityFromState(statedb *StateDB) map[common.Address]*big.Int {
if statedb == nil {
func (s *StateDB) GetTRC21FeeCapacityFromState() map[common.Address]*big.Int {
if s == nil {
return map[common.Address]*big.Int{}
}
tokensCapacity := map[common.Address]*big.Int{}
slotTokens := SlotTRC21Issuer["tokens"]
slotTokensHash := common.BigToHash(new(big.Int).SetUint64(slotTokens))
slotTokensState := SlotTRC21Issuer["tokensState"]
tokenCount := statedb.GetState(common.TRC21IssuerSMC, slotTokensHash).Big().Uint64()
for i := uint64(0); i < tokenCount; i++ {
tokenCount := s.GetState(common.TRC21IssuerSMC, slotTokensHash).Big().Uint64()
for i := range tokenCount {
key := GetLocDynamicArrAtElement(slotTokensHash, i, 1)
value := statedb.GetState(common.TRC21IssuerSMC, key)
value := s.GetState(common.TRC21IssuerSMC, key)
if !value.IsZero() {
token := common.BytesToAddress(value.Bytes())
balanceKey := GetLocMappingAtKey(token.Hash(), slotTokensState)
balanceHash := statedb.GetState(common.TRC21IssuerSMC, common.BigToHash(balanceKey))
balanceHash := s.GetState(common.TRC21IssuerSMC, common.BigToHash(balanceKey))
tokensCapacity[common.BytesToAddress(token.Bytes())] = balanceHash.Big()
}
}
return tokensCapacity
}
func PayFeeWithTRC21TxFail(statedb *StateDB, from common.Address, token common.Address) {
if statedb == nil {
func (s *StateDB) PayFeeWithTRC21TxFail(from common.Address, token common.Address) {
if s == nil {
return
}
slotBalanceTrc21 := SlotTRC21Token["balances"]
balanceKey := GetLocMappingAtKey(from.Hash(), slotBalanceTrc21)
balanceHash := statedb.GetState(token, common.BigToHash(balanceKey))
balanceHash := s.GetState(token, common.BigToHash(balanceKey))
if !balanceHash.IsZero() {
balance := balanceHash.Big()
feeUsed := big.NewInt(0)
@ -79,9 +85,9 @@ func PayFeeWithTRC21TxFail(statedb *StateDB, from common.Address, token common.A
if issuerTokenKey.IsZero() {
return
}
issuerAddr := common.BytesToAddress(statedb.GetState(token, issuerTokenKey).Bytes())
issuerAddr := common.BytesToAddress(s.GetState(token, issuerTokenKey).Bytes())
feeTokenKey := GetLocSimpleVariable(SlotTRC21Token["minFee"])
feeHash := statedb.GetState(token, feeTokenKey)
feeHash := s.GetState(token, feeTokenKey)
fee := feeHash.Big()
if balance.Cmp(fee) < 0 {
feeUsed = balance
@ -89,28 +95,29 @@ func PayFeeWithTRC21TxFail(statedb *StateDB, from common.Address, token common.A
feeUsed = fee
}
balance = balance.Sub(balance, feeUsed)
statedb.SetState(token, common.BigToHash(balanceKey), common.BigToHash(balance))
s.SetState(token, common.BigToHash(balanceKey), common.BigToHash(balance))
issuerBalanceKey := GetLocMappingAtKey(issuerAddr.Hash(), slotBalanceTrc21)
issuerBalanceHash := statedb.GetState(token, common.BigToHash(issuerBalanceKey))
issuerBalanceHash := s.GetState(token, common.BigToHash(issuerBalanceKey))
issuerBalance := issuerBalanceHash.Big()
issuerBalance = issuerBalance.Add(issuerBalance, feeUsed)
statedb.SetState(token, common.BigToHash(issuerBalanceKey), common.BigToHash(issuerBalance))
s.SetState(token, common.BigToHash(issuerBalanceKey), common.BigToHash(issuerBalance))
}
}
func ValidateTRC21Tx(statedb *StateDB, from common.Address, token common.Address, data []byte) bool {
if data == nil || statedb == nil {
func (s *StateDB) ValidateTRC21Tx(from common.Address, token common.Address, data []byte) bool {
if s == nil || data == nil {
return false
}
slotBalanceTrc21 := SlotTRC21Token["balances"]
balanceKey := GetLocMappingAtKey(from.Hash(), slotBalanceTrc21)
balanceHash := statedb.GetState(token, common.BigToHash(balanceKey))
balanceHash := s.GetState(token, common.BigToHash(balanceKey))
if !balanceHash.IsZero() {
balance := balanceHash.Big()
minFeeTokenKey := GetLocSimpleVariable(SlotTRC21Token["minFee"])
minFeeHash := statedb.GetState(token, minFeeTokenKey)
minFeeHash := s.GetState(token, minFeeTokenKey)
requiredMinBalance := minFeeHash.Big()
funcHex := data[:4]
value := big.NewInt(0)
@ -138,14 +145,15 @@ func ValidateTRC21Tx(statedb *StateDB, from common.Address, token common.Address
return false
}
func UpdateTRC21Fee(statedb *StateDB, newBalance map[common.Address]*big.Int, totalFeeUsed *big.Int) {
if statedb == nil || len(newBalance) == 0 {
func (s *StateDB) UpdateTRC21Fee(newBalance map[common.Address]*big.Int, totalFeeUsed *big.Int) {
if s == nil || len(newBalance) == 0 {
return
}
slotTokensState := SlotTRC21Issuer["tokensState"]
for token, value := range newBalance {
balanceKey := GetLocMappingAtKey(token.Hash(), slotTokensState)
statedb.SetState(common.TRC21IssuerSMC, common.BigToHash(balanceKey), common.BigToHash(value))
s.SetState(common.TRC21IssuerSMC, common.BigToHash(balanceKey), common.BigToHash(value))
}
statedb.SubBalance(common.TRC21IssuerSMC, totalFeeUsed, tracing.BalanceChangeUnspecified)
s.SubBalance(common.TRC21IssuerSMC, totalFeeUsed, tracing.BalanceChangeUnspecified)
}

View file

@ -144,7 +144,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, tra
totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee)
}
}
state.UpdateTRC21Fee(statedb, balanceUpdated, totalFeeUsed)
statedb.UpdateTRC21Fee(balanceUpdated, totalFeeUsed)
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
p.engine.Finalize(p.bc, header, statedb, parentState, block.Transactions(), block.Uncles(), receipts)
return receipts, allLogs, *usedGas, nil
@ -238,7 +238,7 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee)
}
}
state.UpdateTRC21Fee(statedb, balanceUpdated, totalFeeUsed)
statedb.UpdateTRC21Fee(balanceUpdated, totalFeeUsed)
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
p.engine.Finalize(p.bc, header, statedb, parentState, block.Transactions(), block.Uncles(), receipts)
return receipts, allLogs, *usedGas, nil
@ -441,7 +441,7 @@ func ApplyTransactionWithEVM(msg *Message, config *params.ChainConfig, gp *GasPo
*usedGas += result.UsedGas
if balanceFee != nil && result.Failed() {
state.PayFeeWithTRC21TxFail(statedb, msg.From, *to)
statedb.PayFeeWithTRC21TxFail(msg.From, *to)
}
return MakeReceipt(evm, result, statedb, blockNumber, blockHash, tx, *usedGas, root), result.UsedGas, balanceFee != nil, nil

View file

@ -99,7 +99,7 @@ func CallContractWithState(call ethereum.CallMsg, chain consensus.ChainContext,
SkipNonceChecks: true,
SkipFromEOACheck: true,
}
feeCapacity := state.GetTRC21FeeCapacityFromState(statedb)
feeCapacity := statedb.GetTRC21FeeCapacityFromState()
if msg.To != nil {
if value, ok := feeCapacity[*msg.To]; ok {
msg.BalanceTokenFee = value

View file

@ -704,7 +704,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
if tx.To() != nil {
if value, ok := pool.trc21FeeCapacity[*tx.To()]; ok {
feeCapacity = value
if !state.ValidateTRC21Tx(pool.currentState, from, *tx.To(), tx.Data()) {
if !pool.currentState.ValidateTRC21Tx(from, *tx.To(), tx.Data()) {
return core.ErrInsufficientFunds
}
cost = tx.TxCost(number)
@ -1445,7 +1445,7 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) {
return
}
pool.currentState = statedb
pool.trc21FeeCapacity = state.GetTRC21FeeCapacityFromStateWithCache(newHead.Root, statedb)
pool.trc21FeeCapacity = statedb.GetTRC21FeeCapacityFromStateWithCache(newHead.Root)
pool.pendingNonces = newNoncer(statedb)
pool.currentMaxGas = newHead.GasLimit

View file

@ -211,7 +211,7 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
}
// Recompute transactions up to the target index.
signer := types.MakeSigner(eth.blockchain.Config(), block.Number())
feeCapacity := state.GetTRC21FeeCapacityFromState(statedb)
feeCapacity := statedb.GetTRC21FeeCapacityFromState()
for idx, tx := range block.Transactions() {
var balance *big.Int
if tx.To() != nil {

View file

@ -264,7 +264,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
signer = types.MakeSigner(api.backend.ChainConfig(), task.block.Number())
blockCtx = core.NewEVMBlockContext(task.block.Header(), api.chainContext(ctx), nil)
)
feeCapacity := state.GetTRC21FeeCapacityFromState(task.statedb)
feeCapacity := task.statedb.GetTRC21FeeCapacityFromState()
// Trace all the transactions contained within
for i, tx := range task.block.Transactions() {
var balance *big.Int
@ -513,7 +513,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
deleteEmptyObjects = chainConfig.IsEIP158(block.Number())
)
feeCapacity := state.GetTRC21FeeCapacityFromState(statedb)
feeCapacity := statedb.GetTRC21FeeCapacityFromState()
for i, tx := range block.Transactions() {
if err := ctx.Err(); err != nil {
return nil, err
@ -593,7 +593,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number())
results = make([]*txTraceResult, len(txs))
)
feeCapacity := state.GetTRC21FeeCapacityFromState(statedb)
feeCapacity := statedb.GetTRC21FeeCapacityFromState()
for i, tx := range txs {
var balance *big.Int
if tx.To() != nil {
@ -644,7 +644,7 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat
defer pend.Done()
// Fetch and execute the next transaction trace tasks
for task := range jobs {
feeCapacity := state.GetTRC21FeeCapacityFromState(task.statedb)
feeCapacity := task.statedb.GetTRC21FeeCapacityFromState()
var balance *big.Int
if txs[task.index].To() != nil {
if value, ok := feeCapacity[*txs[task.index].To()]; ok {
@ -675,7 +675,7 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat
}
// Feed the transactions into the tracers and return
feeCapacity := state.GetTRC21FeeCapacityFromState(statedb)
feeCapacity := statedb.GetTRC21FeeCapacityFromState()
var failed error
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
txloop:
@ -751,7 +751,7 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
return nil, err
}
defer release()
feeCapacity := state.GetTRC21FeeCapacityFromState(statedb)
feeCapacity := statedb.GetTRC21FeeCapacityFromState()
var balance *big.Int
if tx.To() != nil {
if value, ok := feeCapacity[*tx.To()]; ok {
@ -900,7 +900,7 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor
}()
defer cancel()
feeCapacity := state.GetTRC21FeeCapacityFromState(statedb)
feeCapacity := statedb.GetTRC21FeeCapacityFromState()
var balance *big.Int
if tx.To() != nil {
if value, ok := feeCapacity[*tx.To()]; ok {

View file

@ -1842,7 +1842,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
args.AccessList = &accessList
msg := args.ToMessage(b, header.BaseFee, true, true)
feeCapacity := state.GetTRC21FeeCapacityFromState(statedb)
feeCapacity := statedb.GetTRC21FeeCapacityFromState()
var balanceTokenFee *big.Int
if value, ok := feeCapacity[to]; ok {
balanceTokenFee = value

View file

@ -351,7 +351,7 @@ func (w *worker) update() {
acc, _ := types.Sender(w.current.signer, tx)
txs[acc] = append(txs[acc], tx)
}
feeCapacity := state.GetTRC21FeeCapacityFromState(w.current.state)
feeCapacity := w.current.state.GetTRC21FeeCapacityFromState()
txset, specialTxs := types.NewTransactionsByPriceAndNonce(w.current.signer, txs, feeCapacity)
tcount := w.current.tcount
@ -758,7 +758,7 @@ func (w *worker) commitNewWork() {
updatedTrades map[common.Hash]*lendingstate.LendingTrade
liquidatedTrades, autoRepayTrades, autoTopUpTrades, autoRecallTrades []*lendingstate.LendingTrade
)
feeCapacity := state.GetTRC21FeeCapacityFromStateWithCache(parent.Root(), work.state)
feeCapacity := work.state.GetTRC21FeeCapacityFromStateWithCache(parent.Root())
if w.config.XDPoS != nil {
isEpochSwitchBlock, _, err := w.engine.(*XDPoS.XDPoS).IsEpochSwitch(header)
if err != nil {
@ -1133,7 +1133,7 @@ func (w *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Addr
totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee)
}
}
state.UpdateTRC21Fee(w.state, balanceUpdated, totalFeeUsed)
w.state.UpdateTRC21Fee(balanceUpdated, totalFeeUsed)
// make a copy, the state caches the logs and these logs get "upgraded" from pending to mined
// logs by filling in the block hash when the block was mined by the local miner. This can
// cause a race condition if a log was "upgraded" before the PendingLogsEvent is processed.