From 7fa33285b9728ccb0ef3915c61185155ad2535bd Mon Sep 17 00:00:00 2001 From: deadlium Date: Fri, 22 Dec 2023 17:41:09 +0530 Subject: [PATCH] Add settlement module with batch add and verify functions - Implemented the settlement module in the sequencer. - This module introduces 'add batch' and 'verify batch' functionalities. - Enhances the sequencer's efficiency in handling batch operations. Co-authored-by: Uddesh Jaiswal Co-authored-by: Rahul Singh Maraskole Co-authored-by: Shubham Sharma Co-authored-by: Kritarth Agrawal Co-authored-by: Shobhit Sharma --- .DS_Store | Bin 6148 -> 6148 bytes README.md | 91 ++++++++++++++ common/constants.go | 7 +- common/functions.go | 2 +- config/chainInfo.json | 15 +++ go.mod | 2 +- handlers/batchCreator.go | 29 +++-- handlers/blockCheck.go | 4 +- handlers/blocks.go | 6 +- handlers/daCall.go | 10 +- handlers/settlement-client/addBatch.go | 95 ++++++++++++++ .../settlement-client/addExecutionLayer.go | 118 ++++++++++++++++++ handlers/settlement-client/verify.go | 113 +++++++++++++++++ handlers/txns.go | 6 +- main.go | 21 +++- prover/proverFunctions.go | 57 +++++---- scripts/test.sh | 2 +- types/leveDBStruct.go | 5 + types/prooverStruct.go | 6 +- types/settlementStructs.go | 105 ++++++++++++++++ 20 files changed, 636 insertions(+), 58 deletions(-) create mode 100644 config/chainInfo.json create mode 100644 handlers/settlement-client/addBatch.go create mode 100644 handlers/settlement-client/addExecutionLayer.go create mode 100644 handlers/settlement-client/verify.go create mode 100644 types/settlementStructs.go diff --git a/.DS_Store b/.DS_Store index 84cadc6d85a8c6d67085636588e78f0d54960941..98fc9f1d3b2aab0d41e8edf1804111f69b6cda15 100644 GIT binary patch delta 85 zcmZoMXfc@JFDl5uz`)4BAi&_6lb@WFlb;0S3v3qTSk9~ol44=dV@PMnWGF$F2I}Yr W%FX)^1`G_Fc~~wpZ)WHC%MSo8-xizz delta 48 zcmZoMXfc@JFDk&mz`)4B0HiV*(i!p?@)?R4Qa1~7EN5mE*lfabnR#M^#%6Yozx)93 CQwvc5 diff --git a/README.md b/README.md index e69de29..95c63c4 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,91 @@ +![Project Logo](https://www.airchains.io/assets/logos/airchains-svm-rollup-full-logo.png) + +# Overview + +The SVM Chain Sequencer is a groundbreaking, high-performance tool developed to enhance transaction and block management on Smart Virtual Machine (SVM) chains. This innovative tool is distinguished by its integration of cutting-edge technologies and processes, tailored specifically for SVM chains, to ensure streamlined, efficient, and reliable blockchain operations. + +## Table of Contents + +- [Overview](#overview) + - [Table of Contents](#table-of-contents) + - [Key Features](#key-features) + - [Usage](#usage) + - [Script Files Overview](#script-files-overview) + - [License](#license) + - [Acknowledgments](#acknowledgments) + +## Key Features + +- **Optimized Transaction Processing**: Utilizes advanced algorithms to effectively manage and process transactions, significantly increasing throughput and reducing latency in SVM chain environments. + +- **Sophisticated Block Management**: The sequencer is equipped with refined block management capabilities, ensuring smooth and efficient block generation and propagation within the SVM ecosystem. + +- **Data Integrity and Availability**: Integrates robust Data Availability (DA) processes, vital for maintaining the integrity and accessibility of data on the chain. This feature enhances the trustworthiness and transparency of the SVM network. + +- **Custom Batching Techniques**: Features bespoke batching techniques that are specifically designed for SVM chains, optimizing the handling of transaction loads and enhancing overall network performance. + +- **Seamless Integration with SVM Layer**: Designed to seamlessly integrate with the SVM layer, the sequencer maintains consistent performance and compatibility, reinforcing the strength and stability of SVM-based applications. + +- **High Scalability and Flexibility**: Built to accommodate the growing demands of SVM chains, offering scalable solutions that adapt to varying transaction volumes and network conditions. + +- **Reliability and Security**: Prioritizes reliability and security in its design, ensuring that the SVM Chain Sequencer operates with high resilience and robustness, safeguarding against potential threats and vulnerabilities. + +## Usage + +In order to tailor the Sequencer to better align with your specific requirements, please proceed to update key configuration parameters within the `common/constants.go` file. The following constants are crucial for the optimal functioning of the sequencer and can be adjusted to meet your operational needs: + +- **BatchSize**: Modify this value to alter the batch size for transaction processing. This adjustment can optimize throughput and efficiency based on your workload. + +- **BlockDelay**: Adjust this constant to set the delay between blocks check, aligning it with your network's block generation rate for synchronized operations. + +- **ExecutionClientRPC**: Update this URL to connect the sequencer with your preferred execution client's RPC interface. + +- **SettlementClientRPC**: Change this URL to integrate the sequencer with the desired settlement layer's RPC service. + +- **KeyringDirectory**: Specify a new directory path for the keyring, ensuring secure and organized storage of cryptographic keys. + +- **DaClientRPC**: Alter this URL to link the sequencer with your chosen Data Availability (DA) service's RPC endpoint. + +Each of these parameters plays a critical role in the configuration and performance of the sequencer. It is recommended to carefully consider the implications of these changes to maintain optimal functionality and security of the system. + +## Script Files Overview + +This repository includes a set of four essential script files designed to facilitate various operational aspects of the node. Each script has a specific purpose, detailed below: + +- **init.sh**: This script is responsible for setting up the initial environment. It creates all necessary folders and files required for the node's operation. + +``` + sh scripts/init.sh +``` + +- **start.sh**: Designed to simply start the node without altering its current state or block height. Ideal for routine starts where no changes to the environment are needed. + +``` + sh scripts/start.sh +``` + +- **restart.sh**: Used for refreshing the node's environment. It first deletes and then recreates all folders and files, followed by restarting the node to apply these changes. + +``` + sh scripts/restart.sh +``` + +- **test.sh**: As the name suggests, this script is used for testing purposes. It contains commands and procedures specifically intended for testing the node's functionalities and performance. + +``` + sh scripts/test.sh +``` + +> Note: before proceeding to run the sequencer, please ensure that the `init.sh` script has been executed to initialize the basic directory structure and configuration files. + +_Important Security Notice Regarding init.sh Execution_ + +Please be aware that running the `init.sh` script necessitates the entry of your terminal password. This requirement stems from the inclusion of `sudo` commands within the script. These commands elevate privileges for certain operations, which are essential for the correct setup and configuration of the environment. + +## License + +This project is licensed under the MIT License - see the LICENSE file for details. + +## Acknowledgments + +Special thanks to the `gnark` library, an efficient and elegant toolkit for zk-SNARKs on Go. This library has been instrumental in our development process. For more information and to explore their work, visit their GitHub repository at [Consensys/gnark.](https://github.com/Consensys/gnark) diff --git a/common/constants.go b/common/constants.go index 0159bf2..8270258 100644 --- a/common/constants.go +++ b/common/constants.go @@ -3,9 +3,6 @@ package common const BatchSize = 25 const BlockDelay = 5 -// ExecutionClientRPC const ExecutionClientRPC = "http://192.168.1.24:8545/" const ExecutionClientRPC = "http://127.0.0.1:8899/" - -// const ExecutionClientRPC = "http://192.168.1.70:8899/" -// const DaClientRPC = "http://192.168.1.105:5050/celestia" -const DaClientRPC = "http://192.168.1.105:5050/celestia" +const DaClientRPC = "http://192.168.1.106:5050/celestia" +const SettlementClientRPC = "http://192.168.1.105:8080" diff --git a/common/functions.go b/common/functions.go index eb913f4..494034f 100644 --- a/common/functions.go +++ b/common/functions.go @@ -4,7 +4,7 @@ import ( "bytes" "encoding/json" "fmt" - "github.com/airchains-network/solana-seq-indexer/common/logs" + "github.com/airchains-network/svm-sequencer-node/common/logs" "github.com/btcsuite/btcutil/base58" "math/big" "net/http" diff --git a/config/chainInfo.json b/config/chainInfo.json new file mode 100644 index 0000000..df12007 --- /dev/null +++ b/config/chainInfo.json @@ -0,0 +1,15 @@ +{ + "chainInfo": { + "chainID": "aircosmic_2605-1107", + "key": "AccountName", + "moniker": "ChainName" + }, + "daInfo": { + "daSelected": "Celestia", + "daWalletAddress": "0xaddress", + "daWalletKeypair": "0xaddress" + }, + "sequencerInfo": { + "sequencerType": "Air Sequencer" + } +} \ No newline at end of file diff --git a/go.mod b/go.mod index ce30027..0949875 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/airchains-network/solana-seq-indexer +module github.com/airchains-network/svm-sequencer-node go 1.21 diff --git a/handlers/batchCreator.go b/handlers/batchCreator.go index 3346c8f..cd077dd 100644 --- a/handlers/batchCreator.go +++ b/handlers/batchCreator.go @@ -3,10 +3,11 @@ package handlers import ( "encoding/json" "fmt" - "github.com/airchains-network/solana-seq-indexer/common" - "github.com/airchains-network/solana-seq-indexer/common/logs" - "github.com/airchains-network/solana-seq-indexer/prover" - "github.com/airchains-network/solana-seq-indexer/types" + "github.com/airchains-network/svm-sequencer-node/common" + "github.com/airchains-network/svm-sequencer-node/common/logs" + settlement_client "github.com/airchains-network/svm-sequencer-node/handlers/settlement-client" + "github.com/airchains-network/svm-sequencer-node/prover" + "github.com/airchains-network/svm-sequencer-node/types" "github.com/syndtr/goleveldb/leveldb" "os" "strconv" @@ -83,20 +84,34 @@ func BatchGeneration(wg *sync.WaitGroup, lds *leveldb.DB, ldt *leveldb.DB, ldbat batch.AccountNonces = AccountNonces // add prover here - _, currentStateHash, pkErr := prover.GenerateProof(batch, limitInt+1) + witnessVector, currentStatusHash, proofByte, pkErr := prover.GenerateProof(batch, limitInt+1) if pkErr != nil { logs.LogMessage("ERROR:", fmt.Sprintf("Error in generating proof : %s", pkErr.Error())) os.Exit(0) } // !adding Da client here - daKeyHash, err := DaCall(batch.TransactionHash, currentStateHash, limitInt+1, ldDA) + daKeyHash, err := DaCall(batch.TransactionHash, currentStatusHash, limitInt+1, ldDA) if err != nil { logs.LogMessage("ERROR:", fmt.Sprintf("Error in adding Da client : %s", err.Error())) - os.Exit(0) + logs.LogMessage("INFO:", "Waiting for 3 seconds") + time.Sleep(3 * time.Second) + BatchGeneration(wg, lds, ldt, ldbatch, ldDA, []byte(strconv.Itoa(common.BatchSize*(limitInt+1)))) } logs.LogMessage("SUCCESS:", fmt.Sprintf("Successfully added Da client for Batch %s in the latest phase", daKeyHash)) + addBatchRes := settlement_client.AddBatch(witnessVector, limitInt+1, lds) + if addBatchRes == "nil" { + logs.LogMessage("ERROR:", fmt.Sprintf("Error in adding batch to settlement client : %s", addBatchRes)) + os.Exit(0) + } + + status := settlement_client.VerifyBatch(limitInt+1, proofByte, ldDA, lds) + if !status { + logs.LogMessage("ERROR:", fmt.Sprintf("Error in verifying batch to settlement client : %s", status)) + os.Exit(0) + } + logs.LogMessage("SUCCESS:", fmt.Sprintf("Successfully generated proof for Batch %s in the latest phase", strconv.Itoa(limitInt+1))) batchJSON, err := json.Marshal(batch) diff --git a/handlers/blockCheck.go b/handlers/blockCheck.go index 34ab092..b808d38 100644 --- a/handlers/blockCheck.go +++ b/handlers/blockCheck.go @@ -5,8 +5,8 @@ import ( "bytes" "encoding/json" "fmt" - "github.com/airchains-network/solana-seq-indexer/common" - "github.com/airchains-network/solana-seq-indexer/common/logs" + "github.com/airchains-network/svm-sequencer-node/common" + "github.com/airchains-network/svm-sequencer-node/common/logs" "github.com/syndtr/goleveldb/leveldb" "log" "net/http" diff --git a/handlers/blocks.go b/handlers/blocks.go index 28dead3..c7703a6 100644 --- a/handlers/blocks.go +++ b/handlers/blocks.go @@ -4,9 +4,9 @@ import ( "bytes" "encoding/json" "fmt" - "github.com/airchains-network/solana-seq-indexer/common" - "github.com/airchains-network/solana-seq-indexer/common/logs" - "github.com/airchains-network/solana-seq-indexer/types" + "github.com/airchains-network/svm-sequencer-node/common" + "github.com/airchains-network/svm-sequencer-node/common/logs" + "github.com/airchains-network/svm-sequencer-node/types" "github.com/syndtr/goleveldb/leveldb" "net/http" "os" diff --git a/handlers/daCall.go b/handlers/daCall.go index 10a17b9..b2e398f 100644 --- a/handlers/daCall.go +++ b/handlers/daCall.go @@ -4,10 +4,10 @@ import ( "bytes" "encoding/json" "fmt" - air "github.com/airchains-network/solana-seq-indexer/airdb/air-leveldb" - "github.com/airchains-network/solana-seq-indexer/common" - "github.com/airchains-network/solana-seq-indexer/common/logs" - "github.com/airchains-network/solana-seq-indexer/types" + air "github.com/airchains-network/svm-sequencer-node/airdb/air-leveldb" + "github.com/airchains-network/svm-sequencer-node/common" + "github.com/airchains-network/svm-sequencer-node/common/logs" + "github.com/airchains-network/svm-sequencer-node/types" "github.com/syndtr/goleveldb/leveldb" "net/http" "strconv" @@ -95,7 +95,7 @@ func DaCall(transactions []string, currentStateHash string, batchNumber int, ldd DAKey: response.DaKeyHash, DAClientName: "celestia", BatchNumber: strconv.Itoa(batchNumber), - PreviousStateHash: daDecode.PreviousStateHash, + PreviousStateHash: daDecode.CurrentStateHash, CurrentStateHash: currentStateHash, } diff --git a/handlers/settlement-client/addBatch.go b/handlers/settlement-client/addBatch.go new file mode 100644 index 0000000..812567e --- /dev/null +++ b/handlers/settlement-client/addBatch.go @@ -0,0 +1,95 @@ +package settlement_client + +import ( + "bytes" + "encoding/json" + "fmt" + "github.com/airchains-network/svm-sequencer-node/common" + "github.com/airchains-network/svm-sequencer-node/common/logs" + "github.com/airchains-network/svm-sequencer-node/types" + "github.com/syndtr/goleveldb/leveldb" + "io" + "net/http" + "time" +) + +type PostAddBatchStruct struct { + ChainID string `json:"chain_id"` + BatchNumber uint64 `json:"batch_number"` + Witness []byte `json:"witness"` +} + +func AddBatch(witnessVector any, batchNumber int, lds *leveldb.DB) string { + + logs.LogMessage("INFO:", "Submitting batch to settlement") + + settlementChainInfoByte, err := lds.Get([]byte("settlementChainInfo"), nil) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error in getting settlementChainInfo from static db : %s", err.Error())) + return "nil" + } + + var settlementChainInfo types.SettlementLayerChainInfoStruct + err = json.Unmarshal(settlementChainInfoByte, &settlementChainInfo) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error in unmarshalling settlementChainInfo : %s", err.Error())) + return "nil" + } + chainID := settlementChainInfo.ChainId + + //var frVector fr.Vector + + wvByte, _ := json.Marshal(witnessVector) + + postAddBatchStruct := PostAddBatchStruct{ + ChainID: chainID, + BatchNumber: uint64(batchNumber), + Witness: wvByte, + } + + jsonData, err := json.Marshal(postAddBatchStruct) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error in marshalling postAddBatchStruct : %s", err.Error())) + return "nil" + } + rpcUrl := fmt.Sprintf("%s/add_batch", common.SettlementClientRPC) + req, err := http.NewRequest("POST", rpcUrl, bytes.NewBuffer(jsonData)) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error creating request:", err)) + return "nil" + } + + req.Header.Set("Content-Type", "application/json") + logs.LogMessage("INFO:", "Sending request to settlement client") + // Send the request + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error sending request:", err)) + return "nil" + } + defer resp.Body.Close() + + // Read and unmarshal the response + body, err := io.ReadAll(resp.Body) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error reading response:", err)) + return "nil" + } + + var response types.SettlementClientResponseStruct + err = json.Unmarshal(body, &response) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error unmarshalling response:", err)) + return "nil" + } + + if !response.Status { + logs.LogMessage("ERROR:", "error in adding batch to settlement") + logs.LogMessage("INFO:", "Retrying in 5 seconds...") + time.Sleep(5 * time.Second) + AddBatch(witnessVector, batchNumber, lds) + } + + return response.Data +} diff --git a/handlers/settlement-client/addExecutionLayer.go b/handlers/settlement-client/addExecutionLayer.go new file mode 100644 index 0000000..9c30936 --- /dev/null +++ b/handlers/settlement-client/addExecutionLayer.go @@ -0,0 +1,118 @@ +package settlement_client + +import ( + "bytes" + "encoding/json" + "fmt" + air "github.com/airchains-network/svm-sequencer-node/airdb/air-leveldb" + "github.com/airchains-network/svm-sequencer-node/common" + "github.com/airchains-network/svm-sequencer-node/common/logs" + "github.com/airchains-network/svm-sequencer-node/types" + "io" + "net/http" + "os" + "time" +) + +type PostAddExecutionLayerStruct struct { + VerificationKey string `json:"verification_key"` + ChainInfo string `json:"chain_info"` +} + +func AddExecutionLayer() string { + + logs.LogMessage("INFO:", "Adding execution layer") + + if _, err := os.Stat("verificationKey.json"); os.IsNotExist(err) { + logs.LogMessage("INFO:", "Waiting for verificationKey.json file") + time.Sleep(5 * time.Second) + AddExecutionLayer() + } + + verificationKeyContents, err := os.ReadFile("verificationKey.json") + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error reading verificationKey.json file : %s", err.Error())) + return "nil" + } + + verificationKeyContentsAsString := string(verificationKeyContents) + + chainInfoFile, err := os.ReadFile("config/chainInfo.json") + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error reading chainInfo.json file : %s", err.Error())) + os.Exit(0) + } + + var chainInfo types.ChainInfoStruct + + err = json.Unmarshal(chainInfoFile, &chainInfo) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error unmarshalling chainInfo.json file : %s", err.Error())) + os.Exit(0) + } + + chainInfoAsString, err := json.Marshal(chainInfo.ChainInfo) + + postAddExecutionLayerStruct := PostAddExecutionLayerStruct{ + VerificationKey: verificationKeyContentsAsString, + ChainInfo: string(chainInfoAsString), + } + + jsonData, err := json.Marshal(postAddExecutionLayerStruct) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error marshalling postAddExecutionLayerStruct : %s", err.Error())) + return "nil" + } + rpcUrl := fmt.Sprintf("%s/addexelayer", common.SettlementClientRPC) + req, err := http.NewRequest("POST", rpcUrl, bytes.NewBuffer(jsonData)) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error creating request:", err)) + return "nil" + } + + req.Header.Set("Content-Type", "application/json") + + // Send the request + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error sending request:", err)) + return "nil" + } + defer resp.Body.Close() + + // Read and unmarshal the response + body, err := io.ReadAll(resp.Body) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error reading response:", err)) + return "nil" + } + + var response types.SettlementClientResponseStruct + err = json.Unmarshal(body, &response) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error unmarshalling response:", err)) + return "nil" + } + + if response.Data != "nil" && response.Data != "exist" { + var settlementChainInfo = types.SettlementLayerChainInfoStruct{ + ChainId: response.Data, + ChainName: chainInfo.ChainInfo.Moniker, + } + + settlementChainInfoBytes, err := json.Marshal(settlementChainInfo) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error marshalling settlementChainInfo : %s", err.Error())) + return "nil" + } + + err = air.GetStaticDbInstance().Put([]byte("settlementChainInfo"), settlementChainInfoBytes, nil) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error in putting settlementChainInfo in static db : %s", err.Error())) + return "nil" + } + } + + return response.Data +} diff --git a/handlers/settlement-client/verify.go b/handlers/settlement-client/verify.go new file mode 100644 index 0000000..c929e8e --- /dev/null +++ b/handlers/settlement-client/verify.go @@ -0,0 +1,113 @@ +package settlement_client + +import ( + "bytes" + "encoding/json" + "fmt" + "github.com/airchains-network/svm-sequencer-node/common" + "github.com/airchains-network/svm-sequencer-node/common/logs" + "github.com/airchains-network/svm-sequencer-node/types" + "github.com/syndtr/goleveldb/leveldb" + "io" + "net/http" + "time" +) + +type VerifyBatchPostStruct struct { + BatchNumber uint64 `json:"batch_number"` + ChainID string `json:"chain_id"` + MerkleRootHash string `json:"merkle_root_hash"` + PrevMerkleRoot string `json:"prev_merkle_root"` + ZkProof []byte `json:"zk_proof"` +} + +func VerifyBatch(batchNumber int, proofByte []byte, ldda *leveldb.DB, lds *leveldb.DB) bool { + logs.LogMessage("INFO:", "Verifying the batch ") + settlementChainInfoByte, err := lds.Get([]byte("settlementChainInfo"), nil) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error in getting settlementChainInfo from static db : %s", err.Error())) + return false + } + + var settlementChainInfo types.SettlementLayerChainInfoStruct + err = json.Unmarshal(settlementChainInfoByte, &settlementChainInfo) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error in unmarshalling settlementChainInfo : %s", err.Error())) + return false + } + chainID := settlementChainInfo.ChainId + + batchKey := fmt.Sprintf("batch_%d", batchNumber) + batchDetailsByte, err := ldda.Get([]byte(batchKey), nil) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error in getting batch from db : %s", err.Error())) + return false + } + + var batchDetails types.DAStruct + err = json.Unmarshal(batchDetailsByte, &batchDetails) + if err != nil { + return false + } + + postVerifyBatchStruct := VerifyBatchPostStruct{ + BatchNumber: uint64(batchNumber), + ChainID: chainID, + MerkleRootHash: batchDetails.CurrentStateHash, + PrevMerkleRoot: batchDetails.PreviousStateHash, + ZkProof: proofByte, + } + + jsonData, err := json.Marshal(postVerifyBatchStruct) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error in marshalling postVerifyBatchStruct : %s", err.Error())) + return false + } + + rpcUrl := fmt.Sprintf("%s/verify_batch", common.SettlementClientRPC) + + req, err := http.NewRequest("POST", rpcUrl, bytes.NewBuffer(jsonData)) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error creating request:", err)) + return false + } + + req.Header.Set("Content-Type", "application/json") + + logs.LogMessage("INFO:", "Calling Settlement For Verifying Batch") + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error sending request:", err)) + return false + } + + defer func(Body io.ReadCloser) { + err := Body.Close() + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error closing response body:", err)) + } + }(resp.Body) + + body, err := io.ReadAll(resp.Body) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error reading response:", err)) + return false + } + + var response types.SettlementClientResponseStruct + err = json.Unmarshal(body, &response) + if err != nil { + logs.LogMessage("ERROR:", fmt.Sprintf("Error unmarshalling response:", err)) + return false + } + + if !response.Status { + logs.LogMessage("ERROR:", fmt.Sprintf("Error in verifying batch : %s", response.Description)) + logs.LogMessage("ERROR:", fmt.Sprintf("Trying again... in 5 seconds")) + time.Sleep(5 * time.Second) + VerifyBatch(batchNumber, proofByte, ldda, lds) + } + + return response.Status +} diff --git a/handlers/txns.go b/handlers/txns.go index f9d9b63..6c33557 100644 --- a/handlers/txns.go +++ b/handlers/txns.go @@ -5,9 +5,9 @@ import ( "bytes" "encoding/json" "fmt" - "github.com/airchains-network/solana-seq-indexer/common" - "github.com/airchains-network/solana-seq-indexer/common/logs" - "github.com/airchains-network/solana-seq-indexer/types" + "github.com/airchains-network/svm-sequencer-node/common" + "github.com/airchains-network/svm-sequencer-node/common/logs" + "github.com/airchains-network/svm-sequencer-node/types" "github.com/syndtr/goleveldb/leveldb" "net/http" "os" diff --git a/main.go b/main.go index 898a656..772479f 100644 --- a/main.go +++ b/main.go @@ -3,13 +3,15 @@ package main import ( "encoding/json" "fmt" - air "github.com/airchains-network/solana-seq-indexer/airdb/air-leveldb" - "github.com/airchains-network/solana-seq-indexer/common/logs" - "github.com/airchains-network/solana-seq-indexer/handlers" - "github.com/airchains-network/solana-seq-indexer/prover" - "github.com/airchains-network/solana-seq-indexer/types" + air "github.com/airchains-network/svm-sequencer-node/airdb/air-leveldb" + "github.com/airchains-network/svm-sequencer-node/common/logs" + "github.com/airchains-network/svm-sequencer-node/handlers" + settlement_client "github.com/airchains-network/svm-sequencer-node/handlers/settlement-client" + "github.com/airchains-network/svm-sequencer-node/prover" + "github.com/airchains-network/svm-sequencer-node/types" "os" "sync" + "time" ) func main() { @@ -22,6 +24,15 @@ func main() { } prover.CreateVkPk() + chainId := settlement_client.AddExecutionLayer() + if chainId == "nil" { + logs.LogMessage("ERROR:", "Something went wrong while adding execution layer") + logs.LogMessage("INFO:", "Retrying in 5 seconds...") + time.Sleep(5 * time.Second) + chainId = settlement_client.AddExecutionLayer() + } else if chainId == "exist" { + logs.LogMessage("INFO:", "Chain already exist") + } ldt := air.GetTxDbInstance() ldb := air.GetBlockDbInstance() diff --git a/prover/proverFunctions.go b/prover/proverFunctions.go index ea14207..f074dd1 100644 --- a/prover/proverFunctions.go +++ b/prover/proverFunctions.go @@ -5,9 +5,9 @@ import ( "encoding/hex" "encoding/json" "fmt" - air "github.com/airchains-network/solana-seq-indexer/airdb/air-leveldb" - "github.com/airchains-network/solana-seq-indexer/common" - "github.com/airchains-network/solana-seq-indexer/types" + air "github.com/airchains-network/svm-sequencer-node/airdb/air-leveldb" + "github.com/airchains-network/svm-sequencer-node/common" + "github.com/airchains-network/svm-sequencer-node/types" "math/rand" "os" "time" @@ -38,7 +38,7 @@ type MyCircuit struct { } func getTransactionHash(tx types.GetTransactionStruct) string { - record := tx.To + tx.From + fmt.Sprintf("%f", tx.Amount) + fmt.Sprintf("%f", tx.FromBalances) + fmt.Sprintf("%f", tx.ToBalances) + record := tx.To + tx.From + tx.Amount + tx.FromBalances + tx.ToBalances + tx.TransactionHash h := sha256.New() h.Write([]byte(record)) return hex.EncodeToString(h.Sum(nil)) @@ -149,7 +149,6 @@ func (circuit *MyCircuit) Define(api frontend.API) error { } _ = GetMerkleRoot(api, leaves) - //api.Println("Merkle root : ", root) return nil } @@ -170,7 +169,7 @@ func GenerateVerificationKey() (groth16.ProvingKey, groth16.VerifyingKey, error) // GenerateProof generates a proof for the given input data // and returns the proof and the error // batchDbCount is the number of batches in the database and it will be passed as batchNum here -func GenerateProof(inputData types.BatchStruct, batchNum int) ([]byte, string, error) { +func GenerateProof(inputData types.BatchStruct, batchNum int) (any, string, []byte, error) { ccs := ComputeCCS() @@ -179,19 +178,20 @@ func GenerateProof(inputData types.BatchStruct, batchNum int) ([]byte, string, e transaction := types.GetTransactionStruct{ To: inputData.To[i], From: inputData.From[i], - Amount: 0, - FromBalances: 0, - ToBalances: 0, + Amount: inputData.Amounts[i], + FromBalances: inputData.SenderBalances[i], + ToBalances: inputData.ReceiverBalances[i], TransactionHash: inputData.TransactionHash[i], } transactions = append(transactions, transaction) } - currentStateHash := GetMerkleRootCheck(transactions) + currentStatusHash := GetMerkleRootCheck(transactions) if _, err := os.Stat("provingKey.txt"); os.IsNotExist(err) { fmt.Println("Proving key does not exist. Please run the command 'sequencer-sdk create-vk-pk' to generate the proving key") - return nil, "", err + return nil, "", nil, err + } pk, err := ReadProvingKeyFromFile("provingKey.txt") @@ -200,7 +200,8 @@ func GenerateProof(inputData types.BatchStruct, batchNum int) ([]byte, string, e if err != nil { fmt.Println("Error reading proving key:", err) - return nil, "", err + return nil, "", nil, err + } fmt.Println("STEP 5: Generating proof") @@ -210,7 +211,8 @@ func GenerateProof(inputData types.BatchStruct, batchNum int) ([]byte, string, e snarkField, err := twistededwards.GetSnarkField(tedwards.BLS12_381) if err != nil { fmt.Println("Error getting snark field") - return nil, "", err + return nil, "", nil, err + } var inputValueLength int @@ -235,7 +237,7 @@ func GenerateProof(inputData types.BatchStruct, batchNum int) ([]byte, string, e inputValueLength = fromLength } else { fmt.Println("Error: Input data is not correct") - return nil, "", fmt.Errorf("input data is not correct") + return nil, "", nil, fmt.Errorf("input data is not correct") } if inputValueLength < common.BatchSize { @@ -286,7 +288,8 @@ func GenerateProof(inputData types.BatchStruct, batchNum int) ([]byte, string, e signature, err := privateKey.Sign(msg, hFunc) if err != nil { fmt.Println("Error signing the message") - return nil, "", err + return nil, "", nil, err + } // Public key _publicKey := publicKey.Bytes() @@ -300,8 +303,12 @@ func GenerateProof(inputData types.BatchStruct, batchNum int) ([]byte, string, e witness, err := frontend.NewWitness(&inputs, ecc.BLS12_381.ScalarField()) if err != nil { fmt.Printf("Error creating a witness: %v\n", err) - return nil, "", err + return nil, "", nil, err + } + + witnessVector := witness.Vector() + publicWitness, _ := witness.Public() publicWitnessDb := air.GetPublicWitnessDbInstance() publicWitnessDbKey := fmt.Sprintf("public_witness_%d", batchNum) @@ -309,18 +316,21 @@ func GenerateProof(inputData types.BatchStruct, batchNum int) ([]byte, string, e publicWitnessDbValue, err := json.Marshal(publicWitness) if err != nil { fmt.Println("Error marshalling public witness:", err) - return nil, "", err + return nil, "", nil, err + } err = publicWitnessDb.Put([]byte(publicWitnessDbKey), publicWitnessDbValue, nil) if err != nil { fmt.Println("Error saving public witness:", err) - return nil, "", err + return nil, "", nil, err + } fmt.Println("STEP 8: Generating proof") proof, err := groth16.Prove(ccs, pk, witness) if err != nil { fmt.Printf("Error generating proof: %v\n", err) - return nil, "", err + return nil, "", nil, err + } proofDb := air.GetProofDbInstance() @@ -328,16 +338,19 @@ func GenerateProof(inputData types.BatchStruct, batchNum int) ([]byte, string, e proofDbValue, err := json.Marshal(proof) if err != nil { fmt.Println("Error marshalling proof:", err) - return nil, "", err + return nil, "", nil, err + } err = proofDb.Put([]byte(proofDbKey), proofDbValue, nil) if err != nil { fmt.Println("Error saving proof:", err) - return nil, "", err + return nil, "", nil, err + } fmt.Println("STEP 9: Generating proof") - return proofDbValue, currentStateHash, nil + return witnessVector, currentStatusHash, proofDbValue, nil + } func ReadProvingKeyFromFile(filename string) (groth16.ProvingKey, error) { diff --git a/scripts/test.sh b/scripts/test.sh index fe8bb54..b3c7916 100644 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -1,4 +1,4 @@ -rm -rf data/leveldb +sudo rm -rf data/leveldb mkdir -p data/leveldb/batches mkdir -p data/leveldb/blocks mkdir -p data/leveldb/proof diff --git a/types/leveDBStruct.go b/types/leveDBStruct.go index 9be10a6..a1bc03f 100644 --- a/types/leveDBStruct.go +++ b/types/leveDBStruct.go @@ -38,3 +38,8 @@ type DAStruct struct { PreviousStateHash string `json:"previous_state_hash"` CurrentStateHash string `json:"current_state_hash"` } + +type SettlementLayerChainInfoStruct struct { + ChainId string `json:"chain_id"` + ChainName string `json:"chain_name"` +} diff --git a/types/prooverStruct.go b/types/prooverStruct.go index 23e46e2..1cb535e 100644 --- a/types/prooverStruct.go +++ b/types/prooverStruct.go @@ -3,8 +3,8 @@ package types type GetTransactionStruct struct { To string From string - Amount float64 - FromBalances float64 - ToBalances float64 + Amount string + FromBalances string + ToBalances string TransactionHash string } diff --git a/types/settlementStructs.go b/types/settlementStructs.go new file mode 100644 index 0000000..31fb205 --- /dev/null +++ b/types/settlementStructs.go @@ -0,0 +1,105 @@ +package types + +type ChainInfoStruct struct { + ChainInfo struct { + ChainID string `json:"chainID"` // Chain ID of the chain which is taken from the user + Key string `json:"key"` // Name of the account + Moniker string `json:"moniker"` // Name of the chain + } `json:"chainInfo"` + DaInfo struct { + DaSelected string `json:"daSelected"` + DaWalletAddress string `json:"daWalletAddress"` + DaWalletKeypair string `json:"daWalletKeypair"` + } `json:"daInfo"` + SequencerInfo struct { + SequencerType string `json:"sequencerType"` + } `json:"sequencerInfo"` +} + +type SettlementClientResponseStruct struct { + Status bool `json:"status"` + Data string `json:"data"` + Description string `json:"description"` +} + +type SLVerificationKeyStruct struct { + G1 struct { + Alpha struct { + X string `json:"X"` + Y string `json:"Y"` + } `json:"Alpha"` + Beta struct { + X string `json:"X"` + Y string `json:"Y"` + } `json:"Beta"` + Delta struct { + X string `json:"X"` + Y string `json:"Y"` + } `json:"Delta"` + K []struct { + X string `json:"X"` + Y string `json:"Y"` + } `json:"K"` + } `json:"G1"` + G2 struct { + Beta struct { + X struct { + A0 string `json:"A0"` + A1 string `json:"A1"` + } `json:"X"` + Y struct { + A0 string `json:"A0"` + A1 string `json:"A1"` + } `json:"Y"` + } `json:"Beta"` + Delta struct { + X struct { + A0 string `json:"A0"` + A1 string `json:"A1"` + } `json:"X"` + Y struct { + A0 string `json:"A0"` + A1 string `json:"A1"` + } `json:"Y"` + } `json:"Delta"` + Gamma struct { + X struct { + A0 string `json:"A0"` + A1 string `json:"A1"` + } `json:"X"` + Y struct { + A0 string `json:"A0"` + A1 string `json:"A1"` + } `json:"Y"` + } `json:"Gamma"` + } `json:"G2"` + CommitmentKey struct { + } `json:"CommitmentKey"` + PublicAndCommitmentCommitted []any `json:"PublicAndCommitmentCommitted"` +} + +type SLProofStruct struct { + Ar struct { + X string `json:"X"` + Y string `json:"Y"` + } `json:"Ar"` + Krs struct { + X string `json:"X"` + Y string `json:"Y"` + } `json:"Krs"` + Bs struct { + X struct { + A0 string `json:"A0"` + A1 string `json:"A1"` + } `json:"X"` + Y struct { + A0 string `json:"A0"` + A1 string `json:"A1"` + } `json:"Y"` + } `json:"Bs"` + Commitments []any `json:"Commitments"` + CommitmentPok struct { + X int `json:"X"` + Y int `json:"Y"` + } `json:"CommitmentPok"` +}