Skip to content

Commit

Permalink
feat(counter-based ccc): add keccak (#1015)
Browse files Browse the repository at this point in the history
Co-authored-by: Ömer Faruk Irmak <[email protected]>
Co-authored-by: colin <[email protected]>
  • Loading branch information
3 people authored Aug 30, 2024
1 parent 90489b7 commit 268814c
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 23 deletions.
1 change: 1 addition & 0 deletions accounts/abi/bind/backends/simulated.go
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,7 @@ func (m callMsg) Value() *big.Int { return m.CallMsg.Value }
func (m callMsg) Data() []byte { return m.CallMsg.Data }
func (m callMsg) AccessList() types.AccessList { return m.CallMsg.AccessList }
func (m callMsg) IsL1MessageTx() bool { return false }
func (m callMsg) TxSize() common.StorageSize { return 0 }

// filterBackend implements filters.Backend to support filtering for logs without
// taking bloom-bits acceleration structures into account.
Expand Down
1 change: 1 addition & 0 deletions core/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func NewEVMTxContext(msg Message) vm.TxContext {
To: msg.To(),
GasPrice: new(big.Int).Set(msg.GasPrice()),
IsL1MessageTx: msg.IsL1MessageTx(),
TxSize: msg.TxSize(),
}
}

Expand Down
1 change: 1 addition & 0 deletions core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ type Message interface {
Data() []byte
AccessList() types.AccessList
IsL1MessageTx() bool
TxSize() common.StorageSize
}

// ExecutionResult includes all output after executing given evm
Expand Down
27 changes: 15 additions & 12 deletions core/types/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,7 @@ type Message struct {
accessList AccessList
isFake bool
isL1MessageTx bool
txSize common.StorageSize
}

func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice, gasFeeCap, gasTipCap *big.Int, data []byte, accessList AccessList, isFake bool) Message {
Expand Down Expand Up @@ -785,6 +786,7 @@ func (tx *Transaction) AsMessage(s Signer, baseFee *big.Int) (Message, error) {
accessList: tx.AccessList(),
isFake: false,
isL1MessageTx: tx.IsL1MessageTx(),
txSize: tx.Size(),
}
// If baseFee provided, set gasPrice to effectiveGasPrice.
if baseFee != nil {
Expand All @@ -795,18 +797,19 @@ func (tx *Transaction) AsMessage(s Signer, baseFee *big.Int) (Message, error) {
return msg, err
}

func (m Message) From() common.Address { return m.from }
func (m Message) To() *common.Address { return m.to }
func (m Message) GasPrice() *big.Int { return m.gasPrice }
func (m Message) GasFeeCap() *big.Int { return m.gasFeeCap }
func (m Message) GasTipCap() *big.Int { return m.gasTipCap }
func (m Message) Value() *big.Int { return m.amount }
func (m Message) Gas() uint64 { return m.gasLimit }
func (m Message) Nonce() uint64 { return m.nonce }
func (m Message) Data() []byte { return m.data }
func (m Message) AccessList() AccessList { return m.accessList }
func (m Message) IsFake() bool { return m.isFake }
func (m Message) IsL1MessageTx() bool { return m.isL1MessageTx }
func (m Message) From() common.Address { return m.from }
func (m Message) To() *common.Address { return m.to }
func (m Message) GasPrice() *big.Int { return m.gasPrice }
func (m Message) GasFeeCap() *big.Int { return m.gasFeeCap }
func (m Message) GasTipCap() *big.Int { return m.gasTipCap }
func (m Message) Value() *big.Int { return m.amount }
func (m Message) Gas() uint64 { return m.gasLimit }
func (m Message) Nonce() uint64 { return m.nonce }
func (m Message) Data() []byte { return m.data }
func (m Message) AccessList() AccessList { return m.accessList }
func (m Message) IsFake() bool { return m.isFake }
func (m Message) IsL1MessageTx() bool { return m.isL1MessageTx }
func (m Message) TxSize() common.StorageSize { return m.txSize }

// copyAddressPtr copies an address.
func copyAddressPtr(a *common.Address) *common.Address {
Expand Down
9 changes: 5 additions & 4 deletions core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,11 @@ type BlockContext struct {
// All fields can change between transactions.
type TxContext struct {
// Message information
Origin common.Address // Provides information for ORIGIN
To *common.Address // Provides information for trace
IsL1MessageTx bool // Provides information for trace
GasPrice *big.Int // Provides information for GASPRICE
Origin common.Address // Provides information for ORIGIN
To *common.Address // Provides information for trace
IsL1MessageTx bool // Provides information for trace
TxSize common.StorageSize // Provides information for trace
GasPrice *big.Int // Provides information for GASPRICE
}

// EVM is the Ethereum Virtual Machine base object and provides
Expand Down
36 changes: 29 additions & 7 deletions rollup/ccc/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ import (
)

const (
sigCountMax = 127
ecAddCountMax = 50
ecMulCountMax = 50
ecPairingCountMax = 2
rowUsageMax = 1_000_000
sigCountMax = 127
ecAddCountMax = 50
ecMulCountMax = 50
ecPairingCountMax = 2
rowUsageMax = 1_000_000
keccakRounds = 24
keccakRowsPerRound = 12
keccakRowsPerChunk = (keccakRounds + 1) * keccakRowsPerRound
)

var _ vm.EVMLogger = (*Logger)(nil)
Expand All @@ -37,7 +40,6 @@ var _ vm.EVMLogger = (*Logger)(nil)
// tx: row usage depends on the length of raw txns and the number of storage
// slots and/or accounts accessed. With the current gas limit of 10M, it is not possible
// to overflow the circuit.
// keccak: coming soon
type Logger struct {
currentEnv *vm.EVM
isCreate bool
Expand All @@ -54,11 +56,16 @@ type Logger struct {
sha256Usage uint64
expUsage uint64
modExpUsage uint64
keccakUsage uint64

l2TxnsRlpSize uint64
}

func NewLogger() *Logger {
const miscKeccakUsage = 50_000 // heuristically selected safe number to account for Rust side implementation details
return &Logger{
codesAccessed: make(map[common.Hash]bool),
keccakUsage: miscKeccakUsage,
}
}

Expand Down Expand Up @@ -89,6 +96,11 @@ func (l *Logger) logRawBytecode(code []byte) {
l.logBytecodeAccess(crypto.Keccak256Hash(code), uint64(len(code)))
}

// computeKeccakRows computes the number of rows used in keccak256 for the given bytes array length
func computeKeccakRows(length uint64) uint64 {
return ((length + 135) / 136) * keccakRowsPerChunk
}

// logPrecompileAccess checks if the invoked address is a precompile and increments
// resource usage of associated subcircuit
func (l *Logger) logPrecompileAccess(to common.Address, inputLen uint64, inputFn func(int64, int64) []byte) {
Expand All @@ -97,6 +109,7 @@ func (l *Logger) logPrecompileAccess(to common.Address, inputLen uint64, inputFn
switch to {
case common.BytesToAddress([]byte{1}): // &ecrecover{},
l.sigCount++
l.keccakUsage += computeKeccakRows(64)
outputLen = 32
case common.BytesToAddress([]byte{2}): // &sha256hash{},
l.logSha256(inputLen)
Expand Down Expand Up @@ -156,7 +169,10 @@ func (l *Logger) CaptureStart(env *vm.EVM, from common.Address, to common.Addres

if !env.TxContext.IsL1MessageTx {
l.sigCount++
l.l2TxnsRlpSize += uint64(env.TxContext.TxSize)
}
l.keccakUsage += computeKeccakRows(uint64(env.TxContext.TxSize))
l.keccakUsage += computeKeccakRows(64) // ecrecover per txn
}

func (l *Logger) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
Expand All @@ -182,7 +198,10 @@ func (l *Logger) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *
l.logCopy(scope.Stack.Back(3).Uint64())
case vm.CALLDATACOPY, vm.RETURNDATACOPY, vm.CODECOPY, vm.MCOPY, vm.CREATE, vm.CREATE2:
l.logCopy(scope.Stack.Back(2).Uint64())
case vm.LOG0, vm.LOG1, vm.LOG2, vm.LOG3, vm.LOG4, vm.SHA3, vm.RETURN, vm.REVERT:
case vm.SHA3:
l.keccakUsage += computeKeccakRows(scope.Stack.Back(1).Uint64())
l.logCopy(scope.Stack.Back(1).Uint64())
case vm.LOG0, vm.LOG1, vm.LOG2, vm.LOG3, vm.LOG4, vm.RETURN, vm.REVERT:
l.logCopy(scope.Stack.Back(1).Uint64())
case vm.DELEGATECALL, vm.STATICCALL:
inputOffset := int64(scope.Stack.Back(2).Uint64())
Expand Down Expand Up @@ -274,6 +293,9 @@ func (l *Logger) RowConsumption() types.RowConsumption {
}, {
Name: "mod_exp",
RowNumber: l.modExpUsage,
}, {
Name: "keccak",
RowNumber: l.keccakUsage + computeKeccakRows(l.l2TxnsRlpSize),
},
}
}
Expand Down

0 comments on commit 268814c

Please sign in to comment.