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

PoC: WebAssembly API #2760

Draft
wants to merge 49 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
2b7c365
add support for dictionary types
turbolent Aug 31, 2023
9fdfb4d
update wasmtime
turbolent Sep 1, 2023
cbc1ece
improve encodeArgs helper
turbolent Sep 1, 2023
a780497
add the start of a WebAssembly contract
turbolent Sep 1, 2023
188b162
Merge branch 'feature/stable-cadence' into bastian/webassembly
turbolent Sep 1, 2023
02a0122
add comment explaining the program
turbolent Sep 22, 2023
8d9cbb6
convert type
turbolent Sep 22, 2023
254cb3d
Merge branch 'feature/stable-cadence' into bastian/webassembly
turbolent Sep 22, 2023
eaaf1ea
Merge branch 'bastian/allow-type-injection' into bastian/webassembly
turbolent Sep 22, 2023
d4265f6
inject WebAssembly standard library type into environment
turbolent Sep 22, 2023
384eef2
gate WebAssembly behind feture flag
turbolent Sep 23, 2023
4240bf9
move wasmtime-based WebAssembly module to runtime, so it can be reused
turbolent Sep 23, 2023
57b8d6a
rename
turbolent Sep 23, 2023
8d30d3a
extract constructor for wasmtime-based WebAssembly module
turbolent Sep 23, 2023
606c3a2
add metering using fuel mechanism
turbolent Sep 23, 2023
a6e7b9a
fix return type conversion
turbolent Sep 23, 2023
f54b831
Merge branch 'bastian/sync-stable-cadence-10' into bastian/webassembly
turbolent Oct 5, 2023
f8270bd
Merge branch 'bastian/sync-stable-cadence-10' into bastian/webassembly
turbolent Oct 5, 2023
692aa2a
re-generate
turbolent Oct 5, 2023
eb98a3d
Merge branch 'feature/stable-cadence' into bastian/webassembly
turbolent Oct 5, 2023
b4c634b
update comment to reflect current functionality
turbolent Mar 3, 2024
cbfcbd3
Merge branch 'master' into bastian/webassembly
turbolent Jun 25, 2024
b67d23f
update to wasmtime v22
turbolent Jun 25, 2024
e470d46
intgrate WebAssembly standard library values and types into existing …
turbolent Jun 25, 2024
ead17b8
lint
turbolent Jun 25, 2024
e3c752f
update copyright
turbolent Jun 25, 2024
f197db0
improve config
turbolent Jun 25, 2024
23795cb
improve metering: always meter, even on failure
turbolent Jun 25, 2024
f6b6acf
disabling SIMD is broken
turbolent Jun 25, 2024
8bcbf8c
fix check
turbolent Jun 25, 2024
12b56a5
limit store contents
turbolent Jun 25, 2024
9089bc6
add comments
turbolent Jun 26, 2024
6b6c8fb
update wasmtime
turbolent Jun 26, 2024
e55b81e
improve wasmtime setup
turbolent Jun 26, 2024
8bd4f7f
update wasmtime
turbolent Jul 12, 2024
d737d3d
add tests
turbolent Jul 12, 2024
efa0800
convert wasmtime trap to generic stdlib trap error
turbolent Jul 12, 2024
d9a6321
make trap error a user error
turbolent Jul 12, 2024
12817cb
improve error for invalid non-function export
turbolent Jul 12, 2024
ab88756
improve error for WebAssembly module compilation failure
turbolent Jul 12, 2024
a3fe557
convert wasmtime call trap into generic WebAssembly trap error
turbolent Jul 12, 2024
9b4c462
GetFuel/SetFuel should never error
turbolent Jul 12, 2024
755d0d3
add runtime interface method to get remaining computation for given kind
turbolent Jul 12, 2024
ef5d371
use new computation remaining for fuel
turbolent Jul 12, 2024
2d42183
Merge branch 'master' into bastian/webassembly
turbolent Jul 13, 2024
e6c5f1b
Merge branch 'master' into bastian/webassembly
turbolent Oct 16, 2024
d3cca43
fix merge: implement new runtime interface functions
turbolent Oct 16, 2024
c0a9bf1
update to wasmtime v25
turbolent Oct 16, 2024
91b3e19
Merge branch 'master' into bastian/webassembly
turbolent Nov 1, 2024
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
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ require (

require (
github.com/SaveTheRbtz/mph v0.1.2
github.com/bytecodealliance/wasmtime-go/v7 v7.0.0
github.com/bytecodealliance/wasmtime-go/v12 v12.0.0
github.com/k0kubun/pp v3.0.1+incompatible
github.com/k0kubun/pp/v3 v3.2.0
github.com/logrusorgru/aurora/v4 v4.0.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ github.com/SaveTheRbtz/mph v0.1.2 h1:5l3W496Up+7BNOVJQnJhzcGBh+wWfxWdmPUAkx3WmaM
github.com/SaveTheRbtz/mph v0.1.2/go.mod h1:V4+WtKQPe2+dEA5os1WnGsEB0NR9qgqqgIiSt73+sT4=
github.com/bits-and-blooms/bitset v1.2.2 h1:J5gbX05GpMdBjCvQ9MteIg2KKDExr7DrgK+Yc15FvIk=
github.com/bits-and-blooms/bitset v1.2.2/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
github.com/bytecodealliance/wasmtime-go/v7 v7.0.0 h1:/rBNjgFju2HCZnkPb1eL+W4GBwP8DMbaQu7i+GR9DH4=
github.com/bytecodealliance/wasmtime-go/v7 v7.0.0/go.mod h1:bu6fic7trDt20w+LMooX7j3fsOwv4/ln6j8gAdP6vmA=
github.com/bytecodealliance/wasmtime-go/v12 v12.0.0 h1:Wga02UaZXYF3p0LIeL5xFp09/RI7UhjfT2uB0mLrwlw=
github.com/bytecodealliance/wasmtime-go/v12 v12.0.0/go.mod h1:a3PRoftJxxUzkQvgjC6sv7pKyJJK0ZsFVmH+eeEKQC4=
github.com/c-bata/go-prompt v0.2.5 h1:3zg6PecEywxNn0xiqcXHD96fkbxghD+gdB2tbsYfl+Y=
github.com/c-bata/go-prompt v0.2.5/go.mod h1:vFnjEGDIIA/Lib7giyE4E9c50Lvl8j0S+7FVlAwDAVw=
github.com/dave/dst v0.27.2 h1:4Y5VFTkhGLC1oddtNwuxxe36pnyLxMFXT51FOzH8Ekc=
Expand Down
8 changes: 4 additions & 4 deletions runtime/account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ func TestRuntimeAuthAccountKeysAdd(t *testing.T) {
err := rt.ExecuteTransaction(
Script{
Source: []byte(code),
Arguments: encodeArgs([]cadence.Value{pubKey}),
Arguments: encodeArgs(pubKey),
},
Context{
Location: nextTransactionLocation(),
Expand Down Expand Up @@ -1051,7 +1051,7 @@ func addPublicKeyValidation(runtimeInterface *testRuntimeInterface, returnError
}
}

func encodeArgs(argValues []cadence.Value) [][]byte {
func encodeArgs(argValues ...cadence.Value) [][]byte {
args := make([][]byte, len(argValues))
for i, arg := range argValues {
var err error
Expand All @@ -1074,7 +1074,7 @@ func (test accountKeyTestCase) executeTransaction(
runtimeInterface *testRuntimeInterface,
location Location,
) error {
args := encodeArgs(test.args)
args := encodeArgs(test.args...)

err := runtime.ExecuteTransaction(
Script{
Expand All @@ -1094,7 +1094,7 @@ func (test accountKeyTestCase) executeScript(
runtimeInterface *testRuntimeInterface,
) (cadence.Value, error) {

args := encodeArgs(test.args)
args := encodeArgs(test.args...)

value, err := runtime.ExecuteScript(
Script{
Expand Down
4 changes: 4 additions & 0 deletions runtime/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,10 @@ func (*StandardLibraryHandler) BLSAggregateSignatures(_ [][]byte) ([]byte, error
return nil, goerrors.New("crypto functionality is not available in this environment")
}

func (*StandardLibraryHandler) CompileWebAssembly(_ []byte) (stdlib.WebAssemblyModule, error) {
return nil, goerrors.New("WebAssembly functionality is not available in this environment")
}

func (h *StandardLibraryHandler) NewOnEventEmittedHandler() interpreter.OnEventEmittedFunc {
return func(
inter *interpreter.Interpreter,
Expand Down
10 changes: 5 additions & 5 deletions runtime/crypto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ func TestRuntimeSignatureAlgorithmImport(t *testing.T) {
value, err := runtime.ExecuteScript(
Script{
Source: []byte(script),
Arguments: encodeArgs([]cadence.Value{
Arguments: encodeArgs(
cadence.NewEnum([]cadence.Value{
cadence.UInt8(algo.RawValue()),
}).WithType(&cadence.EnumType{
Expand All @@ -364,7 +364,7 @@ func TestRuntimeSignatureAlgorithmImport(t *testing.T) {
},
},
}),
}),
),
},
Context{
Interface: runtimeInterface,
Expand Down Expand Up @@ -433,7 +433,7 @@ func TestRuntimeHashAlgorithmImport(t *testing.T) {
value, err := runtime.ExecuteScript(
Script{
Source: []byte(script),
Arguments: encodeArgs([]cadence.Value{
Arguments: encodeArgs(
cadence.NewEnum([]cadence.Value{
cadence.UInt8(algo.RawValue()),
}).WithType(&cadence.EnumType{
Expand All @@ -446,7 +446,7 @@ func TestRuntimeHashAlgorithmImport(t *testing.T) {
},
},
}),
}),
),
},
Context{
Interface: runtimeInterface,
Expand Down Expand Up @@ -810,7 +810,7 @@ func TestRuntimeTraversingMerkleProof(t *testing.T) {
_, err := runtime.ExecuteScript(
Script{
Source: script,
Arguments: encodeArgs([]cadence.Value{rootHash, address, accountProof}),
Arguments: encodeArgs(rootHash, address, accountProof),
},
Context{
Interface: runtimeInterface,
Expand Down
4 changes: 4 additions & 0 deletions runtime/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,10 @@ func (e *interpreterEnvironment) Hash(data []byte, tag string, algorithm sema.Ha
return e.runtimeInterface.Hash(data, tag, algorithm)
}

func (e *interpreterEnvironment) CompileWebAssembly(bytes []byte) (stdlib.WebAssemblyModule, error) {
return e.runtimeInterface.CompileWebAssembly(bytes)
}

func (e *interpreterEnvironment) DecodeArgument(argument []byte, argumentType cadence.Type) (cadence.Value, error) {
return e.runtimeInterface.DecodeArgument(argument, argumentType)
}
Expand Down
12 changes: 6 additions & 6 deletions runtime/ft_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -617,10 +617,10 @@ func BenchmarkRuntimeFungibleTokenTransfer(b *testing.B) {
err = runtime.ExecuteTransaction(
Script{
Source: []byte(realMintFlowTokenTransaction),
Arguments: encodeArgs([]cadence.Value{
Arguments: encodeArgs(
cadence.Address(senderAddress),
mintAmount,
}),
),
},
Context{
Interface: runtimeInterface,
Expand All @@ -645,10 +645,10 @@ func BenchmarkRuntimeFungibleTokenTransfer(b *testing.B) {
err = runtime.ExecuteTransaction(
Script{
Source: []byte(realFlowTokenTransferTransaction),
Arguments: encodeArgs([]cadence.Value{
Arguments: encodeArgs(
sendAmount,
cadence.Address(receiverAddress),
}),
),
},
Context{
Interface: runtimeInterface,
Expand All @@ -675,9 +675,9 @@ func BenchmarkRuntimeFungibleTokenTransfer(b *testing.B) {
result, err := runtime.ExecuteScript(
Script{
Source: []byte(realFlowTokenBalanceScript),
Arguments: encodeArgs([]cadence.Value{
Arguments: encodeArgs(
cadence.Address(address),
}),
),
},
Context{
Interface: runtimeInterface,
Expand Down
8 changes: 4 additions & 4 deletions runtime/imported_values_memory_metering_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func TestRuntimeImportedValueMemoryMetering(t *testing.T) {
_, err := runtime.ExecuteScript(
Script{
Source: script,
Arguments: encodeArgs(args),
Arguments: encodeArgs(args...),
},
Context{
Interface: runtimeInterface,
Expand Down Expand Up @@ -508,9 +508,9 @@ func TestRuntimeImportedValueMemoryMeteringForSimpleTypes(t *testing.T) {
_, err := runtime.ExecuteScript(
Script{
Source: script,
Arguments: encodeArgs([]cadence.Value{
Arguments: encodeArgs(
test.TypeInstance,
}),
),
},
Context{
Interface: runtimeInterface,
Expand Down Expand Up @@ -583,7 +583,7 @@ func TestRuntimeScriptDecodedLocationMetering(t *testing.T) {
_, err := runtime.ExecuteScript(
Script{
Source: script,
Arguments: encodeArgs([]cadence.Value{value}),
Arguments: encodeArgs(value),
},
Context{
Interface: runtimeInterface,
Expand Down
2 changes: 2 additions & 0 deletions runtime/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/onflow/cadence"
"github.com/onflow/cadence/runtime/common"
"github.com/onflow/cadence/runtime/interpreter"
"github.com/onflow/cadence/runtime/stdlib"
)

type Interface interface {
Expand Down Expand Up @@ -143,6 +144,7 @@ type Interface interface {
)
// GenerateAccountID generates a new, *non-zero*, unique ID for the given account.
GenerateAccountID(address common.Address) (uint64, error)
CompileWebAssembly(bytes []byte) (stdlib.WebAssemblyModule, error)
}

type MeterInterface interface {
Expand Down
8 changes: 4 additions & 4 deletions runtime/rlp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,14 @@ func TestRuntimeRLPDecodeString(t *testing.T) {
result, err := runtime.ExecuteScript(
Script{
Source: script,
Arguments: encodeArgs([]cadence.Value{
Arguments: encodeArgs(
cadence.Array{
ArrayType: &cadence.VariableSizedArrayType{
ElementType: cadence.UInt8Type,
},
Values: test.input,
},
}),
),
},
Context{
Interface: runtimeInterface,
Expand Down Expand Up @@ -295,14 +295,14 @@ func TestRuntimeRLPDecodeList(t *testing.T) {
result, err := runtime.ExecuteScript(
Script{
Source: script,
Arguments: encodeArgs([]cadence.Value{
Arguments: encodeArgs(
cadence.Array{
ArrayType: &cadence.VariableSizedArrayType{
ElementType: cadence.UInt8Type,
},
Values: test.input,
},
}),
),
},
Context{
Interface: runtimeInterface,
Expand Down
34 changes: 17 additions & 17 deletions runtime/runtime_memory_metering_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,9 @@ func TestRuntimeCadenceValueAndTypeMetering(t *testing.T) {
_, err := runtime.ExecuteScript(
Script{
Source: []byte(script),
Arguments: encodeArgs([]cadence.Value{
Arguments: encodeArgs(
cadence.NewInt(12),
}),
),
},
Context{
Interface: runtimeInterface,
Expand Down Expand Up @@ -271,9 +271,9 @@ func TestRuntimeCadenceValueAndTypeMetering(t *testing.T) {
_, err := runtime.ExecuteScript(
Script{
Source: []byte(script),
Arguments: encodeArgs([]cadence.Value{
Arguments: encodeArgs(
largeInt,
}),
),
},
Context{
Interface: runtimeInterface,
Expand Down Expand Up @@ -307,9 +307,9 @@ func TestRuntimeCadenceValueAndTypeMetering(t *testing.T) {
_, err := runtime.ExecuteScript(
Script{
Source: []byte(script),
Arguments: encodeArgs([]cadence.Value{
Arguments: encodeArgs(
cadence.NewInt8(12),
}),
),
},
Context{
Interface: runtimeInterface,
Expand Down Expand Up @@ -343,9 +343,9 @@ func TestRuntimeCadenceValueAndTypeMetering(t *testing.T) {
_, err := runtime.ExecuteScript(
Script{
Source: []byte(script),
Arguments: encodeArgs([]cadence.Value{
Arguments: encodeArgs(
cadence.NewInt16(12),
}),
),
},
Context{
Interface: runtimeInterface,
Expand Down Expand Up @@ -379,9 +379,9 @@ func TestRuntimeCadenceValueAndTypeMetering(t *testing.T) {
_, err := runtime.ExecuteScript(
Script{
Source: []byte(script),
Arguments: encodeArgs([]cadence.Value{
Arguments: encodeArgs(
cadence.NewInt32(12),
}),
),
},
Context{
Interface: runtimeInterface,
Expand Down Expand Up @@ -415,9 +415,9 @@ func TestRuntimeCadenceValueAndTypeMetering(t *testing.T) {
_, err := runtime.ExecuteScript(
Script{
Source: []byte(script),
Arguments: encodeArgs([]cadence.Value{
Arguments: encodeArgs(
cadence.NewInt64(12),
}),
),
},
Context{
Interface: runtimeInterface,
Expand Down Expand Up @@ -451,9 +451,9 @@ func TestRuntimeCadenceValueAndTypeMetering(t *testing.T) {
_, err := runtime.ExecuteScript(
Script{
Source: []byte(script),
Arguments: encodeArgs([]cadence.Value{
Arguments: encodeArgs(
cadence.NewInt128(12),
}),
),
},
Context{
Interface: runtimeInterface,
Expand Down Expand Up @@ -487,9 +487,9 @@ func TestRuntimeCadenceValueAndTypeMetering(t *testing.T) {
_, err := runtime.ExecuteScript(
Script{
Source: []byte(script),
Arguments: encodeArgs([]cadence.Value{
Arguments: encodeArgs(
cadence.NewInt256(12),
}),
),
},
Context{
Interface: runtimeInterface,
Expand Down Expand Up @@ -989,7 +989,7 @@ func TestRuntimeMemoryMeteringErrors(t *testing.T) {
_, err := runtime.ExecuteScript(
Script{
Source: script,
Arguments: encodeArgs(args),
Arguments: encodeArgs(args...),
},
Context{
Interface: runtimeInterface(meter),
Expand Down
13 changes: 11 additions & 2 deletions runtime/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ type testRuntimeInterface struct {
interactionUsed func() (uint64, error)
updatedContractCode bool
generateAccountID func(address common.Address) (uint64, error)
compileWebAssembly func(bytes []byte) (stdlib.WebAssemblyModule, error)

uuid uint64
accountIDs map[common.Address]uint64
Expand Down Expand Up @@ -618,6 +619,14 @@ func (i *testRuntimeInterface) BLSAggregatePublicKeys(keys []*stdlib.PublicKey)
return i.blsAggregatePublicKeys(keys)
}

func (i *testRuntimeInterface) CompileWebAssembly(bytes []byte) (stdlib.WebAssemblyModule, error) {
if i.compileWebAssembly == nil {
return nil, nil
}

return i.compileWebAssembly(bytes)
}

func (i *testRuntimeInterface) GetAccountContractNames(address Address) ([]string, error) {
if i.getAccountContractNames == nil {
return []string{}, nil
Expand Down Expand Up @@ -8069,9 +8078,9 @@ func TestRuntimeAccountTypeEquality(t *testing.T) {
result, err := rt.ExecuteScript(
Script{
Source: script,
Arguments: encodeArgs([]cadence.Value{
Arguments: encodeArgs(
cadence.Address(common.MustBytesToAddress([]byte{0x1})),
}),
),
},
Context{
Interface: runtimeInterface,
Expand Down
2 changes: 2 additions & 0 deletions runtime/stdlib/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type StandardLibraryHandler interface {
BLSPublicKeyAggregator
BLSSignatureAggregator
Hasher
WebAssemblyContractHandler
}

func DefaultStandardLibraryValues(handler StandardLibraryHandler) []StandardLibraryValue {
Expand All @@ -51,6 +52,7 @@ func DefaultStandardLibraryValues(handler StandardLibraryHandler) []StandardLibr
NewPublicKeyConstructor(handler, handler, handler),
NewBLSContract(nil, handler),
NewHashAlgorithmConstructor(handler),
NewWebAssemblyContract(nil, handler),
}
}

Expand Down
Loading
Loading