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

Added Quai ledger scope checks to all EVM state interactions #117

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 36 additions & 4 deletions common/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,51 @@ 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")
)

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
return a.Bytes()[1] > 127
}

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] <= 127
}

func (a Address) Equal(b Address) bool {
Expand Down Expand Up @@ -329,3 +357,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] <= 127
}
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
15 changes: 9 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,11 +375,14 @@ 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()
if err != nil {
return nil, err
}
st.state.AddBalance(coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), effectiveTip)) // todo: etxs no longer pay the miner a fee
if coinbase.IsInQuaiLedgerScope() {
st.state.AddBalance(coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), effectiveTip)) // todo: etxs no longer pay the miner a fee
}

return &ExecutionResult{
UsedGas: st.gasUsed(),
Expand All @@ -400,7 +403,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
Loading
Loading