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

Remove ExternalTransactions from QuaiTransactions and disable receipts from Qi ETXs #1862

Merged
merged 2 commits into from
Jun 28, 2024
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
4 changes: 2 additions & 2 deletions core/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,11 @@ func NewEVMBlockContext(header *types.WorkObject, chain ChainContext, author *co
}
}

// Prime terminus determines which location is eligible to except the etx
// Prime terminus determines which location is eligible to accept the etx
primeTerminus := header.PrimeTerminus()
primeTerminusHeader := chain.GetHeaderByHash(primeTerminus)
if primeTerminusHeader == nil {
log.Global.Error("Prime terminus header not found", "headerHash", header.Hash(), "primeTerminus", primeTerminus)
log.Global.Error("Prime terminus header not found ", " headerHash ", header.Hash(), " primeTerminus ", primeTerminus)
return vm.BlockContext{}, ErrSubNotSyncedToDom
}
etxEligibleSlices := primeTerminusHeader.EtxEligibleSlices()
Expand Down
2 changes: 1 addition & 1 deletion core/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ func DefaultLocalGenesisBlock(consensusEngine string) *Genesis {
Nonce: 66,
ExtraData: hexutil.MustDecode("0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fb"),
GasLimit: 5000000,
Difficulty: big.NewInt(5000000),
Difficulty: big.NewInt(500000),
}
}
return &Genesis{
Expand Down
2 changes: 1 addition & 1 deletion core/rawdb/accessors_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -965,7 +965,7 @@ func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, config *para
}).Error("Missing body but have receipt")
return nil
}
if err := receipts.DeriveFields(config, hash, number, body.QuaiTransactionsWithoutCoinbase()); err != nil {
if err := receipts.DeriveFields(config, hash, number, body.TransactionsWithReceipts()); err != nil {
db.Logger().WithFields(log.Fields{
"hash": hash,
"number": number,
Expand Down
9 changes: 7 additions & 2 deletions core/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ func (p *StateProcessor) Process(block *types.WorkObject) (types.Receipts, []*ty
timePrepare += timePrepareDelta

var receipt *types.Receipt
var addReceipt bool
if tx.Type() == types.ExternalTxType {
startTimeEtx := time.Now()
// ETXs MUST be included in order, so popping the first from the queue must equal the first in the block
Expand Down Expand Up @@ -418,6 +419,7 @@ func (p *StateProcessor) Process(block *types.WorkObject) (types.Receipts, []*ty
if err != nil {
return nil, nil, nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
}
addReceipt = true
totalEtxGas += receipt.GasUsed
timeEtxDelta := time.Since(startTimeEtx)
timeEtx += timeEtxDelta
Expand All @@ -429,6 +431,7 @@ func (p *StateProcessor) Process(block *types.WorkObject) (types.Receipts, []*ty
if err != nil {
return nil, nil, nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
}
addReceipt = true
timeTxDelta := time.Since(startTimeTx)
timeTx += timeTxDelta
} else {
Expand All @@ -439,8 +442,10 @@ func (p *StateProcessor) Process(block *types.WorkObject) (types.Receipts, []*ty
emittedEtxs = append(emittedEtxs, etx)
}
}
receipts = append(receipts, receipt)
allLogs = append(allLogs, receipt.Logs...)
if addReceipt {
receipts = append(receipts, receipt)
allLogs = append(allLogs, receipt.Logs...)
}
i++
}

Expand Down
30 changes: 18 additions & 12 deletions core/types/wo.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,14 +340,30 @@ func (wo *WorkObject) QiTransactionsWithoutCoinbase() []*Transaction {
return qiTxs
}

func (wo *WorkObject) TransactionsWithReceipts() []*Transaction {
txs := make([]*Transaction, 0)
for i, t := range wo.Transactions() {
if i == 0 && IsCoinBaseTx(t, wo.woHeader.parentHash, wo.woHeader.location) {
// ignore the coinbase tx
continue
}
if t.Type() == QuaiTxType || (t.Type() == ExternalTxType && t.To().IsInQuaiLedgerScope()) {
txs = append(txs, t)
}
}
return txs
}

// QuaiTransactionsWithoutCoinbase returns all Quai EVM transactions in the block, excluding the coinbase transaction.
// This also returns all transactions that have an associated receipt.
func (wo *WorkObject) QuaiTransactionsWithoutCoinbase() []*Transaction {
quaiTxs := make([]*Transaction, 0)
for i, t := range wo.Transactions() {
if i == 0 && IsCoinBaseTx(t, wo.woHeader.parentHash, wo.woHeader.location) || t.Type() == QiTxType || (t.Type() == ExternalTxType && t.To().IsInQiLedgerScope()) {
// ignore the Quai coinbase tx and Quai->Qi to comply with prior functionality as it is not a normal transaction
continue
}
if t.Type() != QiTxType {
if t.Type() == QuaiTxType {
quaiTxs = append(quaiTxs, t)
}
}
Expand All @@ -370,16 +386,6 @@ func (wo *WorkObject) InputsAndOutputsWithoutCoinbase() (uint, uint) {
return uint(inputs), uint(outputs)
}

func (wo *WorkObject) QuaiTransactionsWithFees() []*Transaction {
quaiTxs := make([]*Transaction, 0)
for _, t := range wo.Transactions() {
if t.Type() == QuaiTxType { // QuaiTxType is the only type that gives Quai fees to the miner
quaiTxs = append(quaiTxs, t)
}
}
return quaiTxs
}

func (wo *WorkObject) NumberArray() []*big.Int {
numArray := make([]*big.Int, common.HierarchyDepth)
for i := 0; i < common.HierarchyDepth; i++ {
Expand Down Expand Up @@ -579,7 +585,7 @@ func (wb *WorkObjectBody) QiTransactions() []*Transaction {
func (wb *WorkObjectBody) QuaiTransactions() []*Transaction {
quaiTxs := make([]*Transaction, 0)
for _, t := range wb.Transactions() {
if t.Type() != QiTxType {
if t.Type() == QuaiTxType {
quaiTxs = append(quaiTxs, t)
}
}
Expand Down
152 changes: 78 additions & 74 deletions core/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -732,84 +732,84 @@ func (w *worker) commitUncle(env *environment, uncle *types.WorkObjectHeader) er
return nil
}

func (w *worker) commitTransaction(env *environment, parent *types.WorkObject, tx *types.Transaction) ([]*types.Log, error) {
if tx != nil {
if tx.Type() == types.ExternalTxType && tx.To().IsInQiLedgerScope() {
gasUsed := env.wo.GasUsed()
txGas := tx.Gas()
if tx.ETXSender().Location().Equal(*tx.To().Location()) { // Quai->Qi conversion
lock := new(big.Int).Add(env.wo.Number(w.hc.NodeCtx()), big.NewInt(params.ConversionLockPeriod))
primeTerminus := w.hc.GetPrimeTerminus(env.wo)
if primeTerminus == nil {
return nil, errors.New("prime terminus not found")
func (w *worker) commitTransaction(env *environment, parent *types.WorkObject, tx *types.Transaction) ([]*types.Log, bool, error) {
if tx == nil {
return nil, false, errors.New("nil transaction")
}
if tx.Type() == types.ExternalTxType && tx.To().IsInQiLedgerScope() {
gasUsed := env.wo.GasUsed()
txGas := tx.Gas()
if tx.ETXSender().Location().Equal(*tx.To().Location()) { // Quai->Qi conversion
lock := new(big.Int).Add(env.wo.Number(w.hc.NodeCtx()), big.NewInt(params.ConversionLockPeriod))
primeTerminus := w.hc.GetPrimeTerminus(env.wo)
if primeTerminus == nil {
return nil, false, errors.New("prime terminus not found")
}
value := misc.QuaiToQi(primeTerminus, tx.Value())
denominations := misc.FindMinDenominations(value)
outputIndex := uint16(0)

// Iterate over the denominations in descending order
for denomination := types.MaxDenomination; denomination >= 0; denomination-- {
// If the denomination count is zero, skip it
if denominations[uint8(denomination)] == 0 {
continue
}
value := misc.QuaiToQi(primeTerminus, tx.Value())
denominations := misc.FindMinDenominations(value)
outputIndex := uint16(0)

// Iterate over the denominations in descending order
for denomination := types.MaxDenomination; denomination >= 0; denomination-- {
// If the denomination count is zero, skip it
if denominations[uint8(denomination)] == 0 {
continue
for j := uint8(0); j < denominations[uint8(denomination)]; j++ {
if txGas < params.CallValueTransferGas || outputIndex >= types.MaxOutputIndex {
// No more gas, the rest of the denominations are lost but the tx is still valid
break
}
for j := uint8(0); j < denominations[uint8(denomination)]; j++ {
if txGas < params.CallValueTransferGas || outputIndex >= types.MaxOutputIndex {
// No more gas, the rest of the denominations are lost but the tx is still valid
break
}
txGas -= params.CallValueTransferGas
if err := env.gasPool.SubGas(params.CallValueTransferGas); err != nil {
return nil, err
}
gasUsed += params.CallValueTransferGas
// the ETX hash is guaranteed to be unique
if err := env.state.CreateUTXO(tx.Hash(), outputIndex, types.NewUtxoEntry(types.NewTxOut(uint8(denomination), tx.To().Bytes(), lock))); err != nil {
return nil, err
}
outputIndex++
txGas -= params.CallValueTransferGas
if err := env.gasPool.SubGas(params.CallValueTransferGas); err != nil {
return nil, false, err
}
gasUsed += params.CallValueTransferGas
// the ETX hash is guaranteed to be unique
if err := env.state.CreateUTXO(tx.Hash(), outputIndex, types.NewUtxoEntry(types.NewTxOut(uint8(denomination), tx.To().Bytes(), lock))); err != nil {
return nil, false, err
}
outputIndex++
}
} else {
// This Qi ETX should cost more gas
if err := env.gasPool.SubGas(params.CallValueTransferGas); err != nil {
return nil, err
}
if err := env.state.CreateUTXO(tx.OriginatingTxHash(), tx.ETXIndex(), types.NewUtxoEntry(types.NewTxOut(uint8(tx.Value().Uint64()), tx.To().Bytes(), big.NewInt(0)))); err != nil {
return nil, err
}
gasUsed += params.CallValueTransferGas
}
env.wo.Header().SetGasUsed(gasUsed)
env.txs = append(env.txs, tx)
return []*types.Log{}, nil // need to make sure this does not modify receipt hash
}
snap := env.state.Snapshot()
// retrieve the gas used int and pass in the reference to the ApplyTransaction
gasUsed := env.wo.GasUsed()
receipt, err := ApplyTransaction(w.chainConfig, parent, w.hc, &env.coinbase, env.gasPool, env.state, env.wo, tx, &gasUsed, *w.hc.bc.processor.GetVMConfig(), &env.etxRLimit, &env.etxPLimit, w.logger)
if err != nil {
w.logger.WithFields(log.Fields{
"err": err,
"tx": tx.Hash().Hex(),
"block": env.wo.Number(w.hc.NodeCtx()),
"gasUsed": gasUsed,
}).Debug("Error playing transaction in worker")
env.state.RevertToSnapshot(snap)
return nil, err
}
if receipt.Status == types.ReceiptStatusSuccessful {
env.etxs = append(env.etxs, receipt.Etxs...)
} else {
// This Qi ETX should cost more gas
if err := env.gasPool.SubGas(params.CallValueTransferGas); err != nil {
return nil, false, err
}
if err := env.state.CreateUTXO(tx.OriginatingTxHash(), tx.ETXIndex(), types.NewUtxoEntry(types.NewTxOut(uint8(tx.Value().Uint64()), tx.To().Bytes(), big.NewInt(0)))); err != nil {
return nil, false, err
}
gasUsed += params.CallValueTransferGas
}
// once the gasUsed pointer is updated in the ApplyTransaction it has to be set back to the env.Header.GasUsed
// This extra step is needed because previously the GasUsed was a public method and direct update of the value
// was possible.
env.wo.Header().SetGasUsed(gasUsed)
env.txs = append(env.txs, tx)
env.receipts = append(env.receipts, receipt)
return receipt.Logs, nil
return []*types.Log{}, false, nil
}
return nil, errors.New("error finding transaction")
snap := env.state.Snapshot()
// retrieve the gas used int and pass in the reference to the ApplyTransaction
gasUsed := env.wo.GasUsed()
receipt, err := ApplyTransaction(w.chainConfig, parent, w.hc, &env.coinbase, env.gasPool, env.state, env.wo, tx, &gasUsed, *w.hc.bc.processor.GetVMConfig(), &env.etxRLimit, &env.etxPLimit, w.logger)
if err != nil {
w.logger.WithFields(log.Fields{
"err": err,
"tx": tx.Hash().Hex(),
"block": env.wo.Number(w.hc.NodeCtx()),
"gasUsed": gasUsed,
}).Debug("Error playing transaction in worker")
env.state.RevertToSnapshot(snap)
return nil, false, err
}
if receipt.Status == types.ReceiptStatusSuccessful {
env.etxs = append(env.etxs, receipt.Etxs...)
}
// once the gasUsed pointer is updated in the ApplyTransaction it has to be set back to the env.Header.GasUsed
// This extra step is needed because previously the GasUsed was a public method and direct update of the value
// was possible.
env.wo.Header().SetGasUsed(gasUsed)
env.txs = append(env.txs, tx)
env.receipts = append(env.receipts, receipt)
return receipt.Logs, true, nil
}

func (w *worker) commitTransactions(env *environment, parent *types.WorkObject, txs *types.TransactionsByPriceAndNonce, interrupt *int32) bool {
Expand Down Expand Up @@ -853,10 +853,12 @@ func (w *worker) commitTransactions(env *environment, parent *types.WorkObject,
break
}
env.state.Prepare(etx.Hash(), env.tcount)
logs, err := w.commitTransaction(env, parent, etx)
if err == nil {
logs, receipt, err := w.commitTransaction(env, parent, etx)
if err == nil && receipt {
coalescedLogs = append(coalescedLogs, logs...)
env.tcount++
} else if err == nil && !receipt {
env.tcount++
}
oldestIndex.Add(oldestIndex, big.NewInt(1))
}
Expand Down Expand Up @@ -926,7 +928,7 @@ func (w *worker) commitTransactions(env *environment, parent *types.WorkObject,
// Start executing the transaction
env.state.Prepare(tx.Hash(), env.tcount)

logs, err := w.commitTransaction(env, parent, tx)
logs, receipt, err := w.commitTransaction(env, parent, tx)
switch {
case errors.Is(err, types.ErrGasLimitReached):
// Pop the current out-of-gas transaction without shifting in the next from the account
Expand Down Expand Up @@ -956,7 +958,9 @@ func (w *worker) commitTransactions(env *environment, parent *types.WorkObject,

case errors.Is(err, nil):
// Everything ok, collect the logs and shift in the next transaction from the same account
coalescedLogs = append(coalescedLogs, logs...)
if receipt {
coalescedLogs = append(coalescedLogs, logs...)
}
env.tcount++
txs.PopNoSort()

Expand Down Expand Up @@ -1433,7 +1437,7 @@ func copyReceipts(receipts []*types.Receipt) []*types.Receipt {
// totalFees computes total consumed miner fees in ETH. Block transactions and receipts have to have the same order.
func totalFees(block *types.WorkObject, receipts []*types.Receipt) *big.Float {
feesWei := new(big.Int)
for i, tx := range block.QuaiTransactionsWithoutCoinbase() {
for i, tx := range block.TransactionsWithReceipts() {
minerFee, _ := tx.EffectiveGasTip(block.BaseFee())
feesWei.Add(feesWei, new(big.Int).Mul(new(big.Int).SetUint64(receipts[i].GasUsed), minerFee))
}
Expand Down
2 changes: 1 addition & 1 deletion params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ var (
Blake3PowColosseumGenesisHash = common.HexToHash("0x301114d60dd28adcc51872021d16591e3ed300cbcb0a72f363aeedeef09c2cbb")
Blake3PowGardenGenesisHash = common.HexToHash("0xcc765ce0d79736950aeded81e32bbd55a03c4dcec236c1944da32609a237fadc")
Blake3PowOrchardGenesisHash = common.HexToHash("0x3b9f95bf2e01aa5a9c09b9b2c102e262a77eebf38bd1c36fdab39f97285233be")
Blake3PowLocalGenesisHash = common.HexToHash("0xecbfee9f6bce9583520d16795bc9850783a8a86563c0ce9a5082d86f497b728f")
Blake3PowLocalGenesisHash = common.HexToHash("0xdb2e0d01d953a3df18eb42c26cf8caeb58a905474ffe391bc21354ead6e2e0b3")
Blake3PowLighthouseGenesisHash = common.HexToHash("0xf5263c69f46cb25c5c82a6e52cbd7b8c504a453ca8a7b44b581e5b1f2d14df9f")
)

Expand Down
4 changes: 2 additions & 2 deletions quai/gasprice/feehistory.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
return
}

sorter := make(sortGasAndReward, len(bf.block.QuaiTransactionsWithoutCoinbase()))
for i, tx := range bf.block.QuaiTransactionsWithoutCoinbase() {
sorter := make(sortGasAndReward, len(bf.block.TransactionsWithReceipts()))
for i, tx := range bf.block.TransactionsWithReceipts() {
reward, _ := tx.EffectiveGasTip(bf.block.BaseFee())
sorter[i] = txGasAndReward{gasUsed: bf.receipts[i].GasUsed, reward: reward}
}
Expand Down
Loading