github.com/0xPolygon/supernets2-node@v0.0.0-20230711153321-2fe574524eaa/test/e2e/datacommittee_test.go (about) 1 package e2e 2 3 import ( 4 "context" 5 "crypto/ecdsa" 6 "encoding/json" 7 "fmt" 8 "math/big" 9 "os" 10 "os/exec" 11 "sort" 12 "strconv" 13 "strings" 14 "testing" 15 "time" 16 17 "github.com/0xPolygon/supernets2-data-availability/config" 18 cTypes "github.com/0xPolygon/supernets2-node/config/types" 19 "github.com/0xPolygon/supernets2-node/db" 20 "github.com/0xPolygon/supernets2-node/etherman/smartcontracts/supernets2datacommittee" 21 "github.com/0xPolygon/supernets2-node/jsonrpc" 22 "github.com/0xPolygon/supernets2-node/log" 23 "github.com/0xPolygon/supernets2-node/test/operations" 24 "github.com/ethereum/go-ethereum" 25 eTypes "github.com/ethereum/go-ethereum/core/types" 26 27 "github.com/ethereum/go-ethereum/accounts/keystore" 28 "github.com/ethereum/go-ethereum/common" 29 "github.com/ethereum/go-ethereum/crypto" 30 "github.com/ethereum/go-ethereum/ethclient" 31 "github.com/stretchr/testify/assert" 32 "github.com/stretchr/testify/require" 33 ) 34 35 func TestDataCommittee(t *testing.T) { 36 const ( 37 nSignatures = 4 38 mMembers = 5 39 ksFile = "/tmp/pkey" 40 cfgFile = "/tmp/dacnodeconfigfile.json" 41 ksPass = "pass" 42 dacNodeContainer = "hermeznetwork/supernets2-data-availability:v0.0.1" 43 ) 44 45 // Setup 46 var err error 47 if testing.Short() { 48 t.Skip() 49 } 50 ctx := context.Background() 51 defer func() { 52 require.NoError(t, operations.Teardown()) 53 }() 54 err = operations.Teardown() 55 require.NoError(t, err) 56 opsCfg := operations.GetDefaultOperationsConfig() 57 opsCfg.State.MaxCumulativeGasUsed = 80000000000 58 opsman, err := operations.NewManager(ctx, opsCfg) 59 require.NoError(t, err) 60 defer func() { 61 require.NoError(t, opsman.StopDACDB()) 62 }() 63 err = opsman.Setup() 64 require.NoError(t, err) 65 require.NoError(t, opsman.StartDACDB()) 66 time.Sleep(5 * time.Second) 67 authL2, err := operations.GetAuth(operations.DefaultSequencerPrivateKey, operations.DefaultL2ChainID) 68 require.NoError(t, err) 69 authL1, err := operations.GetAuth(operations.DefaultSequencerPrivateKey, operations.DefaultL1ChainID) 70 require.NoError(t, err) 71 clientL2, err := ethclient.Dial(operations.DefaultL2NetworkURL) 72 require.NoError(t, err) 73 clientL1, err := ethclient.Dial(operations.DefaultL1NetworkURL) 74 require.NoError(t, err) 75 dacSC, err := supernets2datacommittee.NewSupernets2datacommittee( 76 common.HexToAddress(operations.DefaultL1DataCommitteeContract), 77 clientL1, 78 ) 79 require.NoError(t, err) 80 81 // Register committe with N / M signatures 82 membs := members{} 83 addrsBytes := []byte{} 84 urls := []string{} 85 for i := 0; i < mMembers; i++ { 86 pk, err := crypto.GenerateKey() 87 require.NoError(t, err) 88 membs = append(membs, member{ 89 addr: crypto.PubkeyToAddress(pk.PublicKey), 90 pk: pk, 91 url: fmt.Sprintf("http://supernets2-data-availability-%d:420%d", i, i), 92 i: i, 93 }) 94 } 95 sort.Sort(membs) 96 for _, m := range membs { 97 addrsBytes = append(addrsBytes, m.addr.Bytes()...) 98 urls = append(urls, m.url) 99 } 100 tx, err := dacSC.SetupCommittee(authL1, big.NewInt(nSignatures), urls, addrsBytes) 101 if err != nil { 102 for _, m := range membs { 103 fmt.Println(m.addr) 104 } 105 } 106 require.NoError(t, err) 107 err = operations.WaitTxToBeMined(ctx, clientL1, tx, operations.DefaultTimeoutTxToBeMined) 108 require.NoError(t, err) 109 110 // Spin up M DAC nodes 111 dacNodeConfig := config.Config{ 112 L1: config.L1Config{ 113 WsURL: "ws://supernets2-mock-l1-network:8546", 114 Contract: "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82", 115 Timeout: cTypes.NewDuration(time.Minute * 3), 116 RetryPeriod: cTypes.NewDuration(time.Second * 5), 117 }, 118 PrivateKey: cTypes.KeystoreFileConfig{ 119 Path: ksFile, 120 Password: ksPass, 121 }, 122 DB: db.Config{ 123 Name: "committee_db", 124 User: "committee_user", 125 Password: "committee_password", 126 Host: "supernets2-data-node-db", 127 Port: "5432", 128 EnableLog: false, 129 MaxConns: 10, 130 }, 131 RPC: jsonrpc.Config{ 132 Host: "0.0.0.0", 133 EnableL2SuggestedGasPricePolling: false, 134 MaxRequestsPerIPAndSecond: 100, 135 }, 136 } 137 defer func() { 138 // Remove tmp files 139 assert.NoError(t, 140 exec.Command("rm", cfgFile).Run(), 141 ) 142 assert.NoError(t, 143 exec.Command("rmdir", ksFile+"_").Run(), 144 ) 145 assert.NoError(t, 146 exec.Command("rm", ksFile).Run(), 147 ) 148 // Stop DAC nodes 149 for i := 0; i < mMembers; i++ { 150 assert.NoError(t, exec.Command( 151 "docker", "kill", "supernets2-data-availability-"+strconv.Itoa(i), 152 ).Run()) 153 assert.NoError(t, exec.Command( 154 "docker", "rm", "supernets2-data-availability-"+strconv.Itoa(i), 155 ).Run()) 156 } 157 // Stop permissionless node 158 require.NoError(t, opsman.StopPermissionlessNodeForcedToSYncThroughDAC()) 159 }() 160 // Start permissionless node 161 require.NoError(t, opsman.StartPermissionlessNodeForcedToSYncThroughDAC()) 162 // Star DAC nodes 163 for _, m := range membs { 164 // Set correct port 165 port := 4200 + m.i 166 dacNodeConfig.RPC.Port = port 167 // Write config file 168 file, err := json.MarshalIndent(dacNodeConfig, "", " ") 169 require.NoError(t, err) 170 err = os.WriteFile(cfgFile, file, 0644) 171 require.NoError(t, err) 172 // Write private key keystore file 173 require.NoError(t, createKeyStore(m.pk, ksFile, ksPass)) 174 // Run DAC node 175 cmd := exec.Command( 176 "docker", "run", "-d", 177 "--name", "supernets2-data-availability-"+strconv.Itoa(m.i), 178 "-v", cfgFile+":/app/config.json", 179 "-v", ksFile+":"+ksFile, 180 "--network", "supernets2", 181 dacNodeContainer, 182 "/bin/sh", "-c", 183 "/app/supernets2-data-availability run --cfg /app/config.json", 184 ) 185 out, err := cmd.CombinedOutput() 186 require.NoError(t, err, string(out)) 187 time.Sleep(time.Second * 5) 188 } 189 190 // Send txs 191 nTxs := 10 192 amount := big.NewInt(10000) 193 toAddress := common.HexToAddress("0x70997970C51812dc3A010C7d01b50e0d17dc79C8") 194 _, err = clientL2.BalanceAt(ctx, authL2.From, nil) 195 require.NoError(t, err) 196 _, err = clientL2.PendingNonceAt(ctx, authL2.From) 197 require.NoError(t, err) 198 199 gasLimit, err := clientL2.EstimateGas(ctx, ethereum.CallMsg{From: authL2.From, To: &toAddress, Value: amount}) 200 require.NoError(t, err) 201 202 gasPrice, err := clientL2.SuggestGasPrice(ctx) 203 require.NoError(t, err) 204 205 nonce, err := clientL2.PendingNonceAt(ctx, authL2.From) 206 require.NoError(t, err) 207 208 txs := make([]*eTypes.Transaction, 0, nTxs) 209 for i := 0; i < nTxs; i++ { 210 tx := eTypes.NewTransaction(nonce+uint64(i), toAddress, amount, gasLimit, gasPrice, nil) 211 log.Infof("generating tx %d / %d: %s", i+1, nTxs, tx.Hash().Hex()) 212 txs = append(txs, tx) 213 } 214 215 // Wait for verification 216 _, err = operations.ApplyL2Txs(ctx, txs, authL2, clientL2, operations.VerifiedConfirmationLevel) 217 require.NoError(t, err) 218 219 // Assert that he permissionless node is fully synced (through the DAC) 220 time.Sleep(30 * time.Second) // Give some time for the permissionless node to get synced 221 clientL2Permissionless, err := ethclient.Dial(operations.PermissionlessL2NetworkURL) 222 require.NoError(t, err) 223 expectedBlock, err := clientL2.BlockByNumber(ctx, nil) 224 require.NoError(t, err) 225 actualBlock, err := clientL2Permissionless.BlockByNumber(ctx, nil) 226 require.NoError(t, err) 227 // je, err := expectedBlock.Header().MarshalJSON() 228 // require.NoError(t, err) 229 // log.Info(string(je)) 230 // ja, err := actualBlock.Header().MarshalJSON() 231 // require.NoError(t, err) 232 // log.Info(string(ja)) 233 // require.Equal(t, string(je), string(ja)) 234 require.Equal(t, expectedBlock.Root().Hex(), actualBlock.Root().Hex()) 235 } 236 237 type member struct { 238 addr common.Address 239 pk *ecdsa.PrivateKey 240 url string 241 i int 242 } 243 type members []member 244 245 func (s members) Len() int { return len(s) } 246 func (s members) Less(i, j int) bool { 247 return strings.ToUpper(s[i].addr.Hex()) < strings.ToUpper(s[j].addr.Hex()) 248 } 249 func (s members) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 250 251 func createKeyStore(pk *ecdsa.PrivateKey, outputDir, password string) error { 252 ks := keystore.NewKeyStore(outputDir+"_", keystore.StandardScryptN, keystore.StandardScryptP) 253 _, err := ks.ImportECDSA(pk, password) 254 if err != nil { 255 return err 256 } 257 fileNameB, err := exec.Command("ls", outputDir+"_/").CombinedOutput() 258 fileName := strings.TrimSuffix(string(fileNameB), "\n") 259 if err != nil { 260 fmt.Println(fileName) 261 return err 262 } 263 out, err := exec.Command("mv", outputDir+"_/"+fileName, outputDir).CombinedOutput() 264 if err != nil { 265 fmt.Println(string(out)) 266 return err 267 } 268 return nil 269 }