diff --git a/zk/syncer/utils.go b/zk/syncer/utils.go index 6e26d0c1bf5..e616df9b5a0 100644 --- a/zk/syncer/utils.go +++ b/zk/syncer/utils.go @@ -11,26 +11,48 @@ import ( "github.com/ledgerwatch/erigon/zk/utils" ) +const ( + sequenceBatchesMethodName = "sequenceBatches" + sequenceBatchesValidiumMethodName = "validiumSequenceBatches" +) + func GetAccInputDataCalcFunction(l1InfoRoot common.Hash, decodedSequenceInteerface interface{}) (accInputHashCalcFn func(prevAccInputHash common.Hash, index int) *common.Hash, totalSequenceBatches int, err error) { switch decodedSequence := decodedSequenceInteerface.(type) { case *SequenceBatchesCalldataPreEtrog: accInputHashCalcFn = func(prevAccInputHash common.Hash, index int) *common.Hash { return utils.CalculatePreEtrogAccInputHash(prevAccInputHash, decodedSequence.Batches[index].Transactions, decodedSequence.Batches[index].GlobalExitRoot, decodedSequence.Batches[index].Timestamp, decodedSequence.L2Coinbase) } - return accInputHashCalcFn, len(decodedSequence.Batches), nil + totalSequenceBatches = len(decodedSequence.Batches) case *SequenceBatchesCalldataEtrog: accInputHashCalcFn = func(prevAccInputHash common.Hash, index int) *common.Hash { return utils.CalculateEtrogAccInputHash(prevAccInputHash, decodedSequence.Batches[index].Transactions, l1InfoRoot, decodedSequence.Batches[index].ForcedTimestamp, decodedSequence.L2Coinbase, decodedSequence.Batches[index].ForcedBlockHashL1) } - return accInputHashCalcFn, len(decodedSequence.Batches), nil + totalSequenceBatches = len(decodedSequence.Batches) case *SequenceBatchesCalldataElderberry: accInputHashCalcFn = func(prevAccInputHash common.Hash, index int) *common.Hash { return utils.CalculateEtrogAccInputHash(prevAccInputHash, decodedSequence.Batches[index].Transactions, l1InfoRoot, decodedSequence.MaxSequenceTimestamp, decodedSequence.L2Coinbase, decodedSequence.Batches[index].ForcedBlockHashL1) } - return accInputHashCalcFn, len(decodedSequence.Batches), nil + totalSequenceBatches = len(decodedSequence.Batches) + case *SequenceBatchesCalldataValidiumPreEtrog: + accInputHashCalcFn = func(prevAccInputHash common.Hash, index int) *common.Hash { + return utils.CalculatePreEtrogValidiumAccInputHash(prevAccInputHash, decodedSequence.Batches[index].TransactionsHash, decodedSequence.Batches[index].GlobalExitRoot, decodedSequence.Batches[index].Timestamp, decodedSequence.L2Coinbase) + } + totalSequenceBatches = len(decodedSequence.Batches) + case *SequenceBatchesCalldataValidiumEtrog: + accInputHashCalcFn = func(prevAccInputHash common.Hash, index int) *common.Hash { + return utils.CalculateEtrogValidiumAccInputHash(prevAccInputHash, decodedSequence.Batches[index].TransactionsHash, l1InfoRoot, decodedSequence.Batches[index].ForcedTimestamp, decodedSequence.L2Coinbase, decodedSequence.Batches[index].ForcedBlockHashL1) + } + totalSequenceBatches = len(decodedSequence.Batches) + case *SequenceBatchesCalldataValidiumElderberry: + accInputHashCalcFn = func(prevAccInputHash common.Hash, index int) *common.Hash { + return utils.CalculateEtrogValidiumAccInputHash(prevAccInputHash, decodedSequence.Batches[index].TransactionsHash, l1InfoRoot, decodedSequence.MaxSequenceTimestamp, decodedSequence.L2Coinbase, decodedSequence.Batches[index].ForcedBlockHashL1) + } + totalSequenceBatches = len(decodedSequence.Batches) default: return nil, 0, fmt.Errorf("unexpected type of decoded sequence calldata: %T", decodedSequenceInteerface) } + + return accInputHashCalcFn, totalSequenceBatches, nil } func DecodeSequenceBatchesCalldata(data []byte) (calldata interface{}, err error) { @@ -51,8 +73,8 @@ func DecodeSequenceBatchesCalldata(data []byte) (calldata interface{}, err error } //sanitycheck - if method.Name != "sequenceBatches" { - return nil, fmt.Errorf("method name is not sequenceBatches, got: %s", method.Name) + if method.Name != sequenceBatchesMethodName && method.Name != sequenceBatchesValidiumMethodName { + return nil, fmt.Errorf("method name is not expected, got: %s", method.Name) } unpackedCalldata := make(map[string]interface{}) @@ -62,11 +84,23 @@ func DecodeSequenceBatchesCalldata(data []byte) (calldata interface{}, err error switch methodSig { case contracts.SequenceBatchesPreEtrog: - return decodePreEtrogSequenceBatchesCallData(unpackedCalldata), nil + if method.Name == sequenceBatchesMethodName { + return decodePreEtrogSequenceBatchesCallData(unpackedCalldata), nil + } else { + return decodePreEtrogSequenceBatchesValidiumCallData(unpackedCalldata), nil + } case contracts.SequenceBatchesIdv5_0: - return decodeEtrogSequenceBatchesCallData(unpackedCalldata), nil + if method.Name == sequenceBatchesMethodName { + return decodeEtrogSequenceBatchesCallData(unpackedCalldata), nil + } else { + return decodeEtrogSequenceBatchesValidiumCallData(unpackedCalldata), nil + } case contracts.SequenceBatchesIdv6_6: - return decodeElderberryBatchesCallData(unpackedCalldata), nil + if method.Name == sequenceBatchesMethodName { + return decodeElderberryBatchesCallData(unpackedCalldata), nil + } else { + return decodeElderberryBatchesValidiumCallData(unpackedCalldata), nil + } default: return nil, fmt.Errorf("no decoder found for method signature: %s", methodSig) } @@ -113,6 +147,47 @@ func decodeElderberryBatchesCallData(unpackedCalldata map[string]interface{}) *S return calldata } +type SequencedBatchValidiumElderberry struct { + TransactionsHash common.Hash + ForcedGlobalExitRoot common.Hash + ForcedTimestamp uint64 + ForcedBlockHashL1 common.Hash +} + +type SequenceBatchesCalldataValidiumElderberry struct { + Batches []SequencedBatchValidiumElderberry + InitSequencedBatch uint64 + L2Coinbase common.Address + MaxSequenceTimestamp uint64 +} + +func decodeElderberryBatchesValidiumCallData(unpackedCalldata map[string]interface{}) *SequenceBatchesCalldataValidiumElderberry { + unpackedbatches := unpackedCalldata["batches"].([]struct { + TransactionsHash [32]uint8 `json:"transactionsHash"` + ForcedGlobalExitRoot [32]uint8 `json:"forcedGlobalExitRoot"` + ForcedTimestamp uint64 `json:"forcedTimestamp"` + ForcedBlockHashL1 [32]uint8 `json:"forcedBlockHashL1"` + }) + + calldata := &SequenceBatchesCalldataValidiumElderberry{ + Batches: make([]SequencedBatchValidiumElderberry, len(unpackedbatches)), + InitSequencedBatch: unpackedCalldata["initSequencedBatch"].(uint64), + L2Coinbase: unpackedCalldata["l2Coinbase"].(common.Address), + MaxSequenceTimestamp: unpackedCalldata["maxSequenceTimestamp"].(uint64), + } + + for i, batch := range unpackedbatches { + calldata.Batches[i] = SequencedBatchValidiumElderberry{ + TransactionsHash: common.BytesToHash(batch.TransactionsHash[:]), + ForcedGlobalExitRoot: common.BytesToHash(batch.ForcedGlobalExitRoot[:]), + ForcedTimestamp: batch.ForcedTimestamp, + ForcedBlockHashL1: common.BytesToHash(batch.ForcedBlockHashL1[:]), + } + } + + return calldata +} + type SequencedBatchEtrog struct { Transactions []uint8 ForcedGlobalExitRoot common.Hash @@ -150,6 +225,43 @@ func decodeEtrogSequenceBatchesCallData(unpackedCalldata map[string]interface{}) return calldata } +type SequencedBatchValidiumEtrog struct { + TransactionsHash common.Hash + ForcedGlobalExitRoot common.Hash + ForcedTimestamp uint64 + ForcedBlockHashL1 common.Hash +} + +type SequenceBatchesCalldataValidiumEtrog struct { + Batches []SequencedBatchValidiumEtrog + L2Coinbase common.Address +} + +func decodeEtrogSequenceBatchesValidiumCallData(unpackedCalldata map[string]interface{}) *SequenceBatchesCalldataValidiumEtrog { + unpackedbatches := unpackedCalldata["batches"].([]struct { + TransactionsHash [32]uint8 `json:"transactionsHash"` + ForcedGlobalExitRoot [32]uint8 `json:"forcedGlobalExitRoot"` + ForcedTimestamp uint64 `json:"forcedTimestamp"` + ForcedBlockHashL1 [32]uint8 `json:"forcedBlockHashL1"` + }) + + calldata := &SequenceBatchesCalldataValidiumEtrog{ + Batches: make([]SequencedBatchValidiumEtrog, len(unpackedbatches)), + L2Coinbase: unpackedCalldata["l2Coinbase"].(common.Address), + } + + for i, batch := range unpackedbatches { + calldata.Batches[i] = SequencedBatchValidiumEtrog{ + TransactionsHash: common.BytesToHash(batch.TransactionsHash[:]), + ForcedGlobalExitRoot: common.BytesToHash(batch.ForcedGlobalExitRoot[:]), + ForcedTimestamp: batch.ForcedTimestamp, + ForcedBlockHashL1: batch.ForcedBlockHashL1, + } + } + + return calldata +} + type SequencedBatchPreEtrog struct { Transactions []uint8 GlobalExitRoot common.Hash @@ -186,3 +298,40 @@ func decodePreEtrogSequenceBatchesCallData(unpackedCalldata map[string]interface return calldata } + +type SequencedBatchValidiumPreEtrog struct { + TransactionsHash common.Hash + GlobalExitRoot common.Hash + Timestamp uint64 + MinForcedTimestamp uint64 +} + +type SequenceBatchesCalldataValidiumPreEtrog struct { + Batches []SequencedBatchValidiumPreEtrog + L2Coinbase common.Address +} + +func decodePreEtrogSequenceBatchesValidiumCallData(unpackedCalldata map[string]interface{}) *SequenceBatchesCalldataValidiumPreEtrog { + unpackedbatches := unpackedCalldata["batches"].([]struct { + TransactionsHash [32]uint8 `json:"transactionsHash"` + GlobalExitRoot [32]uint8 `json:"globalExitRoot"` + Timestamp uint64 `json:"timestamp"` + MinForcedTimestamp uint64 `json:"minForcedTimestamp"` + }) + + calldata := &SequenceBatchesCalldataValidiumPreEtrog{ + Batches: make([]SequencedBatchValidiumPreEtrog, len(unpackedbatches)), + L2Coinbase: unpackedCalldata["l2Coinbase"].(common.Address), + } + + for i, batch := range unpackedbatches { + calldata.Batches[i] = SequencedBatchValidiumPreEtrog{ + TransactionsHash: common.BytesToHash(batch.TransactionsHash[:]), + GlobalExitRoot: common.BytesToHash(batch.GlobalExitRoot[:]), + Timestamp: batch.Timestamp, + MinForcedTimestamp: batch.MinForcedTimestamp, + } + } + + return calldata +} diff --git a/zk/utils/acc_input_hash.go b/zk/utils/acc_input_hash.go index d1087de7517..2a987015cdb 100644 --- a/zk/utils/acc_input_hash.go +++ b/zk/utils/acc_input_hash.go @@ -8,6 +8,27 @@ import ( "github.com/ledgerwatch/erigon/crypto" ) +// calculates the new accInputHash based on the old one and data frem one new batch +// this returns the accInputHash for the current batch +// oldAccInputHash - the accInputHash from the previous batch +func CalculateEtrogValidiumAccInputHash( + oldAccInputHash common.Hash, + batchTransactionData common.Hash, + l1InfoRoot common.Hash, + limitTimestamp uint64, + sequencerAddress common.Address, + forcedBlockHashL1 common.Hash, +) *common.Hash { + return calculateEtrogAccInputHash( + oldAccInputHash, + batchTransactionData.Bytes(), + l1InfoRoot, + limitTimestamp, + sequencerAddress, + forcedBlockHashL1, + ) +} + // calculates the new accInputHash based on the old one and data frem one new batch // this returns the accInputHash for the current batch // oldAccInputHash - the accInputHash from the previous batch @@ -19,9 +40,26 @@ func CalculateEtrogAccInputHash( sequencerAddress common.Address, forcedBlockHashL1 common.Hash, ) *common.Hash { - batchHashData := CalculateBatchHashData(batchTransactionData) + return calculateEtrogAccInputHash( + oldAccInputHash, + CalculateBatchHashData(batchTransactionData), + l1InfoRoot, + limitTimestamp, + sequencerAddress, + forcedBlockHashL1, + ) +} + +func calculateEtrogAccInputHash( + oldAccInputHash common.Hash, + batchDataHash []byte, + l1InfoRoot common.Hash, + limitTimestamp uint64, + sequencerAddress common.Address, + forcedBlockHashL1 common.Hash, +) *common.Hash { v1 := oldAccInputHash.Bytes() - v2 := batchHashData + v2 := batchDataHash v3 := l1InfoRoot.Bytes() v4 := big.NewInt(0).SetUint64(limitTimestamp).Bytes() v5 := sequencerAddress.Bytes() @@ -49,9 +87,22 @@ func CalculateEtrogAccInputHash( return &hash } -// calculates the new accInputHash based on the old one and data frem one new batch -// this returns the accInputHash for the current batch -// oldAccInputHash - the accInputHash from the previous batch +func CalculatePreEtrogValidiumAccInputHash( + oldAccInputHash common.Hash, + batchHashData common.Hash, + globalExitRoot common.Hash, + timestamp uint64, + sequencerAddress common.Address, +) *common.Hash { + return calculatePreEtrogAccInputHash( + oldAccInputHash, + batchHashData.Bytes(), + globalExitRoot, + timestamp, + sequencerAddress, + ) +} + func CalculatePreEtrogAccInputHash( oldAccInputHash common.Hash, batchTransactionData []byte, @@ -60,8 +111,27 @@ func CalculatePreEtrogAccInputHash( sequencerAddress common.Address, ) *common.Hash { batchHashData := CalculateBatchHashData(batchTransactionData) + return calculatePreEtrogAccInputHash( + oldAccInputHash, + batchHashData, + globalExitRoot, + timestamp, + sequencerAddress, + ) +} + +// calculates the new accInputHash based on the old one and data frem one new batch +// this returns the accInputHash for the current batch +// oldAccInputHash - the accInputHash from the previous batch +func calculatePreEtrogAccInputHash( + oldAccInputHash common.Hash, + batchTransactionHash []byte, + globalExitRoot common.Hash, + timestamp uint64, + sequencerAddress common.Address, +) *common.Hash { v1 := oldAccInputHash.Bytes() - v2 := batchHashData + v2 := batchTransactionHash v3 := globalExitRoot.Bytes() v4 := big.NewInt(0).SetUint64(timestamp).Bytes() v5 := sequencerAddress.Bytes()