From 78fd77ad8ba12f0df37186164cce7de90d30000e Mon Sep 17 00:00:00 2001 From: Jimmy Moore Date: Tue, 3 Oct 2023 11:12:37 +0100 Subject: [PATCH] Updated to use extension hash rather than name in wasm fns Signed-off-by: Jimmy Moore --- extension/generator/generator.go | 10 +- extension/generator/golang/generator.go | 26 ++--- extension/generator/golang/generator_test.go | 12 ++- .../generator/golang/templates/guest.go.templ | 36 +++---- .../generator/golang/templates/host.go.templ | 39 ++++---- extension/generator/rust/generated.txt | 2 +- extension/generator/rust/generator.go | 7 +- extension/generator/rust/guest.txt | 96 +++++++++++++++---- .../generator/rust/templates/guest.rs.templ | 25 +++-- 9 files changed, 160 insertions(+), 93 deletions(-) diff --git a/extension/generator/generator.go b/extension/generator/generator.go index 8d604095..b4f884e5 100644 --- a/extension/generator/generator.go +++ b/extension/generator/generator.go @@ -75,7 +75,7 @@ func GenerateGuestLocal(options *Options) (*GuestLocalPackage, error) { return nil, err } - golangGuest, err := golang.GenerateGuest(options.Extension, options.GolangPackageName, options.GolangPackageVersion) + golangGuest, err := golang.GenerateGuest(options.Extension, hashString, options.GolangPackageName, options.GolangPackageVersion) if err != nil { return nil, err } @@ -125,12 +125,18 @@ func GenerateGuestLocal(options *Options) (*GuestLocalPackage, error) { } func GenerateHostLocal(options *Options) (*HostLocalPackage, error) { + hash, err := options.Extension.Hash() + if err != nil { + return nil, err + } + hashString := hex.EncodeToString(hash) + golangTypes, err := golang.GenerateTypes(options.Extension, options.GolangPackageName) if err != nil { return nil, err } - golangHost, err := golang.GenerateHost(options.Extension, options.GolangPackageName, options.GolangPackageVersion) + golangHost, err := golang.GenerateHost(options.Extension, hashString, options.GolangPackageName, options.GolangPackageVersion) if err != nil { return nil, err } diff --git a/extension/generator/golang/generator.go b/extension/generator/golang/generator.go index 2ce81a21..e9aaf147 100644 --- a/extension/generator/golang/generator.go +++ b/extension/generator/golang/generator.go @@ -42,16 +42,16 @@ func GenerateInterfaces(schema *extension.Schema, packageName string, version st return generator.GenerateInterfaces(schema, packageName, version) } -func GenerateGuest(schema *extension.Schema, packageName string, version string) ([]byte, error) { - return generator.GenerateGuest(schema, packageName, version) +func GenerateGuest(schema *extension.Schema, extensionHash string, packageName string, version string) ([]byte, error) { + return generator.GenerateGuest(schema, extensionHash, packageName, version) } func GenerateModfile(packageName string) ([]byte, error) { return generator.GenerateModfile(packageName) } -func GenerateHost(schema *extension.Schema, packageName string, version string) ([]byte, error) { - return generator.GenerateHost(schema, packageName, version) +func GenerateHost(schema *extension.Schema, extensionHash string, packageName string, version string) ([]byte, error) { + return generator.GenerateHost(schema, extensionHash, packageName, version) } func init() { @@ -122,16 +122,17 @@ func (g *Generator) GenerateInterfaces(schema *extension.Schema, packageName str } // GenerateGuest generates the guest bindings -func (g *Generator) GenerateGuest(schema *extension.Schema, packageName string, version string) ([]byte, error) { +func (g *Generator) GenerateGuest(schema *extension.Schema, schemaHash string, packageName string, version string) ([]byte, error) { if packageName == "" { packageName = defaultPackageName } buf := new(bytes.Buffer) err := g.templ.ExecuteTemplate(buf, "guest.go.templ", map[string]any{ - "schema": schema, - "version": version, - "package": packageName, + "extension_schema": schema, + "extension_hash": schemaHash, + "version": version, + "package": packageName, }) if err != nil { return nil, err @@ -156,16 +157,17 @@ func (g *Generator) GenerateModfile(packageImportPath string) ([]byte, error) { } // GenerateHost generates the host bindings -func (g *Generator) GenerateHost(schema *extension.Schema, packageName string, version string) ([]byte, error) { +func (g *Generator) GenerateHost(schema *extension.Schema, schemaHash string, packageName string, version string) ([]byte, error) { if packageName == "" { packageName = defaultPackageName } buf := new(bytes.Buffer) err := g.templ.ExecuteTemplate(buf, "host.go.templ", map[string]any{ - "schema": schema, - "version": version, - "package": packageName, + "extension_schema": schema, + "extension_hash": schemaHash, + "version": version, + "package": packageName, }) if err != nil { return nil, err diff --git a/extension/generator/golang/generator_test.go b/extension/generator/golang/generator_test.go index 429290ab..62cdb944 100644 --- a/extension/generator/golang/generator_test.go +++ b/extension/generator/golang/generator_test.go @@ -16,6 +16,7 @@ package golang import ( + "encoding/hex" "os" "testing" @@ -48,16 +49,19 @@ func TestGenerator(t *testing.T) { require.NoError(t, err) require.Equal(t, string(expTypes), string(formatted)) - host, err := GenerateHost(s, packageName, "v0.1.0") + sHash, err := s.Hash() + hash := hex.EncodeToString(sHash) + + host, err := GenerateHost(s, hash, packageName, "v0.1.0") require.NoError(t, err) - // os.WriteFile("./host.txt", host, 0644) + os.WriteFile("./host.txt", host, 0644) expHost, err := os.ReadFile("./host.txt") require.NoError(t, err) require.Equal(t, string(expHost), string(host)) - guest, err := GenerateGuest(s, packageName, "v0.1.0") + guest, err := GenerateGuest(s, hash, packageName, "v0.1.0") require.NoError(t, err) - // os.WriteFile("./guest.txt", guest, 0644) + os.WriteFile("./guest.txt", guest, 0644) expGuest, err := os.ReadFile("./guest.txt") require.NoError(t, err) require.Equal(t, string(expGuest), string(guest)) diff --git a/extension/generator/golang/templates/guest.go.templ b/extension/generator/golang/templates/guest.go.templ index 4e9adc5e..1a246529 100644 --- a/extension/generator/golang/templates/guest.go.templ +++ b/extension/generator/golang/templates/guest.go.templ @@ -1,7 +1,9 @@ // Code generated by scale-extension {{ .version }}, DO NOT EDIT. -// schema: {{ .schema.Name }}:{{ .schema.Tag }} +// schema: {{ .extension_schema.Name }}:{{ .extension_schema.Tag }} // output: {{ .package }} +{{ $hash := .extension_hash }} + package {{ .package }} import ( @@ -14,9 +16,9 @@ var ( readBuffer []byte ) -//export ext_{{ .schema.Name }}_Resize -//go:linkname ext_{{ .schema.Name }}_Resize -func ext_{{ .schema.Name }}_Resize(size uint32) uint32 { +//export ext_{{ $hash }}_Resize +//go:linkname ext_{{ $hash }}_Resize +func ext_{{ $hash }}_Resize(size uint32) uint32 { readBuffer = make([]byte, size) //if uint32(cap(readBuffer)) < size { // readBuffer = append(make([]byte, 0, uint32(len(readBuffer))+size), readBuffer...) @@ -25,12 +27,12 @@ func ext_{{ .schema.Name }}_Resize(size uint32) uint32 { return uint32(uintptr(unsafe.Pointer(&readBuffer[0]))) } -{{ $schema := .schema }} +{{ $schema := .extension_schema }} // Define any interfaces we need here... // Also define structs we can use to hold instanceId -{{ range $ifc := .schema.Interfaces }} +{{ range $ifc := .extension_schema.Interfaces }} // Define concrete types with a hidden instanceId @@ -54,7 +56,7 @@ func (d *_{{ $ifc.Name }}) {{ $fn.Name }}(params *{{ $fn.Params }}) ({{ $fn.Retu {{- if (IsInterface $schema $fn.Return) }} readBuffer = nil - v := ext_{{ $schema.Name }}_{{ $ifc.Name }}_{{ $fn.Name }}(d.instanceId, off, l) + v := ext_{{ $hash }}_{{ $ifc.Name }}_{{ $fn.Name }}(d.instanceId, off, l) // IF the return type is an interface return ifc, which contains hidden instanceId. // Handle error from host. In this case there'll be an error in the readBuffer @@ -72,7 +74,7 @@ func (d *_{{ $ifc.Name }}) {{ $fn.Name }}(params *{{ $fn.Params }}) ({{ $fn.Retu return ret, nil {{ else }} - ext_{{ $schema.Name }}_{{ $ifc.Name }}_{{ $fn.Name }}(d.instanceId, off, l) + ext_{{ $hash }}_{{ $ifc.Name }}_{{ $fn.Name }}(d.instanceId, off, l) // IF the return type is a model, we should read the data from the read buffer. ret := &{{ $fn.Return }}{} @@ -86,9 +88,9 @@ func (d *_{{ $ifc.Name }}) {{ $fn.Name }}(params *{{ $fn.Params }}) ({{ $fn.Retu {{ end }} } -//export ext_{{ $schema.Name }}_{{ $ifc.Name }}_{{ $fn.Name }} -//go:linkname ext_{{ $schema.Name }}_{{ $ifc.Name }}_{{ $fn.Name }} -func ext_{{ $schema.Name }}_{{ $ifc.Name }}_{{ $fn.Name }}(instance uint64, offset uint32, length uint32) uint64 +//export ext_{{ $hash }}_{{ $ifc.Name }}_{{ $fn.Name }} +//go:linkname ext_{{ $hash }}_{{ $ifc.Name }}_{{ $fn.Name }} +func ext_{{ $hash }}_{{ $ifc.Name }}_{{ $fn.Name }}(instance uint64, offset uint32, length uint32) uint64 {{ end }} @@ -96,11 +98,11 @@ func ext_{{ $schema.Name }}_{{ $ifc.Name }}_{{ $fn.Name }}(instance uint64, offs // Define any global functions here... -{{ range $fn := .schema.Functions }} +{{ range $fn := .extension_schema.Functions }} -//export ext_{{ $schema.Name }}_{{ $fn.Name }} -//go:linkname ext_{{ $schema.Name }}_{{ $fn.Name }} -func ext_{{ $schema.Name }}_{{ $fn.Name }}(instance uint64, offset uint32, length uint32) uint64 +//export ext_{{ $hash }}_{{ $fn.Name }} +//go:linkname ext_{{ $hash }}_{{ $fn.Name }} +func ext_{{ $hash }}_{{ $fn.Name }}(instance uint64, offset uint32, length uint32) uint64 func {{ $fn.Name }}(params *{{ $fn.Params }}) ({{ $fn.Return }}, error) { // First we take the params, serialize them. @@ -116,7 +118,7 @@ func {{ $fn.Name }}(params *{{ $fn.Params }}) ({{ $fn.Return }}, error) { {{- if (IsInterface $schema $fn.Return) }} readBuffer = nil - v := ext_{{ $schema.Name }}_{{ $fn.Name }}(0, off, l) + v := ext_{{ $hash }}_{{ $fn.Name }}(0, off, l) // IF the return type is an interface return ifc, which contains hidden instanceId. // Handle error from host. In this case there'll be an error in the readBuffer @@ -134,7 +136,7 @@ func {{ $fn.Name }}(params *{{ $fn.Params }}) ({{ $fn.Return }}, error) { return ret, nil {{ else }} - ext_{{ $schema.Name }}_{{ $fn.Name }}(0, off, l) + ext_{{ $hash }}_{{ $fn.Name }}(0, off, l) // IF the return type is a model, we should read the data from the read buffer. ret := &{{ $fn.Return }}{} diff --git a/extension/generator/golang/templates/host.go.templ b/extension/generator/golang/templates/host.go.templ index 50c42fe3..4d191a43 100644 --- a/extension/generator/golang/templates/host.go.templ +++ b/extension/generator/golang/templates/host.go.templ @@ -1,7 +1,10 @@ // Code generated by scale-extension {{ .version }}, DO NOT EDIT. -// schema: {{ .schema.Name }}:{{ .schema.Tag }} +// schema: {{ .extension_schema.Name }}:{{ .extension_schema.Tag }} // output: {{ .package }} +{{ $schema := .extension_schema }} +{{ $hash := .extension_hash }} + package {{ .package }} import ( @@ -13,14 +16,14 @@ import ( extension "github.com/loopholelabs/scale-extension-interfaces" ) -const identifier = "{{ .schema.Name }}:{{ .schema.Tag }}" +const identifier = "{{ .extension_schema.Name }}:{{ .extension_schema.Tag }}" // Write an error to the scale function guest buffer. func hostError(mem extension.ModuleMemory, resize extension.Resizer, err error) { b := polyglot.NewBuffer() polyglot.Encoder(b).Error(err) - writeBuffer, err := resize("ext_HttpFetch_Resize", uint64(b.Len())) + writeBuffer, err := resize("ext_{{ $hash }}_Resize", uint64(b.Len())) if err != nil { panic(err) @@ -31,11 +34,9 @@ func hostError(mem extension.ModuleMemory, resize extension.Resizer, err error) } } -{{ $schema := .schema }} - type hostExt struct { functions map[string]extension.InstallableFunc - host *{{ .schema.Name }}Host + host *{{ .extension_schema.Name }}Host } func (he *hostExt) Init() map[string]extension.InstallableFunc { @@ -44,27 +45,27 @@ func (he *hostExt) Init() map[string]extension.InstallableFunc { func (he *hostExt) Reset() { // Reset any instances that have been created. - {{ range $ifc := .schema.Interfaces }} + {{ range $ifc := .extension_schema.Interfaces }} he.host.instances_{{ $ifc.Name }} = make(map[uint64]{{ $ifc.Name }}) {{ end }} } -func New(impl {{ .schema.Name }}Ifc) extension.Extension { - hostWrapper := &{{ .schema.Name }}Host{ impl: impl } +func New(impl {{ .extension_schema.Name }}Ifc) extension.Extension { + hostWrapper := &{{ .extension_schema.Name }}Host{ impl: impl } fns := make(map[string]extension.InstallableFunc) // Add global functions to the runtime -{{ range $fn := .schema.Functions }} - fns["ext_{{ $schema.Name }}_{{ $fn.Name }}"] = hostWrapper.host_ext_{{ $schema.Name }}_{{ $fn.Name }} +{{ range $fn := .extension_schema.Functions }} + fns["ext_{{ $hash }}_{{ $fn.Name }}"] = hostWrapper.host_ext_{{ $schema.Name }}_{{ $fn.Name }} {{ end }} -{{ range $ifc := .schema.Interfaces }} +{{ range $ifc := .extension_schema.Interfaces }} hostWrapper.instances_{{ $ifc.Name }} = make(map[uint64]{{ $ifc.Name }}) {{ range $fn := $ifc.Functions }} - fns["ext_{{ $schema.Name }}_{{ $ifc.Name }}_{{ $fn.Name }}"] = hostWrapper.host_ext_{{ $schema.Name }}_{{ $ifc.Name }}_{{ $fn.Name }} + fns["ext_{{ $hash }}_{{ $ifc.Name }}_{{ $fn.Name }}"] = hostWrapper.host_ext_{{ $schema.Name }}_{{ $ifc.Name }}_{{ $fn.Name }} {{ end }} {{ end }} @@ -75,9 +76,9 @@ func New(impl {{ .schema.Name }}Ifc) extension.Extension { } } -type {{ .schema.Name }}Host struct { - impl {{ .schema.Name }}Ifc -{{ range $ifc := .schema.Interfaces }} +type {{ .extension_schema.Name }}Host struct { + impl {{ .extension_schema.Name }}Ifc +{{ range $ifc := .extension_schema.Interfaces }} gid_{{ $ifc.Name }} uint64 instancesLock_{{ $ifc.Name }} sync.Mutex @@ -88,7 +89,7 @@ type {{ .schema.Name }}Host struct { } // Global functions -{{ range $fn := .schema.Functions }} +{{ range $fn := .extension_schema.Functions }} func (h *{{ $schema.Name }}Host) host_ext_{{ $schema.Name }}_{{ $fn.Name}}(mem extension.ModuleMemory, resize extension.Resizer, params []uint64) { @@ -143,7 +144,7 @@ func (h *{{ $schema.Name }}Host) host_ext_{{ $schema.Name }}_{{ $fn.Name}}(mem e {{ end }} -{{ range $ifc := .schema.Interfaces }} +{{ range $ifc := .extension_schema.Interfaces }} {{ range $fn := $ifc.Functions }} @@ -189,7 +190,7 @@ func (h *{{ $schema.Name }}Host) host_ext_{{ $schema.Name }}_{{ $ifc.Name }}_{{ b := polyglot.NewBuffer() resp.Encode(b) - writeBuffer, err := resize("ext_{{ $schema.Name }}_Resize", uint64(b.Len())) + writeBuffer, err := resize("ext_{{ $hash }}_Resize", uint64(b.Len())) if err != nil { hostError(mem, resize, err) diff --git a/extension/generator/rust/generated.txt b/extension/generator/rust/generated.txt index 6b4ea1b1..176efc3b 100644 --- a/extension/generator/rust/generated.txt +++ b/extension/generator/rust/generated.txt @@ -1,4 +1,4 @@ -// Code generated by scale-extension 0.4.1, DO NOT EDIT. +// Code generated by scale-extension 0.4.2, DO NOT EDIT. // output: types #![allow(dead_code)] diff --git a/extension/generator/rust/generator.go b/extension/generator/rust/generator.go index c0a890b4..31beade7 100644 --- a/extension/generator/rust/generator.go +++ b/extension/generator/rust/generator.go @@ -16,7 +16,6 @@ package rust import ( "bytes" "context" - "fmt" "strings" "text/template" @@ -50,8 +49,8 @@ func GenerateCargofile(packageName string, packageVersion string) ([]byte, error return generator.GenerateCargofile(packageName, packageVersion) } -func GenerateGuest(extensionSchema *extension.Schema, signatureHash string, packageName string) ([]byte, error) { - return generator.GenerateGuest(extensionSchema, signatureHash, packageName) +func GenerateGuest(extensionSchema *extension.Schema, extensionHash string, packageName string) ([]byte, error) { + return generator.GenerateGuest(extensionSchema, extensionHash, packageName) } func init() { @@ -145,8 +144,6 @@ func (g *Generator) GenerateGuest(extensionSchema *extension.Schema, extensionHa packageName = defaultPackageName } - fmt.Printf("Generating guest...\n") - buf := new(bytes.Buffer) err := g.templ.ExecuteTemplate(buf, "guest.rs.templ", map[string]any{ "extension_schema": extensionSchema, diff --git a/extension/generator/rust/guest.txt b/extension/generator/rust/guest.txt index 8824eec1..82b75800 100644 --- a/extension/generator/rust/guest.txt +++ b/extension/generator/rust/guest.txt @@ -1,4 +1,4 @@ -// Code generated by scale-extension 0.4.1, DO NOT EDIT. +// Code generated by scale-extension 0.4.2, DO NOT EDIT. // output: guest @@ -8,7 +8,7 @@ pub mod types; use crate::types::{Encode, Decode}; use std::io::Cursor; -use polyglot_rs::{Encoder}; +use polyglot_rs::{Decoder, Encoder}; static HASH: &'static str = "3914ee157703d809e20bf4e9f4a6d0cf0db287ec4b3dcfe4982c25b0101bc156"; @@ -24,7 +24,7 @@ static mut WRITE_BUFFER: Vec = Vec::new(); pub trait HttpConnector { - fn Fetch(&self, ConnectionDetails) -> Result, Box> + fn Fetch(&self, params: types::ConnectionDetails) -> Result, Box>; @@ -42,11 +42,28 @@ pub unsafe fn ext_HttpFetch_Resize(size: u32) -> *const u8 { return READ_BUFFER.as_ptr(); } +// Define imports for instances + + + + +#[link(wasm_import_module = "env")] +extern "C" { + #[link_name = "ext_HttpFetch_HttpConnector_Fetch"] + fn _ext_HttpFetch_HttpConnector_Fetch(instance: u64, ptr: u32, size: u32) -> u64; +} + + + + +// All external interface functions defined. + // Define any interfaces we need here... // Also define structs we can use to hold instanceId + // Define concrete types with a hidden instanceId HttpConnector #[derive(Clone, Debug, PartialEq)] @@ -54,15 +71,42 @@ pub struct _HttpConnector { pub instanceId: u64, } +impl HttpConnector for _HttpConnector { + + +fn Fetch(&self, params: types::ConnectionDetails) -> Result, Box> { + + + unsafe { -// func (d *_HttpConnector) Fetch(params *ConnectionDetails) (HttpResponse, error) { -// } + let mut cursor = Cursor::new(Vec::new()); -//export ext_HttpFetch_HttpConnector_Fetch -//go:linkname ext_HttpFetch_HttpConnector_Fetch -//func ext_HttpFetch_HttpConnector_Fetch(instance uint64, offset uint32, length uint32) uint64 + types::ConnectionDetails::encode(Some(¶ms), &mut cursor); + let vec = cursor.into_inner(); + WRITE_BUFFER.resize(vec.len() as usize, 0); + WRITE_BUFFER.copy_from_slice(&vec); + + // Now make the call to the host. + + let mut off = WRITE_BUFFER.as_ptr() as u32; + let mut l = WRITE_BUFFER.len() as u32; + _ext_HttpFetch_HttpConnector_Fetch(self.instanceId, off, l); + // IF the return type is a model, we should read the data from the read buffer. + + let mut cursor = Cursor::new(&mut READ_BUFFER); + return types::HttpResponse::decode(&mut cursor) + + //return Ok(Some(c)) + + + } +} + + + +} @@ -75,24 +119,37 @@ extern "C" { #[link_name = "ext_HttpFetch_New"] fn _ext_HttpFetch_New(instance: u64, ptr: u32, size: u32) -> u64; } -pub fn New(params: types::HttpConfig) -> Result, Box> { +pub fn New(params: types::HttpConfig) -> Result, Box> { + + + unsafe { - // TODO: First we take the params, serialize them. - //writeBuffer.Reset() - //params.Encode(writeBuffer) - //underlying := writeBuffer.Bytes() - //ptr := &underlying[0] - //unsafePtr := uintptr(unsafe.Pointer(ptr)) - //off := uint32(unsafePtr) - //l := uint32(writeBuffer.Len()) + let mut cursor = Cursor::new(Vec::new()); + + types::HttpConfig::encode(Some(¶ms), &mut cursor); + + let vec = cursor.into_inner(); + + WRITE_BUFFER.resize(vec.len() as usize, 0); + WRITE_BUFFER.copy_from_slice(&vec); // Now make the call to the host. - let off = WRITE_BUFFER.as_ptr() as u32; - let l = WRITE_BUFFER.len() as u32; + let mut off = WRITE_BUFFER.as_ptr() as u32; + let mut l = WRITE_BUFFER.len() as u32; + READ_BUFFER.resize(0, 0); let v = _ext_HttpFetch_New(0, off, l); // IF the return type is an interface return ifc, which contains hidden instanceId. + // Check for an error + if READ_BUFFER.len() > 0 { + // Read the error and return it... + let mut cursor = Cursor::new(&mut READ_BUFFER); + if let Ok(error) = cursor.decode_error() { + return Err(error); + } + } + // TODO: Handle error from host. In this case there'll be an error in the readBuffer let c = _HttpConnector{ @@ -101,6 +158,7 @@ pub fn New(params: types::HttpConfig) -> Result *const u8 { +pub unsafe fn ext_{{ $hash }}_Resize(size: u32) -> *const u8 { READ_BUFFER.resize(size as usize, 0); return READ_BUFFER.as_ptr(); } @@ -50,8 +51,8 @@ pub unsafe fn ext_{{ .extension_schema.Name }}_Resize(size: u32) -> *const u8 { #[link(wasm_import_module = "env")] extern "C" { - #[link_name = "ext_{{ $schema.Name }}_{{ $ifc.Name }}_{{ $fn.Name }}"] - fn _ext_{{ $schema.Name }}_{{ $ifc.Name }}_{{ $fn.Name }}(instance: u64, ptr: u32, size: u32) -> u64; + #[link_name = "ext_{{ $hash }}_{{ $ifc.Name }}_{{ $fn.Name }}"] + fn _ext_{{ $hash }}_{{ $ifc.Name }}_{{ $fn.Name }}(instance: u64, ptr: u32, size: u32) -> u64; } {{ end }} @@ -99,18 +100,16 @@ fn {{ $fn.Name }}(&self, params: types::{{ $fn.Params }}) -> Result