Skip to content
This repository has been archived by the owner on Mar 8, 2024. It is now read-only.

Commit

Permalink
Added Quai ledger scope checks to all EVM state interactions
Browse files Browse the repository at this point in the history
  • Loading branch information
jdowning100 committed Feb 29, 2024
1 parent 69f4640 commit e1112bc
Show file tree
Hide file tree
Showing 22 changed files with 166 additions and 84 deletions.
39 changes: 36 additions & 3 deletions common/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,25 +38,54 @@ type AddressData interface {
setBytes(b []byte)
}

var ErrNilInner = errors.New("Address has nil inner")
var (
ErrNilInner = errors.New("Address has nil inner")
ErrInvalidScope = errors.New("address is not in scope")
ErrQuaiAddress = errors.New("address is in Quai ledger scope and is not in Qi ledger scope")
LedgerMask = byte(0b10000000)
)

func (a Address) InternalAddress() (InternalAddress, error) {
if a.inner == nil {
return InternalAddress{}, ErrNilInner
}
internal, ok := a.inner.(*InternalAddress)
if !ok || internal == nil {
if !ok {
return InternalAddress{}, ErrInvalidScope
}
if internal == nil {
return InternalAddress{}, ErrNilInner
}
return *internal, nil
}

func (a Address) InternalAndQuaiAddress() (InternalAddress, error) {
if a.inner == nil {
return InternalAddress{}, ErrNilInner
}
if a.IsInQiLedgerScope() {
return InternalAddress{}, MakeErrQiAddress(a.Hex())
}
internal, ok := a.inner.(*InternalAddress)
if !ok {
return InternalAddress{}, ErrInvalidScope
}
if internal == nil {
return InternalAddress{}, ErrNilInner
}
return *internal, nil
}

func (a Address) IsInQiLedgerScope() bool {
LedgerMask := byte(0b10000000)
// The first bit of the second byte is set if the address is in the Qi ledger
return a.Bytes()[1]&LedgerMask == LedgerMask
}

func (a Address) IsInQuaiLedgerScope() bool {
// The first bit of the second byte is not set if the address is in the Quai ledger
return a.Bytes()[1]&LedgerMask != LedgerMask
}

func (a Address) Equal(b Address) bool {
if a.inner == nil && b.inner == nil {
return true
Expand Down Expand Up @@ -329,3 +358,7 @@ func (a AddressBytes) hex() []byte {
hex.Encode(buf[2:], a[:])
return buf[:]
}

func MakeErrQiAddress(addr string) error {
return fmt.Errorf("address %s is in Qi ledger scope and is not in Quai ledger scope", addr)
}
5 changes: 5 additions & 0 deletions common/internal_address.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,8 @@ func (a InternalAddress) Location() *Location {
upperNib := (a[0] & 0xF0) >> 4 // Upper 4 bits, shifted right
return &Location{upperNib, lowerNib}
}

func (a InternalAddress) IsInQuaiLedgerScope() bool {
// The first bit of the second byte is not set if the address is in the Quai ledger
return a.Bytes()[1]&LedgerMask != LedgerMask
}
5 changes: 2 additions & 3 deletions common/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,8 @@ const (
var (
hashT = reflect.TypeOf(Hash{})
// The zero address (0x0)
ZeroExternal = ExternalAddress{}
Zero = Address{&ZeroExternal} // For utility purposes only. It is out-of-scope for state purposes.
ErrInvalidScope = errors.New("address is not in scope")
ZeroExternal = ExternalAddress{}
Zero = Address{&ZeroExternal} // For utility purposes only. It is out-of-scope for state purposes.
)

// Hash represents the 32 byte Keccak256 hash of arbitrary data.
Expand Down
22 changes: 17 additions & 5 deletions consensus/blake3pow/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,11 +443,16 @@ func (blake3pow *Blake3pow) Finalize(chain consensus.ChainHeaderReader, header *
if err != nil {
blake3pow.logger.Error("Provided address in genesis block is out of scope")
}
state.AddBalance(internal, account.Balance)
state.SetCode(internal, account.Code)
state.SetNonce(internal, account.Nonce)
for key, value := range account.Storage {
state.SetState(internal, key, value)
if addr.IsInQuaiLedgerScope() {
state.AddBalance(internal, account.Balance)
state.SetCode(internal, account.Code)
state.SetNonce(internal, account.Nonce)
for key, value := range account.Storage {
state.SetState(internal, key, value)
}
} else {
blake3pow.logger.WithField("address", addr.String()).Error("Provided address in genesis block alloc is not in the Quai ledger scope")
continue
}
}
}
Expand Down Expand Up @@ -488,6 +493,13 @@ func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header
}).Error("Block has out of scope coinbase, skipping block reward")
return
}
if !header.Coinbase().IsInQuaiLedgerScope() {
logger.WithFields(log.Fields{
"Address": header.Coinbase().String(),
"Hash": header.Hash().String(),
}).Debug("Block coinbase is in Qi ledger, skipping Quai block reward") // this log is largely unnecessary
return
}

// Accumulate the rewards for the miner and any included uncles
reward := new(big.Int).Set(blockReward)
Expand Down
22 changes: 17 additions & 5 deletions consensus/progpow/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -480,11 +480,16 @@ func (progpow *Progpow) Finalize(chain consensus.ChainHeaderReader, header *type
if err != nil {
progpow.logger.Error("Provided address in genesis block is out of scope")
}
state.AddBalance(internal, account.Balance)
state.SetCode(internal, account.Code)
state.SetNonce(internal, account.Nonce)
for key, value := range account.Storage {
state.SetState(internal, key, value)
if addr.IsInQuaiLedgerScope() {
state.AddBalance(internal, account.Balance)
state.SetCode(internal, account.Code)
state.SetNonce(internal, account.Nonce)
for key, value := range account.Storage {
state.SetState(internal, key, value)
}
} else {
progpow.logger.WithField("address", addr.String()).Error("Provided address in genesis block alloc is not in the Quai ledger scope")
continue
}
}
}
Expand Down Expand Up @@ -522,6 +527,13 @@ func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header
logger.WithField("hash", header.Hash().String()).Error("Block has out-of-scope coinbase, skipping block reward")
return
}
if !header.Coinbase().IsInQuaiLedgerScope() {
logger.WithFields(log.Fields{
"Address": header.Coinbase().String(),
"Hash": header.Hash().String(),
}).Debug("Block coinbase is in Qi ledger, skipping Quai block reward") // this log is largely unnecessary
return
}

// Accumulate the rewards for the miner and any included uncles
reward := new(big.Int).Set(blockReward)
Expand Down
4 changes: 2 additions & 2 deletions core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -1155,7 +1155,7 @@ func (c *Core) Get(hash common.Hash) *types.Transaction {
}

func (c *Core) Nonce(addr common.Address) uint64 {
internal, err := addr.InternalAddress()
internal, err := addr.InternalAndQuaiAddress()
if err != nil {
return 0
}
Expand All @@ -1171,7 +1171,7 @@ func (c *Core) Content() (map[common.InternalAddress]types.Transactions, map[com
}

func (c *Core) ContentFrom(addr common.Address) (types.Transactions, types.Transactions) {
internal, err := addr.InternalAddress()
internal, err := addr.InternalAndQuaiAddress()
if err != nil {
return nil, nil
}
Expand Down
6 changes: 3 additions & 3 deletions core/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ func GetHashFn(ref *types.Header, chain ChainContext) func(n uint64) common.Hash
// CanTransfer checks whether there are enough funds in the address' account to make a transfer.
// This does not take the necessary gas in to account to make the transfer valid.
func CanTransfer(db vm.StateDB, addr common.Address, amount *big.Int) bool {
internalAddr, err := addr.InternalAddress()
internalAddr, err := addr.InternalAndQuaiAddress()
if err != nil {
return false
}
Expand All @@ -142,11 +142,11 @@ func CanTransfer(db vm.StateDB, addr common.Address, amount *big.Int) bool {

// Transfer subtracts amount from sender and adds amount to recipient using the given Db
func Transfer(db vm.StateDB, sender, recipient common.Address, amount *big.Int) error {
internalSender, err := sender.InternalAddress()
internalSender, err := sender.InternalAndQuaiAddress()
if err != nil {
return err
}
internalRecipient, err := recipient.InternalAddress()
internalRecipient, err := recipient.InternalAndQuaiAddress()
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion core/state/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []
account.SecureKey = it.Key
}
addr := common.BytesToAddress(addrBytes, s.nodeLocation)
internal, err := addr.InternalAddress()
internal, err := addr.InternalAndQuaiAddress()
if err != nil {
continue
}
Expand Down
2 changes: 1 addition & 1 deletion core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,7 @@ func (s *StateDB) GetOrNewStateObject(addr common.InternalAddress) *stateObject
// createObject creates a new state object. If there is an existing account with
// the given address, it is overwritten and returned as the second return value.
func (s *StateDB) createObject(addr common.InternalAddress) (newobj, prev *stateObject) {
if !common.IsInChainScope(addr.Bytes(), s.nodeLocation) {
if !common.IsInChainScope(addr.Bytes(), s.nodeLocation) || !addr.IsInQuaiLedgerScope() {
s.setError(fmt.Errorf("createObject (%x) error: %v", addr.Bytes(), common.ErrInvalidScope))
return nil, nil
}
Expand Down
12 changes: 6 additions & 6 deletions core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ func (st *StateTransition) buyGas() error {
balanceCheck = balanceCheck.Mul(balanceCheck, st.gasFeeCap)
balanceCheck.Add(balanceCheck, st.value)
}
from, err := st.msg.From().InternalAddress()
from, err := st.msg.From().InternalAndQuaiAddress()
if err != nil {
return err
}
Expand Down Expand Up @@ -238,7 +238,7 @@ func (st *StateTransition) subGasETX() error {
}

func (st *StateTransition) preCheck() error {
from, err := st.msg.From().InternalAddress()
from, err := st.msg.From().InternalAndQuaiAddress()
if err != nil {
return err
}
Expand Down Expand Up @@ -352,11 +352,11 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
contractAddr = &contract
} else {
// Increment the nonce for the next transaction
addr, err := sender.Address().InternalAddress()
addr, err := sender.Address().InternalAndQuaiAddress()
if err != nil {
return nil, err
}
from, err := msg.From().InternalAddress()
from, err := msg.From().InternalAndQuaiAddress()
if err != nil {
return nil, err
}
Expand All @@ -375,7 +375,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
st.refundGas(params.RefundQuotient)

effectiveTip := cmath.BigMin(st.gasTipCap, new(big.Int).Sub(st.gasFeeCap, st.evm.Context.BaseFee))
coinbase, err := st.evm.Context.Coinbase.InternalAddress()
coinbase, err := st.evm.Context.Coinbase.InternalAndQuaiAddress()
if err != nil {
return nil, err
}
Expand All @@ -400,7 +400,7 @@ func (st *StateTransition) refundGas(refundQuotient uint64) {

// Return ETH for remaining gas, exchanged at the original rate.
remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gas), st.gasPrice)
from, err := st.msg.From().InternalAddress()
from, err := st.msg.From().InternalAndQuaiAddress()
if err != nil {
return
}
Expand Down
31 changes: 18 additions & 13 deletions core/tx_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
addToCache := true
if sender := tx.From(); sender != nil { // Check tx cache first
var err error
internal, err = sender.InternalAddress()
internal, err = sender.InternalAndQuaiAddress()
if err != nil {
return err
}
Expand All @@ -706,7 +706,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
if err != nil {
return ErrInvalidSender
}
internal, err = from.InternalAddress()
internal, err = from.InternalAndQuaiAddress()
if err != nil {
return err
}
Expand Down Expand Up @@ -819,7 +819,7 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err e
if err != nil {
return false, err
}
internal, err := from.InternalAddress()
internal, err := from.InternalAndQuaiAddress()
if err != nil {
return false, err
}
Expand Down Expand Up @@ -883,7 +883,7 @@ func (pool *TxPool) enqueueTx(hash common.Hash, tx *types.Transaction, local boo
if err != nil {
return false, err
}
internal, err := from.InternalAddress()
internal, err := from.InternalAndQuaiAddress()
if err != nil {
return false, err
}
Expand Down Expand Up @@ -1040,12 +1040,17 @@ func (pool *TxPool) addTxs(txs []*types.Transaction, local, sync bool) []error {
pool.addUtxoTx(tx)
continue
}
if tx.To().IsInQiLedgerScope() {
errs[i] = common.MakeErrQiAddress(tx.To().Hex())
invalidTxMeter.Add(1)
continue
}
// Exclude transactions with invalid signatures as soon as
// possible and cache senders in transactions before
// obtaining lock
if sender := tx.From(); sender != nil {
var err error
_, err = sender.InternalAddress()
_, err = sender.InternalAndQuaiAddress()
if err != nil {
errs[i] = err
invalidTxMeter.Add(1)
Expand All @@ -1060,9 +1065,9 @@ func (pool *TxPool) addTxs(txs []*types.Transaction, local, sync bool) []error {
invalidTxMeter.Add(1)
continue
}
_, err = from.InternalAddress()
_, err = from.InternalAndQuaiAddress()
if err != nil {
errs[i] = ErrInvalidSender
errs[i] = err
invalidTxMeter.Add(1)
continue
}
Expand Down Expand Up @@ -1201,7 +1206,7 @@ func (pool *TxPool) Status(hashes []common.Hash) []TxStatus {
if err != nil {
continue
}
internal, err := from.InternalAddress()
internal, err := from.InternalAndQuaiAddress()
if err != nil {
continue
}
Expand Down Expand Up @@ -1241,7 +1246,7 @@ func (pool *TxPool) removeTx(hash common.Hash, outofbound bool) {
if err != nil {
return
}
internal, err := addr.InternalAddress()
internal, err := addr.InternalAndQuaiAddress()
if err != nil {
return
}
Expand Down Expand Up @@ -1375,7 +1380,7 @@ func (pool *TxPool) scheduleReorgLoop() {
if err != nil {
continue
}
internal, err := addr.InternalAddress()
internal, err := addr.InternalAndQuaiAddress()
if err != nil {
pool.logger.WithField("err", err).Debug("Failed to queue transaction")
continue
Expand Down Expand Up @@ -1469,7 +1474,7 @@ func (pool *TxPool) runReorg(done chan struct{}, cancel chan struct{}, reset *tx
if err != nil {
continue
}
internal, err := addr.InternalAddress()
internal, err := addr.InternalAndQuaiAddress()
if err != nil {
pool.logger.WithField("err", err).Debug("Failed to add transaction event")
continue
Expand Down Expand Up @@ -1994,7 +1999,7 @@ func (as *accountSet) empty() bool {
// cannot be derived, this method returns false.
func (as *accountSet) containsTx(tx *types.Transaction) bool {
if addr, err := types.Sender(as.signer, tx); err == nil {
internal, err := addr.InternalAddress()
internal, err := addr.InternalAndQuaiAddress()
if err != nil {
return false
}
Expand All @@ -2012,7 +2017,7 @@ func (as *accountSet) add(addr common.InternalAddress) {
// addTx adds the sender of tx into the set.
func (as *accountSet) addTx(tx *types.Transaction, logger *log.Logger) {
if addr, err := types.Sender(as.signer, tx); err == nil {
internal, err := addr.InternalAddress()
internal, err := addr.InternalAndQuaiAddress()
if err != nil {
logger.WithField("err", err).Debug("Failed to add tx to account set")
return
Expand Down
6 changes: 6 additions & 0 deletions core/types/transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,9 @@ func TestTransactionHashing(t *testing.T) {
require.NotEqual(t, hash, txHash)

}

func TestQiAddressScope(t *testing.T) {
addr := common.HexToAddress("0x001a1C308B372Fe50E7eA2Df8323d57a08a89f83", common.Location{0, 0})
t.Log(addr.IsInQiLedgerScope())
t.Log(addr.IsInQuaiLedgerScope())
}
Loading

0 comments on commit e1112bc

Please sign in to comment.