github.com/0xPolygon/supernets2-node@v0.0.0-20230711153321-2fe574524eaa/tools/executor/main.go (about) 1 package main 2 3 import ( 4 "context" 5 "encoding/hex" 6 "encoding/json" 7 "os" 8 "os/exec" 9 "strings" 10 "time" 11 12 "github.com/0xPolygon/supernets2-node/db" 13 "github.com/0xPolygon/supernets2-node/log" 14 "github.com/0xPolygon/supernets2-node/state" 15 "github.com/0xPolygon/supernets2-node/state/runtime/executor" 16 "github.com/0xPolygon/supernets2-node/state/runtime/executor/pb" 17 "github.com/0xPolygon/supernets2-node/test/testutils" 18 ) 19 20 const ( 21 waitForDBSeconds = 3 22 vectorDir = "./vectors/" 23 genesisDir = "./genesis/" 24 executorURL = "localhost:50071" 25 ) 26 27 func main() { 28 // Start containers 29 defer func() { 30 cmd := exec.Command("docker-compose", "down", "--remove-orphans") 31 if err := cmd.Run(); err != nil { 32 log.Errorf("Failed stop containers: %v", err) 33 return 34 } 35 }() 36 log.Info("Starting DB and prover") 37 cmd := exec.Command("docker-compose", "up", "-d", "executor-tool-db") 38 if out, err := cmd.CombinedOutput(); err != nil { 39 log.Errorf("Failed to star DB: %w. %v", err, out) 40 return 41 } 42 time.Sleep(time.Second * waitForDBSeconds) 43 cmd = exec.Command("docker-compose", "up", "-d", "executor-tool-prover") 44 if out, err := cmd.CombinedOutput(); err != nil { 45 log.Errorf("Failed to star prover: %v. %v", err, out) 46 return 47 } 48 log.Info("DONE starting DB and prover") 49 50 // Load vector file names 51 files, err := os.ReadDir(vectorDir) 52 if err != nil { 53 log.Errorf("Error reading directory: %v", err) 54 return 55 } 56 for _, file := range files { 57 genesis, test, err := loadCase(vectorDir + file.Name()) 58 if err != nil { 59 log.Errorf("Failed loading case: %v", err) 60 return 61 } 62 if test.Skip { 63 log.Infof("Case %v skipped", test.Title) 64 continue 65 } 66 log.Infof("Running case %v\n", test.Title) 67 err = runTestCase(context.Background(), genesis, test) 68 if err != nil { 69 log.Errorf("Failed running case: %v", err) 70 return 71 } 72 log.Infof("Done running case %v\n\n\n\n\n", test.Title) 73 } 74 } 75 76 func runTestCase(ctx context.Context, genesis []genesisItem, tc testCase) error { 77 // DB connection 78 dbConfig := db.Config{ 79 User: testutils.GetEnv("PGUSER", "prover_user"), 80 Password: testutils.GetEnv("PGPASSWORD", "prover_pass"), 81 Name: testutils.GetEnv("PGDATABASE", "prover_db"), 82 Host: testutils.GetEnv("PGHOST", "localhost"), 83 Port: testutils.GetEnv("PGPORT", "5432"), 84 EnableLog: false, 85 MaxConns: 1, 86 } 87 sqlDB, err := db.NewSQLDB(dbConfig) 88 if err != nil { 89 return err 90 } 91 92 // Clean DB 93 _, err = sqlDB.Exec(context.Background(), "DELETE FROM state.merkletree") 94 if err != nil { 95 return err 96 } 97 98 // Insert genesis 99 for _, item := range genesis { 100 _, err = sqlDB.Exec( 101 context.Background(), 102 "INSERT INTO state.merkletree (hash, data) VALUES ($1, $2)", 103 item.Hash, item.Data, 104 ) 105 if err != nil { 106 return err 107 } 108 } 109 110 // Executor connection 111 xecutor, _, _ := executor.NewExecutorClient(ctx, executor.Config{URI: executorURL}) 112 // Execute batches 113 for i := 0; i < len(tc.Requests); i++ { 114 pbr := pb.ProcessBatchRequest(tc.Requests[i]) //nolint 115 res, err := xecutor.ProcessBatch(ctx, &pbr) 116 if err != nil { 117 return err 118 } 119 log.Infof("********** BATCH %d **********", tc.Requests[i].OldBatchNum) 120 txs, _, err := state.DecodeTxs(tc.Requests[i].BatchL2Data) 121 if err != nil { 122 log.Warnf("Txs are not correctly encoded") 123 } 124 lastTxWithResponse := 0 125 log.Infof("CumulativeGasUsed: %v", res.CumulativeGasUsed) 126 log.Infof("NewStateRoot: %v", hex.EncodeToString(res.NewStateRoot)) 127 log.Infof("NewLocalExitRoot: %v", hex.EncodeToString(res.NewLocalExitRoot)) 128 log.Infof("CntKeccakHashes: %v", res.CntKeccakHashes) 129 log.Infof("CntPoseidonHashes: %v", res.CntPoseidonHashes) 130 log.Infof("CntPoseidonPaddings: %v", res.CntPoseidonPaddings) 131 log.Infof("CntMemAligns: %v", res.CntMemAligns) 132 log.Infof("CntArithmetics: %v", res.CntArithmetics) 133 log.Infof("CntBinaries: %v", res.CntBinaries) 134 log.Infof("CntSteps: %v", res.CntSteps) 135 for i, txRes := range res.Responses { 136 log.Infof("=====> TX #%d", i) 137 if "0x"+hex.EncodeToString(txRes.TxHash) != txs[i].Hash().Hex() { 138 log.Warnf("TxHash missmatch:\nexecutor: %s\ndecoded: %s", "0x"+hex.EncodeToString(txRes.TxHash), txs[i].Hash().Hex()) 139 } else { 140 log.Infof("= TxHash: %v", txs[i].Hash().Hex()) 141 } 142 log.Infof("= Nonce: %d", txs[i].Nonce()) 143 log.Infof("= To: %v", txs[i].To()) 144 log.Infof("= Gas: %v", txs[i].Gas()) 145 log.Infof("= GasPrice: %v", txs[i].GasPrice()) 146 log.Infof("= StateRoot: %v", hex.EncodeToString(txRes.StateRoot)) 147 log.Infof("= Error: %v", txRes.Error) 148 log.Infof("= GasUsed: %v", txRes.GasUsed) 149 log.Infof("= GasLeft: %v", txRes.GasLeft) 150 log.Infof("= GasRefunded: %v", txRes.GasRefunded) 151 log.Infof("<======") 152 lastTxWithResponse = i + 1 153 } 154 if lastTxWithResponse != len(txs) { 155 log.Warnf("%d txs sent to the executor, but only got %d responses", len(txs), lastTxWithResponse) 156 log.Info("Txs without response:") 157 for i := lastTxWithResponse; i < len(txs); i++ { 158 log.Info("--------------------------------") 159 log.Infof("TxHash (decoded): %v", txs[i].Hash().Hex()) 160 log.Infof("Nonce: %d", txs[i].Nonce()) 161 log.Infof("To: %v", txs[i].To()) 162 log.Infof("Gas: %v", txs[i].Gas()) 163 log.Infof("GasPrice: %v", txs[i].GasPrice()) 164 log.Info("--------------------------------") 165 } 166 } 167 log.Info("*******************************************************") 168 } 169 return nil 170 } 171 172 func loadCase(vectorFileName string) ([]genesisItem, testCase, error) { 173 tc := testCase{} 174 gen := []genesisItem{} 175 // Load and parse test case 176 f, err := os.ReadFile(vectorFileName) 177 if err != nil { 178 return gen, tc, err 179 } 180 err = json.Unmarshal(f, &tc) 181 if err != nil { 182 return gen, tc, err 183 } 184 // Load and parse genesis 185 f, err = os.ReadFile(genesisDir + tc.GenesisFile) 186 if err != nil { 187 return gen, tc, err 188 } 189 err = json.Unmarshal(f, &gen) 190 if err != nil { 191 return gen, tc, err 192 } 193 return gen, tc, err 194 } 195 196 type genesisItem struct { 197 Hash []byte 198 Data []byte 199 } 200 201 func (gi *genesisItem) UnmarshalJSON(src []byte) error { 202 type jGenesis struct { 203 Hash string `json:"hash"` 204 Data string `json:"data"` 205 } 206 jg := jGenesis{} 207 if err := json.Unmarshal(src, &jg); err != nil { 208 return err 209 } 210 hash, err := hex.DecodeString(jg.Hash) 211 if err != nil { 212 return err 213 } 214 data, err := hex.DecodeString(jg.Data) 215 if err != nil { 216 return err 217 } 218 *gi = genesisItem{ 219 Hash: hash, 220 Data: data, 221 } 222 return nil 223 } 224 225 type testCase struct { 226 Title string `json:"title"` 227 GenesisFile string `json:"genesisFile"` 228 Skip bool `json:"skip"` 229 Requests []executorRequest `json:"batches"` 230 } 231 232 type executorRequest pb.ProcessBatchRequest 233 234 func (er *executorRequest) UnmarshalJSON(data []byte) error { 235 type jExecutorRequeststruct struct { 236 BatchL2Data string `json:"batchL2Data"` 237 GlobalExitRoot string `json:"globalExitRoot"` 238 OldBatchNum uint64 `json:"oldBatchNum"` 239 OldAccInputHash string `json:"oldAccInputHash"` 240 OldStateRoot string `json:"oldStateRoot"` 241 SequencerAddr string `json:"sequencerAddr"` 242 Timestamp uint64 `json:"timestamp"` 243 } 244 jer := jExecutorRequeststruct{} 245 if err := json.Unmarshal(data, &jer); err != nil { 246 return err 247 } 248 batchL2Data, err := hex.DecodeString(strings.TrimPrefix(jer.BatchL2Data, "0x")) 249 if err != nil { 250 return err 251 } 252 globalExitRoot, err := hex.DecodeString(strings.TrimPrefix(jer.GlobalExitRoot, "0x")) 253 if err != nil { 254 return err 255 } 256 oldAccInputHash, err := hex.DecodeString(strings.TrimPrefix(jer.OldAccInputHash, "0x")) 257 if err != nil { 258 return err 259 } 260 oldStateRoot, err := hex.DecodeString(strings.TrimPrefix(jer.OldStateRoot, "0x")) 261 if err != nil { 262 return err 263 } 264 265 req := pb.ProcessBatchRequest{ 266 BatchL2Data: batchL2Data, 267 GlobalExitRoot: globalExitRoot, 268 OldBatchNum: jer.OldBatchNum, 269 OldAccInputHash: oldAccInputHash, 270 OldStateRoot: oldStateRoot, 271 Coinbase: jer.SequencerAddr, 272 EthTimestamp: jer.Timestamp, 273 } 274 *er = executorRequest(req) //nolint 275 return nil 276 }