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  }