Skip to content

Commit

Permalink
Quai->Qi conversions have receipts and return an error when conversio…
Browse files Browse the repository at this point in the history
…n gas is too low
  • Loading branch information
jdowning100 committed Dec 16, 2024
1 parent 8060835 commit 34a2705
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 12 deletions.
26 changes: 25 additions & 1 deletion core/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ func (p *StateProcessor) Process(block *types.WorkObject, batch ethdb.Batch) (ty
value := etx.Value()
txGas := etx.Gas()
if txGas < params.TxGas {
continue
return nil, nil, nil, nil, 0, 0, 0, nil, nil, fmt.Errorf("etx gas is less than the minimum gas required")
}
txGas -= params.TxGas
if err := gp.SubGas(params.TxGas); err != nil {
Expand All @@ -587,15 +587,19 @@ func (p *StateProcessor) Process(block *types.WorkObject, batch ethdb.Batch) (ty
totalEtxGas += params.TxGas
denominations := misc.FindMinDenominations(value)
outputIndex := uint16(0)
total := big.NewInt(0)
success := true
// 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 := uint64(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
success = false
break
}
txGas -= params.CallValueTransferGas
Expand All @@ -612,9 +616,29 @@ func (p *StateProcessor) Process(block *types.WorkObject, batch ethdb.Batch) (ty
utxosCreatedDeleted.UtxosCreatedHashes = append(utxosCreatedDeleted.UtxosCreatedHashes, types.UTXOHash(etx.Hash(), outputIndex, utxo))
utxosCreatedDeleted.UtxosCreatedKeys = append(utxosCreatedDeleted.UtxosCreatedKeys, rawdb.UtxoKeyWithDenomination(etx.Hash(), outputIndex, utxo.Denomination))
p.logger.Debugf("Converting Quai to Qi %032x with denomination %d index %d lock %d\n", tx.Hash(), denomination, outputIndex, lock)
total.Add(total, types.Denominations[uint8(denomination)])
outputIndex++
}
}
if success {
receipt = &types.Receipt{Type: tx.Type(), Status: types.ReceiptStatusSuccessful, GasUsed: etx.Gas() - txGas, TxHash: tx.Hash(),
Logs: []*types.Log{{
Address: *etx.To(),
Topics: []common.Hash{types.QuaiToQiConversionTopic},
Data: total.Bytes(),
}},
}
} else {
receipt = &types.Receipt{Type: tx.Type(), Status: types.ReceiptStatusFailed, GasUsed: etx.Gas(), TxHash: tx.Hash(),
Logs: []*types.Log{{
Address: *etx.To(),
Topics: []common.Hash{types.QuaiToQiConversionTopic},
Data: total.Bytes(),
}},
}
}
receipts = append(receipts, receipt)
allLogs = append(allLogs, receipt.Logs...)
} else if !types.IsCoinBaseTx(tx) && !etx.ETXSender().Location().Equal(*etx.To().Location()) && etx.To().IsInQiLedgerScope() { // Regular Qi ETX
utxo := types.NewUtxoEntry(types.NewTxOut(uint8(etx.Value().Uint64()), etx.To().Bytes(), big.NewInt(0)))
// There are no more checks to be made as the ETX is worked so add it to the set
Expand Down
14 changes: 14 additions & 0 deletions core/types/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -1307,3 +1307,17 @@ func IsConversionTx(tx *Transaction) bool {
}
return tx.EtxType() == ConversionType
}

func IsQiToQuaiConversionTx(tx *Transaction) bool {
if tx.Type() == ExternalTxType && tx.EtxType() == ConversionType && tx.To().IsInQuaiLedgerScope() {
return true
}
return false
}

func IsQuaiToQiConversionTx(tx *Transaction) bool {
if tx.Type() == ExternalTxType && tx.EtxType() == ConversionType && tx.To().IsInQiLedgerScope() {
return true
}
return false
}
9 changes: 6 additions & 3 deletions core/types/utxo.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ const (
MaxTrimDenomination = 5
)

var MaxQi = new(big.Int).Mul(big.NewInt(math.MaxInt64), big.NewInt(params.Ether)) // This is just a default; determine correct value later
var (
MaxQi = new(big.Int).Mul(big.NewInt(math.MaxInt64), big.NewInt(params.Ether)) // This is just a default; determine correct value later
QuaiToQiConversionTopic = crypto.Keccak256Hash([]byte("QuaiToQiConversion"))
)

// Denominations is a map of denomination to number of Qi
var Denominations map[uint8]*big.Int
Expand Down Expand Up @@ -49,8 +52,8 @@ func init() {
TrimDepths = make(map[uint8]uint64)
TrimDepths[0] = params.GoldenAgeForkNumberV2 + 720 // 2 hours after fork starts from block 1
TrimDepths[1] = params.GoldenAgeForkNumberV2 + 720 // 2 hours
TrimDepths[2] = params.GoldenAgeForkNumberV2 + 1080 // 3 hours
TrimDepths[3] = params.GoldenAgeForkNumberV2 + 1080 // 3 hours
TrimDepths[2] = params.GoldenAgeForkNumberV2 + 1080 // 3 hours
TrimDepths[3] = params.GoldenAgeForkNumberV2 + 1080 // 3 hours
TrimDepths[4] = params.GoldenAgeForkNumberV2 + 2160 // 6 hours
TrimDepths[5] = params.GoldenAgeForkNumberV2 + 4320 // 12 hours
}
Expand Down
2 changes: 1 addition & 1 deletion core/types/wo.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ func (wo *WorkObject) TransactionsWithReceipts() []*Transaction {
// ignore the coinbase tx
continue
}
if !IsConversionTx(t) && (t.Type() == QuaiTxType || (t.Type() == ExternalTxType && t.To().IsInQuaiLedgerScope())) {
if t.Type() == QuaiTxType || (t.Type() == ExternalTxType && t.Type() != ConversionType && t.To().IsInQuaiLedgerScope()) || IsQuaiToQiConversionTx(t) {
txs = append(txs, t)
}
}
Expand Down
24 changes: 24 additions & 0 deletions core/vm/instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,7 @@ func opETX(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte
addr, value, etxGasLimit, gasTipCap, gasFeeCap, inOffset, inSize, accessListOffset, accessListSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
toAddr := common.Bytes20ToAddress(addr.Bytes20(), interpreter.evm.chainConfig.Location)
// Verify address is not in context
// This means that a conversion cannot happen with opETX
if common.IsInChainScope(toAddr.Bytes(), interpreter.evm.chainConfig.Location) {
temp.Clear()
stack.push(&temp)
Expand All @@ -911,6 +912,21 @@ func opETX(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte
return nil, nil
}

if etxGasLimit.CmpUint64(math.MaxUint64) == 1 {
temp.Clear()
stack.push(&temp)
fmt.Printf("%x opETX error: gas limit %d is greater than maximum %d\n", scope.Contract.self.Address(), etxGasLimit, math.MaxInt64)
return nil, nil
}

// Overflow not a problem here as overflow guarantees a number larger than txgas
if etxGasLimit.Uint64() < params.TxGas {
temp.Clear()
stack.push(&temp)
fmt.Printf("%x opETX error: gas limit %d is less than minimum %d\n", scope.Contract.self.Address(), etxGasLimit, params.TxGas)
return nil, nil
}

interpreter.evm.StateDB.SubBalance(internalSender, total.ToBig())

// Get the arguments from the memory.
Expand Down Expand Up @@ -1004,6 +1020,14 @@ func opConvert(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]
return nil, nil
}

// Overflow not a problem here as overflow guarantees a number larger than txgas
if etxGasLimit.Uint64() < params.TxGas {
temp.Clear()
stack.push(&temp)
fmt.Printf("%x opETX error: gas limit %d is less than minimum %d\n", scope.Contract.self.Address(), etxGasLimit, params.TxGas)
return nil, nil
}

interpreter.evm.StateDB.SubBalance(internalSender, total.ToBig())

interpreter.evm.ETXCacheLock.RLock()
Expand Down
40 changes: 33 additions & 7 deletions core/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -1241,8 +1241,7 @@ func (w *worker) commitTransaction(env *environment, parent *types.WorkObject, t
}
}
if txGas < params.TxGas {
// No gas, the result is a no-op but the tx is still valid
return nil, false, nil
return nil, false, fmt.Errorf("insufficient gas for Qi->Quai conversion")
}
txGas -= params.TxGas
if err := env.gasPool.SubGas(params.TxGas); err != nil {
Expand All @@ -1251,7 +1250,8 @@ func (w *worker) commitTransaction(env *environment, parent *types.WorkObject, t
gasUsed += params.TxGas
denominations := misc.FindMinDenominations(tx.Value())
outputIndex := uint16(0)

total := big.NewInt(0)
success := true
// Iterate over the denominations in descending order
for denomination := types.MaxDenomination; denomination >= 0; denomination-- {
// If the denomination count is zero, skip it
Expand All @@ -1261,6 +1261,7 @@ func (w *worker) commitTransaction(env *environment, parent *types.WorkObject, t
for j := uint64(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
success = false
break
}
txGas -= params.CallValueTransferGas
Expand All @@ -1271,9 +1272,32 @@ func (w *worker) commitTransaction(env *environment, parent *types.WorkObject, t
// the ETX hash is guaranteed to be unique
utxoHash := types.UTXOHash(tx.Hash(), outputIndex, types.NewUtxoEntry(types.NewTxOut(uint8(denomination), tx.To().Bytes(), lock)))
env.utxosCreate = append(env.utxosCreate, utxoHash)
total.Add(total, types.Denominations[uint8(denomination)])
outputIndex++
}
}
var receipt *types.Receipt
if success {
receipt = &types.Receipt{Type: tx.Type(), Status: types.ReceiptStatusSuccessful, GasUsed: tx.Gas() - txGas, TxHash: tx.Hash(),
Logs: []*types.Log{{
Address: *tx.To(),
Topics: []common.Hash{types.QuaiToQiConversionTopic},
Data: total.Bytes(),
}},
}
} else {
receipt = &types.Receipt{Type: tx.Type(), Status: types.ReceiptStatusFailed, GasUsed: tx.Gas(), TxHash: tx.Hash(),
Logs: []*types.Log{{
Address: *tx.To(),
Topics: []common.Hash{types.QuaiToQiConversionTopic},
Data: total.Bytes(),
}},
}
}
env.wo.Header().SetGasUsed(gasUsed)
env.txs = append(env.txs, tx)
env.gasUsedAfterTransaction = append(env.gasUsedAfterTransaction, gasUsed)
return receipt.Logs, true, nil
} else {
// This Qi ETX should cost more gas
if err := env.gasPool.SubGas(params.CallValueTransferGas); err != nil {
Expand All @@ -1282,11 +1306,13 @@ func (w *worker) commitTransaction(env *environment, parent *types.WorkObject, t
utxoHash := types.UTXOHash(tx.OriginatingTxHash(), tx.ETXIndex(), types.NewUtxoEntry(types.NewTxOut(uint8(tx.Value().Uint64()), tx.To().Bytes(), common.Big0)))
env.utxosCreate = append(env.utxosCreate, utxoHash)
gasUsed += params.CallValueTransferGas

env.wo.Header().SetGasUsed(gasUsed)
env.txs = append(env.txs, tx)
env.gasUsedAfterTransaction = append(env.gasUsedAfterTransaction, gasUsed)
return []*types.Log{}, false, nil
}
env.wo.Header().SetGasUsed(gasUsed)
env.txs = append(env.txs, tx)
env.gasUsedAfterTransaction = append(env.gasUsedAfterTransaction, gasUsed)
return []*types.Log{}, false, nil

} else if tx.Type() == types.ExternalTxType && types.IsConversionTx(tx) && tx.To().IsInQuaiLedgerScope() { // Qi->Quai Conversion
gasUsed := env.wo.GasUsed() + params.QiToQuaiConversionGas
env.wo.Header().SetGasUsed(gasUsed)
Expand Down

0 comments on commit 34a2705

Please sign in to comment.