diff --git a/arbos/parse_l2_test.go b/arbos/parse_l2_test.go index 0c8134aeb5..a67b65b54b 100644 --- a/arbos/parse_l2_test.go +++ b/arbos/parse_l2_test.go @@ -21,7 +21,7 @@ func TestEspressoParsing(t *testing.T) { } var mockProof = json.RawMessage(`{"NonExistence":{"ns_id":0}}`) var mockChainConfig = &espressoTypes.ResolvableChainConfig{ - espressoTypes.EitherChainConfig{ + ChainConfig: espressoTypes.EitherChainConfig{ Left: &espressoTypes.ChainConfig{ChainId: *espressoTypes.NewU256().SetUint64(0x8a19), MaxBlockSize: 10240, BaseFee: *espressoTypes.NewU256().SetUint64(0)}, }, } diff --git a/system_tests/espresso_e2e_test.go b/system_tests/espresso_e2e_test.go index e2e4fcbdc9..4f77fd9c4f 100644 --- a/system_tests/espresso_e2e_test.go +++ b/system_tests/espresso_e2e_test.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "math/big" + "os" "os/exec" "strings" "testing" @@ -20,6 +21,7 @@ import ( "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbnode/dataposter/storage" "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/solgen/go/ospgen" "github.com/offchainlabs/nitro/solgen/go/rollupgen" "github.com/offchainlabs/nitro/solgen/go/upgrade_executorgen" "github.com/offchainlabs/nitro/staker" @@ -31,7 +33,7 @@ import ( var workingDir = "./espresso-e2e" var lightClientAddress = "0xb075b82c7a23e0994df4793422a1f03dbcf9136f" -// var hostIoAddress = "0xF34C2fac45527E55ED122f80a969e79A40547e6D" +var hostIoAddress = "0xF34C2fac45527E55ED122f80a969e79A40547e6D" var hotShotUrl = "http://127.0.0.1:50000" var ( @@ -452,113 +454,110 @@ func TestEspressoE2E(t *testing.T) { }) Require(t, err) - // TOOD: uncomment once we fix fraud proofs - // https://github.com/EspressoSystems/nitro-espresso-integration/issues/117 - - // hostIo, err := ospgen.NewOneStepProverHostIo(common.HexToAddress(hostIoAddress), builder.L1.Client) - // Require(t, err) - // actualCommitment, err := hostIo.GetHotShotCommitment(&bind.CallOpts{}, big.NewInt(1)) - // Require(t, err) - // commitmentBytes := actualCommitment.Bytes() - // if len(commitmentBytes) != 32 { - // t.Fatal("failed to read hotshot via hostio contract, length is not 32") - // } - // empty := actualCommitment.Cmp(big.NewInt(0)) == 0 - // if empty { - // t.Fatal("failed to read hotshot via hostio contract, empty") - // } - // log.Info("Read hotshot commitment via hostio contract successfully", "height", 1, "commitment", commitmentBytes) - - // incorrectHeight := uint64(10) - - // goodStaker, blockValidatorA, cleanA := createStaker(ctx, t, builder, 0) - // defer cleanA() - // badStaker, blockValidatorB, cleanB := createStaker(ctx, t, builder, incorrectHeight) - // defer cleanB() - - // err = waitForWith(t, ctx, 60*time.Second, 1*time.Second, func() bool { - // validatedA := blockValidatorA.Validated(t) - // validatedB := blockValidatorB.Validated(t) - // shouldValidated := arbutil.MessageIndex(incorrectHeight - 1) - // condition := validatedA >= shouldValidated && validatedB >= shouldValidated - // if !condition { - // log.Info("waiting for stakers to catch up the incorrect hotshot height", "stakerA", validatedA, "stakerB", validatedB, "target", shouldValidated) - // } - // return condition - // }) - // Require(t, err) - // validatorUtils, err := rollupgen.NewValidatorUtils(builder.L2.ConsensusNode.DeployInfo.ValidatorUtils, builder.L1.Client) - // Require(t, err) - // goodOpts := builder.L1Info.GetDefaultCallOpts("Staker1", ctx) - // badOpts := builder.L1Info.GetDefaultCallOpts("Staker2", ctx) - // i := 0 - // err = waitFor(t, ctx, func() bool { - // log.Info("good staker acts", "step", i) - // txA, err := goodStaker.Act(ctx) - // Require(t, err) - // if txA != nil { - // _, err = builder.L1.EnsureTxSucceeded(txA) - // Require(t, err) - // } - - // log.Info("bad staker acts", "step", i) - // txB, err := badStaker.Act(ctx) - // Require(t, err) - // if txB != nil { - // _, err = builder.L1.EnsureTxSucceeded(txB) - // Require(t, err) - // } - // i += 1 - // conflict, err := validatorUtils.FindStakerConflict(&bind.CallOpts{}, builder.L2.ConsensusNode.DeployInfo.Rollup, goodOpts.From, badOpts.From, big.NewInt(1024)) - // Require(t, err) - // condition := staker.ConflictType(conflict.Ty) == staker.CONFLICT_TYPE_FOUND - // if !condition { - // log.Info("waiting for the conflict") - // } - // return condition - // }) - // Require(t, err) - - // // The following tests are very time-consuming and, given that the related code - // // does not change often, it's not necessary to run them every time. - // // Note: If you are modifying the smart contracts, staker-related code or doing overhaul. - // // Set the E2E_CHECK_STAKER env variable to any non-empty string to run the check. - - // checkStaker := os.Getenv("E2E_CHECK_STAKER") - // if checkStaker == "" { - // return - // } - // err = waitForWith( - // t, - // ctx, - // time.Minute*20, - // time.Second*5, - // func() bool { - // log.Info("good staker acts", "step", i) - // txA, err := goodStaker.Act(ctx) - // Require(t, err) - // if txA != nil { - // _, err = builder.L1.EnsureTxSucceeded(txA) - // Require(t, err) - // } - - // log.Info("bad staker acts", "step", i) - // txB, err := badStaker.Act(ctx) - // if txB != nil { - // _, err = builder.L1.EnsureTxSucceeded(txB) - // Require(t, err) - // } - // if err != nil { - // ok := strings.Contains(err.Error(), "ERROR_HOTSHOT_COMMITMENT") - // if ok { - // return true - // } else { - // t.Fatal("unexpected err") - // } - // } - // i += 1 - // return false - - // }) - // Require(t, err) + hostIo, err := ospgen.NewOneStepProverHostIo(common.HexToAddress(hostIoAddress), builder.L1.Client) + Require(t, err) + actualCommitment, err := hostIo.GetHotShotCommitment(&bind.CallOpts{}, big.NewInt(1)) + Require(t, err) + commitmentBytes := actualCommitment.Bytes() + if len(commitmentBytes) != 32 { + t.Fatal("failed to read hotshot via hostio contract, length is not 32") + } + empty := actualCommitment.Cmp(big.NewInt(0)) == 0 + if empty { + t.Fatal("failed to read hotshot via hostio contract, empty") + } + log.Info("Read hotshot commitment via hostio contract successfully", "height", 1, "commitment", commitmentBytes) + + incorrectHeight := uint64(10) + + goodStaker, blockValidatorA, cleanA := createStaker(ctx, t, builder, 0) + defer cleanA() + badStaker, blockValidatorB, cleanB := createStaker(ctx, t, builder, incorrectHeight) + defer cleanB() + + err = waitForWith(t, ctx, 60*time.Second, 1*time.Second, func() bool { + validatedA := blockValidatorA.Validated(t) + validatedB := blockValidatorB.Validated(t) + shouldValidated := arbutil.MessageIndex(incorrectHeight - 1) + condition := validatedA >= shouldValidated && validatedB >= shouldValidated + if !condition { + log.Info("waiting for stakers to catch up the incorrect hotshot height", "stakerA", validatedA, "stakerB", validatedB, "target", shouldValidated) + } + return condition + }) + Require(t, err) + validatorUtils, err := rollupgen.NewValidatorUtils(builder.L2.ConsensusNode.DeployInfo.ValidatorUtils, builder.L1.Client) + Require(t, err) + goodOpts := builder.L1Info.GetDefaultCallOpts("Staker1", ctx) + badOpts := builder.L1Info.GetDefaultCallOpts("Staker2", ctx) + i := 0 + err = waitFor(t, ctx, func() bool { + log.Info("good staker acts", "step", i) + txA, err := goodStaker.Act(ctx) + Require(t, err) + if txA != nil { + _, err = builder.L1.EnsureTxSucceeded(txA) + Require(t, err) + } + + log.Info("bad staker acts", "step", i) + txB, err := badStaker.Act(ctx) + Require(t, err) + if txB != nil { + _, err = builder.L1.EnsureTxSucceeded(txB) + Require(t, err) + } + i += 1 + conflict, err := validatorUtils.FindStakerConflict(&bind.CallOpts{}, builder.L2.ConsensusNode.DeployInfo.Rollup, goodOpts.From, badOpts.From, big.NewInt(1024)) + Require(t, err) + condition := staker.ConflictType(conflict.Ty) == staker.CONFLICT_TYPE_FOUND + if !condition { + log.Info("waiting for the conflict") + } + return condition + }) + Require(t, err) + + // The following tests are very time-consuming and, given that the related code + // does not change often, it's not necessary to run them every time. + // Note: If you are modifying the smart contracts, staker-related code or doing overhaul. + // Set the E2E_CHECK_STAKER env variable to any non-empty string to run the check. + + checkStaker := os.Getenv("E2E_CHECK_STAKER") + if checkStaker == "" { + return + } + err = waitForWith( + t, + ctx, + time.Minute*20, + time.Second*5, + func() bool { + log.Info("good staker acts", "step", i) + txA, err := goodStaker.Act(ctx) + Require(t, err) + if txA != nil { + _, err = builder.L1.EnsureTxSucceeded(txA) + Require(t, err) + } + + log.Info("bad staker acts", "step", i) + txB, err := badStaker.Act(ctx) + if txB != nil { + _, err = builder.L1.EnsureTxSucceeded(txB) + Require(t, err) + } + if err != nil { + ok := strings.Contains(err.Error(), "ERROR_HOTSHOT_COMMITMENT") + if ok { + return true + } else { + t.Fatal("unexpected err") + } + } + i += 1 + return false + + }) + Require(t, err) }