Skip to content

Commit

Permalink
test(fvm): validate MCOPY opcode for FIP-0094 (#12556)
Browse files Browse the repository at this point in the history
---------

Co-authored-by: Rod Vagg <[email protected]>
Co-authored-by: Mikers <[email protected]>
  • Loading branch information
3 people authored Oct 14, 2024
1 parent f6d4fc7 commit bc50e5d
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 2 deletions.
1 change: 1 addition & 0 deletions itests/contracts/mcopy/MCOPYTest.hex
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6080604052348015600e575f80fd5b506103148061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063733580551461002d575b5f80fd5b61004760048036038101906100429190610217565b61005d565b60405161005491906102be565b60405180910390f35b60605f825167ffffffffffffffff81111561007b5761007a6100f3565b5b6040519080825280601f01601f1916602001820160405280156100ad5781602001600182028036833780820191505090505b509050825160208401602083018282825e50505080915050919050565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b610129826100e3565b810181811067ffffffffffffffff82111715610148576101476100f3565b5b80604052505050565b5f61015a6100ca565b90506101668282610120565b919050565b5f67ffffffffffffffff821115610185576101846100f3565b5b61018e826100e3565b9050602081019050919050565b828183375f83830152505050565b5f6101bb6101b68461016b565b610151565b9050828152602081018484840111156101d7576101d66100df565b5b6101e284828561019b565b509392505050565b5f82601f8301126101fe576101fd6100db565b5b813561020e8482602086016101a9565b91505092915050565b5f6020828403121561022c5761022b6100d3565b5b5f82013567ffffffffffffffff811115610249576102486100d7565b5b610255848285016101ea565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f6102908261025e565b61029a8185610268565b93506102aa818560208601610278565b6102b3816100e3565b840191505092915050565b5f6020820190508181035f8301526102d68184610286565b90509291505056fea2646970667358221220636e7de4492dd5c1e8857edc7182c645466bf34d0a2a0cea445a7de5360a9fe364736f6c634300081a0033
21 changes: 21 additions & 0 deletions itests/contracts/mcopy/MCOPYTest.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

contract MCOPYTest {
function optimizedCopy(bytes memory data) public pure returns (bytes memory) {
bytes memory result = new bytes(data.length);
assembly {
let length := mload(data) // Get the length of the input data
let source := add(data, 0x20) // Point to the start of the data (skip the length)
let destination := add(result, 0x20) // Point to the start of the result memory (skip the length)

// Use MCOPY opcode directly for memory copying
// destination: destination memory pointer
// source: source memory pointer
// length: number of bytes to copy
mcopy(destination, source, length)
}
return result;
}

}
52 changes: 52 additions & 0 deletions itests/fevm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,18 @@ import (
"github.com/stretchr/testify/require"

"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
builtintypes "github.com/filecoin-project/go-state-types/builtin"
"github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/go-state-types/manifest"
"github.com/filecoin-project/go-state-types/network"

"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/build/buildconstants"
"github.com/filecoin-project/lotus/chain/consensus/filcns"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/types/ethtypes"
Expand Down Expand Up @@ -1310,6 +1314,54 @@ func TestEthGetTransactionCount(t *testing.T) {
require.Zero(t, contractNonceAfterDestroy)
}

func TestMcopy(t *testing.T) {
// MCOPY introduced in nv24, start the test on nv23 to check the error, then upgrade at epoch 100
// and check that an MCOPY contract can be deployed and run.
nv24epoch := abi.ChainEpoch(100)
upgradeSchedule := kit.UpgradeSchedule(
stmgr.Upgrade{
Network: network.Version23,
Height: -1,
},
stmgr.Upgrade{
Network: network.Version24,
Height: nv24epoch,
Migration: filcns.UpgradeActorsV15,
},
)

ctx, cancel, client := kit.SetupFEVMTest(t, upgradeSchedule)
defer cancel()

// try to deploy the contract before the upgrade, expect an error somewhere' in deploy or in call,
// if the error is in deploy we may need to implement DeployContractFromFilename here where we can
// assert an error

// 0000000000000000000000000000000000000000000000000000000000000020: The offset for the bytes argument (32 bytes).
// 0000000000000000000000000000000000000000000000000000000000000008: The length of the bytes data (8 bytes for "testdata").
// 7465737464617461000000000000000000000000000000000000000000000000: The hexadecimal representation of "testdata", padded to 32 bytes.
hexString := "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000087465737464617461000000000000000000000000000000000000000000000000"

// Decode the hex string into a byte slice
inputArgument, err := hex.DecodeString(hexString)
require.NoError(t, err)

filenameActor := "contracts/mcopy/MCOPYTest.hex"
fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor)
_, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "optimizedCopy(bytes)", inputArgument)
// We expect an error here due to MCOPY not being available in this network version
require.ErrorContains(t, err, "undefined instruction (35)")

// wait for the upgrade
client.WaitTillChain(ctx, kit.HeightAtLeast(nv24epoch+5))

// should be able to deploy and call the contract now
fromAddr, contractAddr = client.EVM().DeployContractFromFilename(ctx, filenameActor)
result, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "optimizedCopy(bytes)", inputArgument)
require.NoError(t, err)
require.Equal(t, inputArgument, result)
}

func TestEthGetBlockByNumber(t *testing.T) {
blockTime := 100 * time.Millisecond
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
Expand Down
6 changes: 4 additions & 2 deletions itests/kit/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ func removeLeadingZeros(data []byte) []byte {
return data[firstNonZeroIndex:]
}

func SetupFEVMTest(t *testing.T) (context.Context, context.CancelFunc, *TestFullNode) {
func SetupFEVMTest(t *testing.T, opts ...interface{}) (context.Context, context.CancelFunc, *TestFullNode) {
// make all logs extra quiet for fevm tests
lvl, err := logging.LevelFromString("error")
if err != nil {
Expand All @@ -419,7 +419,9 @@ func SetupFEVMTest(t *testing.T) (context.Context, context.CancelFunc, *TestFull
logging.SetAllLoggers(lvl)

blockTime := 100 * time.Millisecond
client, _, ens := EnsembleMinimal(t, MockProofs(), ThroughRPC())

opts = append([]interface{}{MockProofs(), ThroughRPC()}, opts...)
client, _, ens := EnsembleMinimal(t, opts...)
ens.InterconnectAll().BeginMining(blockTime)
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)

Expand Down

0 comments on commit bc50e5d

Please sign in to comment.