Skip to content

Conversation

ARR4N
Copy link
Collaborator

@ARR4N ARR4N commented Oct 7, 2025

Why this should be merged

The temporary.WithTempRegisteredExtras() global lock introduced in #234 wasn't fit for purpose when used in coreth as it required central coordination of registration, types, and usage of the payload accessor.

How this works

Instead of a central registration point, the new libevm.WithTemporaryExtrasLock() function takes out a global lock and provides the caller with a handle that proves the lock is held. All of the override functions, e.g. params.WithTempRegisteredExtras() now require a current lock, which will be propagated by the respective coreth functions.

See ava-labs/coreth#1328 for intended usage in coreth and subnet-evm. A consumer of both of these can then safely do the following:

import (
    "github.com/ava-labs/libevm/libevm"

    coreth "github.com/ava-labs/coreth/plugin/evm"
    subnet "github.com/ava-labs/subnet-evm/plugin/evm"
)

// asCChain calls `fn` while emulating `coreth`. It is safe for concurrent usage with [asSubnetEVM].
func asCChain(fn func() error) error {
    return libevm.WithTemporaryExtrasLock(func(l libevm.ExtrasLock) error {
        return coreth.WithTempRegisteredLibEVMExtras(l, fn)
    })
}

// asSubnetEVM calls `fn` while emulating `subnet-evm`. It is safe for concurrent usage with [asCChain].
func asSubnetEVM(fn func() error) error {
    return libevm.WithTemporaryExtrasLock(func(l libevm.ExtrasLock) error {
        return subnet.WithTempRegisteredLibEVMExtras(l, fn)
    })
}

How this was tested

Unit test of the new function plus existing integration tests of all modified code.

@ARR4N ARR4N marked this pull request as ready for review October 7, 2025 15:43
@ARR4N ARR4N requested review from a team and ceyonur October 7, 2025 15:43
@ARR4N ARR4N self-assigned this Oct 8, 2025
Copy link

@ceyonur ceyonur left a comment

Choose a reason for hiding this comment

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

mostly questions

//
// WithTemporaryExtrasLock MUST NOT be used on a live chain. It is solely
// intended for off-chain consumers that require access to extras.
func WithTemporaryExtrasLock(fn func(lock ExtrasLock) error) error {
Copy link

Choose a reason for hiding this comment

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

I wonder if we can omit taking the lock in the fn

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

What do you mean? The fn doesn't take it; it waits for it to be taken before being called.

Copy link

Choose a reason for hiding this comment

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

Comment on lines +49 to +50
v := extrasHandle.Load()
return fn(ExtrasLock{&v})
Copy link

Choose a reason for hiding this comment

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

Why do we need to pass the lock here and defer the lock verification to the fn? Can't we verify that here? Are we expecting fn to be called with different locks?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Nope, we're expecting fn to pass the lock to every extras override, each of which does its own verification. This is an example of an fn and this is a test that demonstrates it being used to temporarily emulate all C-Chain behaviour via this package.

Copy link

Choose a reason for hiding this comment

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

1- This pattern could be difficult for a consumer. I wonder if we can move the complexity either to libevm or to coreth/subnet-evm so that the consumer can use something like this

evm.WithTempRegisteredLibEVMExtras(func() error { 
	t.Run("payloads", func(t *testing.T) {
		for pkg, fn := range payloadTests {
			t.Run(pkg, fn)
		}
	})
	return nil
})

TLDR; IMO locks should be abstracted away.

// An ExtrasLock is a handle that proves a current call to
// [WithTemporaryExtrasLock].
type ExtrasLock struct {
handle *uint64
Copy link

Choose a reason for hiding this comment

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

why do we have this handle as a uint64? Or why do we need the handle? Aren't this implying if the lock is held or not?

Comment on lines +49 to +50
v := extrasHandle.Load()
return fn(ExtrasLock{&v})
Copy link

Choose a reason for hiding this comment

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

1- This pattern could be difficult for a consumer. I wonder if we can move the complexity either to libevm or to coreth/subnet-evm so that the consumer can use something like this

evm.WithTempRegisteredLibEVMExtras(func() error { 
	t.Run("payloads", func(t *testing.T) {
		for pkg, fn := range payloadTests {
			t.Run(pkg, fn)
		}
	})
	return nil
})

TLDR; IMO locks should be abstracted away.

//
// WithTemporaryExtrasLock MUST NOT be used on a live chain. It is solely
// intended for off-chain consumers that require access to extras.
func WithTemporaryExtrasLock(fn func(lock ExtrasLock) error) error {
Copy link

Choose a reason for hiding this comment

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

//
// WithTemporaryExtrasLock MUST NOT be used on a live chain. It is solely
// intended for off-chain consumers that require access to extras.
func WithTemporaryExtrasLock(fn func(lock ExtrasLock) error) error {
Copy link

Choose a reason for hiding this comment

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

I wonder if taking multiple fns (i.e WithTemporaryExtrasLock(fns ...func(lock ExtrasLock) error)` would help cleaning this nested calls.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants