Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stateprice for Quai #2049

Merged
merged 11 commits into from
Sep 6, 2024
Merged
10 changes: 10 additions & 0 deletions consensus/blake3pow/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,15 @@ func (blake3pow *Blake3pow) verifyHeader(chain consensus.ChainHeaderReader, head
return fmt.Errorf("invalid baseFee: have %s, want %s, parentBaseFee %s, parentGasUsed %d",
expectedBaseFee, header.BaseFee(), parent.BaseFee(), parent.GasUsed())
}
// Verify that the stateUsed is <= stateLimit
if header.StateUsed() > header.StateLimit() {
return fmt.Errorf("invalid stateUsed: have %d, stateLimit %d", header.StateUsed(), header.StateLimit())
}
// Verify the stateLimit is correct based on the parent header.
expectedStateLimit := misc.CalcStateLimit(parent, params.StateCeil)
if header.StateLimit() != expectedStateLimit {
return fmt.Errorf("invalid stateLimit: have %v, want %v, parentStateLimit %v", expectedStateLimit, header.StateLimit(), parent.StateLimit())
}
var expectedPrimeTerminus common.Hash
_, parentOrder, _ := blake3pow.CalcOrder(chain, parent)
if parentOrder == common.PRIME_CTX {
Expand Down Expand Up @@ -642,6 +651,7 @@ func (blake3pow *Blake3pow) Finalize(chain consensus.ChainHeaderReader, header *
header.Header().SetUTXORoot(state.UTXORoot())
header.Header().SetEVMRoot(state.IntermediateRoot(true))
header.Header().SetEtxSetRoot(state.ETXRoot())
header.Header().SetQuaiStateSize(state.GetQuaiTrieSize())
}

// FinalizeAndAssemble implements consensus.Engine, accumulating the block and
Expand Down
43 changes: 43 additions & 0 deletions consensus/misc/statefee.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package misc

import (
"github.com/dominant-strategies/go-quai/common"
"github.com/dominant-strategies/go-quai/core/types"
"github.com/dominant-strategies/go-quai/params"
)

func CalcStateLimit(parent *types.WorkObject, stateCeil uint64) uint64 {
// No Gas for TimeToStartTx days worth of zone blocks, this gives enough time to
// onboard new miners into the slice
if parent.NumberU64(common.ZONE_CTX) < params.TimeToStartTx {
return 0
}

// If parent gas is zero and we have passed the 5 day threshold, we can set the first block gas limit to min gas limit
if parent.StateLimit() == 0 {
return params.MinGasLimit
}

parentStateLimit := parent.StateLimit()

delta := parentStateLimit/params.StateLimitBoundDivisor - 1
limit := parentStateLimit

var desiredLimit uint64
percentStateUsed := parent.StateUsed() * 100 / parent.StateLimit()
if percentStateUsed > params.PercentStateUsedThreshold {
desiredLimit = stateCeil
if limit+delta > desiredLimit {
return desiredLimit
} else {
return limit + delta
}
} else {
desiredLimit = params.MinGasLimit
if limit-delta/2 < desiredLimit {
return desiredLimit
} else {
return limit - delta/2
}
}
}
10 changes: 10 additions & 0 deletions consensus/progpow/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,15 @@ func (progpow *Progpow) verifyHeader(chain consensus.ChainHeaderReader, header,
return fmt.Errorf("invalid baseFee: have %s, want %s, parentBaseFee %s, parentGasUsed %d",
expectedBaseFee, header.BaseFee(), parent.BaseFee(), parent.GasUsed())
}
// Verify that the stateUsed is <= stateLimit
if header.StateUsed() > header.StateLimit() {
return fmt.Errorf("invalid stateUsed: have %d, stateLimit %d", header.StateUsed(), header.StateLimit())
}
// Verify the StateLimit is correct based on the parent header.
expectedStateLimit := misc.CalcStateLimit(parent, params.StateCeil)
if header.StateLimit() != expectedStateLimit {
return fmt.Errorf("invalid StateLimit: have %d, want %d, parentStateLimit %d", expectedStateLimit, header.StateLimit(), parent.StateLimit())
}
var expectedPrimeTerminus common.Hash
var expectedPrimeTerminusNumber *big.Int
_, parentOrder, _ := progpow.CalcOrder(chain, parent)
Expand Down Expand Up @@ -698,6 +707,7 @@ func (progpow *Progpow) Finalize(chain consensus.ChainHeaderReader, header *type
header.Header().SetUTXORoot(state.UTXORoot())
header.Header().SetEVMRoot(state.IntermediateRoot(true))
header.Header().SetEtxSetRoot(state.ETXRoot())
header.Header().SetQuaiStateSize(state.GetQuaiTrieSize())
}

// FinalizeAndAssemble implements consensus.Engine, accumulating the block and
Expand Down
8 changes: 7 additions & 1 deletion core/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,13 +261,16 @@ func (v *BlockValidator) SanityCheckWorkObjectShareViewBody(wo *types.WorkObject
// transition, such as amount of used gas, the receipt roots and the state root
// itself. ValidateState returns a database batch if the validation was a success
// otherwise nil and an error is returned.
func (v *BlockValidator) ValidateState(block *types.WorkObject, statedb *state.StateDB, receipts types.Receipts, etxs types.Transactions, usedGas uint64) error {
func (v *BlockValidator) ValidateState(block *types.WorkObject, statedb *state.StateDB, receipts types.Receipts, etxs types.Transactions, usedGas uint64, usedState uint64) error {
start := time.Now()
header := types.CopyHeader(block.Header())
time1 := common.PrettyDuration(time.Since(start))
if block.GasUsed() != usedGas {
return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas)
}
if block.StateUsed() != usedState {
return fmt.Errorf("invalid state used (remote: %d local: %d)", block.StateUsed(), usedState)
}
time2 := common.PrettyDuration(time.Since(start))
time3 := common.PrettyDuration(time.Since(start))
// Tre receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, Rn]]))
Expand All @@ -281,6 +284,9 @@ func (v *BlockValidator) ValidateState(block *types.WorkObject, statedb *state.S
if root := statedb.IntermediateRoot(true); header.EVMRoot() != root {
return fmt.Errorf("invalid merkle root (remote: %x local: %x)", header.EVMRoot(), root)
}
if stateSize := statedb.GetQuaiTrieSize(); header.QuaiStateSize().Cmp(stateSize) != 0 {
return fmt.Errorf("invalid quai trie size (remote: %x local: %x)", header.QuaiStateSize(), stateSize)
}
if root := statedb.UTXORoot(); header.UTXORoot() != root {
return fmt.Errorf("invalid utxo root (remote: %x local: %x)", header.UTXORoot(), root)
}
Expand Down
7 changes: 4 additions & 3 deletions core/chain_indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"encoding/binary"
"errors"
"fmt"
"math/big"
"runtime/debug"
"sync"
"sync/atomic"
Expand Down Expand Up @@ -67,7 +68,7 @@ type ChainIndexerChain interface {
// NodeCtx returns the context of the chain
NodeCtx() int
// StateAt returns the state for a state trie root and utxo root
StateAt(root common.Hash, utxoRoot common.Hash, etxRoot common.Hash) (*state.StateDB, error)
StateAt(root common.Hash, utxoRoot common.Hash, etxRoot common.Hash, quaiStateSize *big.Int) (*state.StateDB, error)
}

// ChainIndexer does a post-processing job for equally sized sections of the
Expand All @@ -85,7 +86,7 @@ type ChainIndexer struct {
backend ChainIndexerBackend // Background processor generating the index data content
children []*ChainIndexer // Child indexers to cascade chain updates to
GetBloom func(common.Hash) (*types.Bloom, error)
StateAt func(common.Hash, common.Hash, common.Hash) (*state.StateDB, error)
StateAt func(common.Hash, common.Hash, common.Hash, *big.Int) (*state.StateDB, error)
active uint32 // Flag whether the event loop was started
update chan struct{} // Notification channel that headers should be processed
quit chan chan error // Quit channel to tear down running goroutines
Expand Down Expand Up @@ -666,7 +667,7 @@ func (c *ChainIndexer) reorgUtxoIndexer(headers []*types.WorkObject, addressOutp
}
parent := rawdb.ReadHeader(c.chainDb, *parentNumber, block.ParentHash(nodeCtx))

state, err := c.StateAt(parent.EVMRoot(), parent.UTXORoot(), parent.EtxSetRoot())
state, err := c.StateAt(parent.EVMRoot(), parent.UTXORoot(), parent.EtxSetRoot(), parent.QuaiStateSize())
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -1146,8 +1146,8 @@ func (c *Core) State() (*state.StateDB, error) {
}

// StateAt returns a new mutable state based on a particular point in time.
func (c *Core) StateAt(root, utxoRoot, etxRoot common.Hash) (*state.StateDB, error) {
return c.sl.hc.bc.processor.StateAt(root, utxoRoot, etxRoot)
func (c *Core) StateAt(root, utxoRoot, etxRoot common.Hash, quaiStateSize *big.Int) (*state.StateDB, error) {
return c.sl.hc.bc.processor.StateAt(root, utxoRoot, etxRoot, quaiStateSize)
}

// StateCache returns the caching database underpinning the blockchain instance.
Expand Down
1 change: 1 addition & 0 deletions core/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ func NewEVMBlockContext(header *types.WorkObject, parent *types.WorkObject, chai
GasLimit: header.GasLimit(),
CheckIfEtxEligible: chain.CheckIfEtxIsEligible,
EtxEligibleSlices: etxEligibleSlices,
QuaiStateSize: parent.QuaiStateSize(), // using the state size at the parent for all the gas calculations
}, nil
}

Expand Down
4 changes: 3 additions & 1 deletion core/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, nodeLoca
// We have the genesis block in database(perhaps in ancient database)
// but the corresponding state is missing.
header := rawdb.ReadHeader(db, 0, stored)
if _, err := state.New(header.EVMRoot(), header.UTXORoot(), header.EtxSetRoot(), state.NewDatabaseWithConfig(db, nil), state.NewDatabaseWithConfig(db, nil), state.NewDatabaseWithConfig(db, nil), nil, nodeLocation, logger); err != nil {
if _, err := state.New(header.EVMRoot(), header.UTXORoot(), header.EtxSetRoot(), header.QuaiStateSize(), state.NewDatabaseWithConfig(db, nil), state.NewDatabaseWithConfig(db, nil), state.NewDatabaseWithConfig(db, nil), nil, nodeLocation, logger); err != nil {
if genesis == nil {
genesis = DefaultGenesisBlock()
}
Expand Down Expand Up @@ -288,6 +288,8 @@ func (g *Genesis) ToBlock(startingExpansionNumber uint64) *types.WorkObject {
wo.Header().SetEtxEligibleSlices(common.Hash{})
}
wo.Header().SetBaseFee(new(big.Int).SetUint64(params.InitialBaseFee))
wo.Header().SetStateLimit(params.InitialStateLimit)
wo.Header().SetStateUsed(0)
wo.Header().SetEtxSetRoot(types.EmptyRootHash)
if g.GasLimit == 0 {
wo.Header().SetGasLimit(params.GenesisGasLimit)
Expand Down
4 changes: 2 additions & 2 deletions core/headerchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -1011,8 +1011,8 @@ func (hc *HeaderChain) SubscribeChainSideEvent(ch chan<- ChainSideEvent) event.S
return hc.scope.Track(hc.chainSideFeed.Subscribe(ch))
}

func (hc *HeaderChain) StateAt(root, utxoRoot, etxRoot common.Hash) (*state.StateDB, error) {
return hc.bc.processor.StateAt(root, utxoRoot, etxRoot)
func (hc *HeaderChain) StateAt(root, utxoRoot, etxRoot common.Hash, quaiStateSize *big.Int) (*state.StateDB, error) {
return hc.bc.processor.StateAt(root, utxoRoot, etxRoot, quaiStateSize)
}

func (hc *HeaderChain) SlicesRunning() []common.Location {
Expand Down
3 changes: 3 additions & 0 deletions core/slice.go
Original file line number Diff line number Diff line change
Expand Up @@ -1405,6 +1405,7 @@ func (sl *Slice) combinePendingHeader(header *types.WorkObject, slPendingHeader

combinedPendingHeader.Header().SetEtxRollupHash(header.EtxRollupHash())
combinedPendingHeader.Header().SetUncledS(header.Header().UncledS())
combinedPendingHeader.Header().SetQuaiStateSize(header.Header().QuaiStateSize())
combinedPendingHeader.Header().SetUncleHash(header.UncleHash())
combinedPendingHeader.Header().SetTxHash(header.Header().TxHash())
combinedPendingHeader.Header().SetEtxHash(header.EtxHash())
Expand All @@ -1414,6 +1415,8 @@ func (sl *Slice) combinePendingHeader(header *types.WorkObject, slPendingHeader
combinedPendingHeader.Header().SetUTXORoot(header.UTXORoot())
combinedPendingHeader.Header().SetEtxSetRoot(header.EtxSetRoot())
combinedPendingHeader.Header().SetBaseFee(header.BaseFee())
combinedPendingHeader.Header().SetStateLimit(header.StateLimit())
combinedPendingHeader.Header().SetStateUsed(header.StateUsed())
combinedPendingHeader.Header().SetGasLimit(header.GasLimit())
combinedPendingHeader.Header().SetGasUsed(header.GasUsed())
combinedPendingHeader.Header().SetExtra(header.Extra())
Expand Down
2 changes: 2 additions & 0 deletions core/state/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ type DumpAccount struct {
Root hexutil.Bytes `json:"root"`
CodeHash hexutil.Bytes `json:"codeHash"`
Code hexutil.Bytes `json:"code,omitempty"`
Size string `json:"size"`
Storage map[common.Hash]string `json:"storage,omitempty"`
Address *common.InternalAddress `json:"address,omitempty"` // Address only present in iterative (line-by-line) mode
SecureKey hexutil.Bytes `json:"key,omitempty"` // If we don't have address, we can output the key
Expand Down Expand Up @@ -149,6 +150,7 @@ func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []
Nonce: data.Nonce,
Root: data.Root[:],
CodeHash: data.CodeHash,
Size: data.Size.String(),
SecureKey: it.Key,
}
addrBytes := s.trie.GetKey(it.Key)
Expand Down
12 changes: 12 additions & 0 deletions core/state/journal.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ type (
account *common.InternalAddress
prevcode, prevhash []byte
}
sizeChange struct {
account *common.InternalAddress
prev *big.Int
}

// Changes to other state values.
refundChange struct {
Expand Down Expand Up @@ -211,6 +215,14 @@ func (ch storageChange) dirtied() *common.InternalAddress {
return ch.account
}

func (ch sizeChange) revert(s *StateDB) {
s.getStateObject(*ch.account).SetSize(ch.prev)
}

func (ch sizeChange) dirtied() *common.InternalAddress {
return ch.account
}

func (ch refundChange) revert(s *StateDB) {
s.refund = ch.prev
}
Expand Down
8 changes: 5 additions & 3 deletions core/state/snapshot/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ type Account struct {
Balance *big.Int
Root []byte
CodeHash []byte
Size *big.Int
}

// SlimAccount converts a state.Account content into a slim snapshot account
func SlimAccount(nonce uint64, balance *big.Int, root common.Hash, codehash []byte) Account {
func SlimAccount(nonce uint64, balance *big.Int, root common.Hash, codehash []byte, size *big.Int) Account {
slim := Account{
Nonce: nonce,
Balance: balance,
Size: size,
}
if root != emptyRoot {
slim.Root = root[:]
Expand All @@ -52,8 +54,8 @@ func SlimAccount(nonce uint64, balance *big.Int, root common.Hash, codehash []by

// SlimAccountRLP converts a state.Account content into a slim snapshot
// version RLP encoded.
func SlimAccountRLP(nonce uint64, balance *big.Int, root common.Hash, codehash []byte) []byte {
data, err := rlp.EncodeToBytes(SlimAccount(nonce, balance, root, codehash))
func SlimAccountRLP(nonce uint64, balance *big.Int, root common.Hash, codehash []byte, size *big.Int) []byte {
data, err := rlp.EncodeToBytes(SlimAccount(nonce, balance, root, codehash, size))
if err != nil {
panic(err)
}
Expand Down
3 changes: 2 additions & 1 deletion core/state/snapshot/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,7 @@ func (dl *diskLayer) generate(stats *generatorStats) {
Balance *big.Int
Root common.Hash
CodeHash []byte
Size *big.Int
}
if err := rlp.DecodeBytes(val, &acc); err != nil {
stats.logger.WithField("err", err).Fatal("Invalid account encountered during snapshot creation")
Expand All @@ -581,7 +582,7 @@ func (dl *diskLayer) generate(stats *generatorStats) {
dataLen -= 32
}
} else {
data := SlimAccountRLP(acc.Nonce, acc.Balance, acc.Root, acc.CodeHash)
data := SlimAccountRLP(acc.Nonce, acc.Balance, acc.Root, acc.CodeHash, acc.Size)
dataLen = len(data)
rawdb.WriteAccountSnapshot(batch, accountHash, data)
}
Expand Down
Loading
Loading