mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
159 lines
4.8 KiB
Go
159 lines
4.8 KiB
Go
package state
|
|
|
|
import (
|
|
"bytes"
|
|
"math/big"
|
|
|
|
"github.com/XinFinOrg/XDPoSChain/common"
|
|
"github.com/XinFinOrg/XDPoSChain/common/lru"
|
|
"github.com/XinFinOrg/XDPoSChain/core/tracing"
|
|
)
|
|
|
|
var (
|
|
SlotTRC21Issuer = map[string]uint64{
|
|
"minCap": 0,
|
|
"tokens": 1,
|
|
"tokensState": 2,
|
|
}
|
|
SlotTRC21Token = map[string]uint64{
|
|
"balances": 0,
|
|
"minFee": 1,
|
|
"issuer": 2,
|
|
}
|
|
transferFuncHex = common.Hex2Bytes("0xa9059cbb")
|
|
transferFromFuncHex = common.Hex2Bytes("0x23b872dd")
|
|
cache = lru.NewCache[common.Hash, map[common.Address]*big.Int](128)
|
|
)
|
|
|
|
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 = 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 (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 := s.GetState(common.TRC21IssuerSMC, slotTokensHash).Big().Uint64()
|
|
for i := range tokenCount {
|
|
key := GetLocDynamicArrAtElement(slotTokensHash, i, 1)
|
|
value := s.GetState(common.TRC21IssuerSMC, key)
|
|
if !value.IsZero() {
|
|
token := common.BytesToAddress(value.Bytes())
|
|
balanceKey := GetLocMappingAtKey(token.Hash(), slotTokensState)
|
|
balanceHash := s.GetState(common.TRC21IssuerSMC, common.BigToHash(balanceKey))
|
|
tokensCapacity[common.BytesToAddress(token.Bytes())] = balanceHash.Big()
|
|
}
|
|
}
|
|
|
|
return tokensCapacity
|
|
}
|
|
|
|
func (s *StateDB) PayFeeWithTRC21TxFail(from common.Address, token common.Address) {
|
|
if s == nil {
|
|
return
|
|
}
|
|
|
|
slotBalanceTrc21 := SlotTRC21Token["balances"]
|
|
balanceKey := GetLocMappingAtKey(from.Hash(), slotBalanceTrc21)
|
|
balanceHash := s.GetState(token, common.BigToHash(balanceKey))
|
|
if !balanceHash.IsZero() {
|
|
balance := balanceHash.Big()
|
|
feeUsed := big.NewInt(0)
|
|
if balance.Cmp(feeUsed) <= 0 {
|
|
return
|
|
}
|
|
issuerTokenKey := GetLocSimpleVariable(SlotTRC21Token["issuer"])
|
|
if issuerTokenKey.IsZero() {
|
|
return
|
|
}
|
|
issuerAddr := common.BytesToAddress(s.GetState(token, issuerTokenKey).Bytes())
|
|
feeTokenKey := GetLocSimpleVariable(SlotTRC21Token["minFee"])
|
|
feeHash := s.GetState(token, feeTokenKey)
|
|
fee := feeHash.Big()
|
|
if balance.Cmp(fee) < 0 {
|
|
feeUsed = balance
|
|
} else {
|
|
feeUsed = fee
|
|
}
|
|
balance = balance.Sub(balance, feeUsed)
|
|
s.SetState(token, common.BigToHash(balanceKey), common.BigToHash(balance))
|
|
|
|
issuerBalanceKey := GetLocMappingAtKey(issuerAddr.Hash(), slotBalanceTrc21)
|
|
issuerBalanceHash := s.GetState(token, common.BigToHash(issuerBalanceKey))
|
|
issuerBalance := issuerBalanceHash.Big()
|
|
issuerBalance = issuerBalance.Add(issuerBalance, feeUsed)
|
|
s.SetState(token, common.BigToHash(issuerBalanceKey), common.BigToHash(issuerBalance))
|
|
}
|
|
}
|
|
|
|
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 := s.GetState(token, common.BigToHash(balanceKey))
|
|
|
|
if !balanceHash.IsZero() {
|
|
balance := balanceHash.Big()
|
|
minFeeTokenKey := GetLocSimpleVariable(SlotTRC21Token["minFee"])
|
|
minFeeHash := s.GetState(token, minFeeTokenKey)
|
|
requiredMinBalance := minFeeHash.Big()
|
|
funcHex := data[:4]
|
|
value := big.NewInt(0)
|
|
if bytes.Equal(funcHex, transferFuncHex) && len(data) == 68 {
|
|
value = common.BytesToHash(data[36:]).Big()
|
|
} else {
|
|
if bytes.Equal(funcHex, transferFromFuncHex) && len(data) == 80 {
|
|
value = common.BytesToHash(data[68:]).Big()
|
|
}
|
|
}
|
|
requiredMinBalance = requiredMinBalance.Add(requiredMinBalance, value)
|
|
if balance.Cmp(requiredMinBalance) < 0 {
|
|
return false
|
|
} else {
|
|
return true
|
|
}
|
|
} else {
|
|
// we both accept tx with balance = 0 and fee = 0
|
|
minFeeTokenKey := GetLocSimpleVariable(SlotTRC21Token["minFee"])
|
|
if !minFeeTokenKey.IsZero() {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
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)
|
|
s.SetState(common.TRC21IssuerSMC, common.BigToHash(balanceKey), common.BigToHash(value))
|
|
}
|
|
s.SubBalance(common.TRC21IssuerSMC, totalFeeUsed, tracing.BalanceChangeUnspecified)
|
|
}
|