Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test precompile methods related to stylus #2737

Merged
merged 4 commits into from
Oct 29, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions system_tests/program_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1242,6 +1242,134 @@ func testSdkStorage(t *testing.T, jit bool) {
check()
}

func TestStylusPrecompileMethodsSimple(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

builder := NewNodeBuilder(ctx).DefaultConfig(t, true)
cleanup := builder.Build(t)
defer cleanup()

arbOwner, err := pgen.NewArbOwner(types.ArbOwnerAddress, builder.L2.Client)
Require(t, err)
arbDebug, err := pgen.NewArbDebug(types.ArbDebugAddress, builder.L2.Client)
Require(t, err)
arbWasm, err := pgen.NewArbWasm(types.ArbWasmAddress, builder.L2.Client)
Require(t, err)

ensure := func(tx *types.Transaction, err error) *types.Receipt {
t.Helper()
Require(t, err)
receipt, err := EnsureTxSucceeded(ctx, builder.L2.Client, tx)
Require(t, err)
return receipt
}

ownerAuth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx)
ensure(arbDebug.BecomeChainOwner(&ownerAuth))

// ArbOwner precompile methods
testConst := uint16(10)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably going to sound paranoid, but I'd use different values for each different thing you want to test.

As an example, suppose there were a broken implementation of: SetInkPrice and SetWasmInitCostScalar
And actually, the broken implementation meant that whatever value gets passed to SetInkPrice actually sets the value for WasmInitCostScalar and vice versa. Your test would still pass, but there would be a serious bug in the behavior.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, specially considering that today there are different precompile functions, even from different precompiles, that have the same side effect.
Not sure if that is the case of the functions tested in this PR though, but it would be a good practice anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. Fixed it

ensure(arbOwner.SetInkPrice(&ownerAuth, uint32(testConst)))
ensure(arbOwner.SetWasmMaxStackDepth(&ownerAuth, uint32(testConst)))
ensure(arbOwner.SetWasmFreePages(&ownerAuth, testConst))
ensure(arbOwner.SetWasmPageGas(&ownerAuth, testConst))
ensure(arbOwner.SetWasmPageLimit(&ownerAuth, testConst))
// Setting low values of gas and cached parameters ensures when MinInitGas is called on ArbWasm precompile,
// the returned values would be programs.MinInitGasUnits and programs.MinCachedGasUnits
ensure(arbOwner.SetWasmMinInitGas(&ownerAuth, 1, 1))
ensure(arbOwner.SetWasmInitCostScalar(&ownerAuth, uint64(testConst)))
expectedExpiryDays := uint16(1)
ensure(arbOwner.SetWasmExpiryDays(&ownerAuth, expectedExpiryDays))
ensure(arbOwner.SetWasmKeepaliveDays(&ownerAuth, 0))
ensure(arbOwner.SetWasmBlockCacheSize(&ownerAuth, testConst))

// ArbWasm precompile methods
wasm, _ := readWasmFile(t, rustFile("keccak"))
codehash := crypto.Keccak256Hash(wasm)
programAddress := deployContract(t, ctx, ownerAuth, builder.L2.Client, wasm)

activateAuth := ownerAuth
activateAuth.Value = oneEth
ensure(arbWasm.ActivateProgram(&activateAuth, programAddress))

bcs, err := arbWasm.BlockCacheSize(nil)
diegoximenes marked this conversation as resolved.
Show resolved Hide resolved
Require(t, err)
if bcs != testConst {
t.Errorf("BlockCacheSize from arbWasm precompile didnt match the value set by arbowner. have: %d, want: %d", bcs, testConst)
}
ed, err := arbWasm.ExpiryDays(nil)
Require(t, err)
if ed != expectedExpiryDays {
t.Errorf("ExpiryDays from arbWasm precompile didnt match the value set by arbowner. have: %d, want: %d", ed, expectedExpiryDays)
}
fp, err := arbWasm.FreePages(nil)
Require(t, err)
if fp != testConst {
t.Errorf("FreePages from arbWasm precompile didnt match the value set by arbowner. have: %d, want: %d", fp, testConst)
}
ics, err := arbWasm.InitCostScalar(nil)
Require(t, err)
if ics != uint64(testConst) {
t.Errorf("InitCostScalar from arbWasm precompile didnt match the value set by arbowner. have: %d, want: %d", ics, testConst)
}
ip, err := arbWasm.InkPrice(nil)
Require(t, err)
if ip != uint32(testConst) {
t.Errorf("InkPrice from arbWasm precompile didnt match the value set by arbowner. have: %d, want: %d", ip, testConst)
}
kad, err := arbWasm.KeepaliveDays(nil)
Require(t, err)
if kad != 0 {
t.Errorf("KeepaliveDays from arbWasm precompile didnt match the value set by arbowner. have: %d, want: 0", kad)
}
msd, err := arbWasm.MaxStackDepth(nil)
Require(t, err)
if msd != uint32(testConst) {
t.Errorf("MaxStackDepth from arbWasm precompile didnt match the value set by arbowner. have: %d, want: %d", msd, testConst)
}
mig, err := arbWasm.MinInitGas(nil)
Require(t, err)
if mig.Gas != programs.MinInitGasUnits {
t.Errorf("MinInitGas from arbWasm precompile didnt match the Gas value set by arbowner. have: %d, want: %d", mig.Gas, programs.MinInitGasUnits)
}
if mig.Cached != programs.MinCachedGasUnits {
t.Errorf("MinInitGas from arbWasm precompile didnt match the Cached value set by arbowner. have: %d, want: %d", mig.Cached, programs.MinCachedGasUnits)
}
pg, err := arbWasm.PageGas(nil)
Require(t, err)
if pg != testConst {
t.Errorf("PageGas from arbWasm precompile didnt match the value set by arbowner. have: %d, want: %d", pg, testConst)
}
pl, err := arbWasm.PageLimit(nil)
Require(t, err)
if pl != testConst {
t.Errorf("PageLimit from arbWasm precompile didnt match the value set by arbowner. have: %d, want: %d", pl, testConst)
}
// pageramp currently is initialPageRamp = 620674314 value in programs package
_, err = arbWasm.PageRamp(nil)
Require(t, err)

cas, err := arbWasm.CodehashAsmSize(nil, codehash)
Require(t, err)
if cas == 0 {
t.Error("CodehashAsmSize from arbWasm precompile returned 0 value")
}
ptl, err := arbWasm.ProgramTimeLeft(nil, programAddress)
Require(t, err)
expectedExpirySeconds := (uint64(expectedExpiryDays) * 24 * 3600)
// ProgramTimeLeft returns time in seconds to expiry and the current ExpiryDays is set to 1 day
// We expect the lag of 3600 seconds to exist because program.activatedAt uses hoursSinceArbitrum that
// rounds down (the current time since ArbitrumStartTime in hours)/3600
if expectedExpirySeconds-ptl > 3600 {
diegoximenes marked this conversation as resolved.
Show resolved Hide resolved
t.Errorf("ProgramTimeLeft from arbWasm precompile returned value lesser than expected. %d <= want <= %d, have: %d", expectedExpirySeconds-3600, expectedExpirySeconds, ptl)
}
// Since ArbOwner has set wasm KeepaliveDays to 0, it enables us to do this, though this shouldn't have any effect
codehashKeepaliveAuth := ownerAuth
codehashKeepaliveAuth.Value = oneEth
ensure(arbWasm.CodehashKeepalive(&codehashKeepaliveAuth, codehash))
}

func TestProgramActivationLogs(t *testing.T) {
t.Parallel()
builder, auth, cleanup := setupProgramTest(t, true)
Expand Down
Loading