diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000000..6dfc370f71 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,34 @@ +# Description of change + +Please write a summary of your changes and why you made them. + +## Links to any relevant issues + +Be sure to reference any related issues by adding `fixes issue #`. + +## Type of change + +Choose a type of change, and delete any options that are not relevant. + +- Bug fix (a non-breaking change which fixes an issue) +- Enhancement (a non-breaking change which adds functionality) +- Breaking change (fix or feature that would cause existing functionality to not work as expected) +- Documentation Fix + +## How the change has been tested + +Describe the tests that you ran to verify your changes. + +Make sure to provide instructions for the maintainer as well as any relevant configurations. + +## Change checklist + +Tick the boxes that are relevant to your changes, and delete any items that are not. + +- [ ] I have followed the [contribution guidelines](https://wiki.iota.org/smart-contracts/contribute) for this project +- [ ] I have performed a self-review of my own code +- [ ] I have selected the `develop` branch as the target branch +- [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] I have made corresponding changes to the documentation +- [ ] I have added tests that prove my fix is effective or that my feature works +- [ ] I have checked that new and existing unit tests pass locally with my changes diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 34a058225e..74e4de1bc5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,9 +16,12 @@ jobs: name: Set up Go uses: actions/setup-go@v2 with: - go-version: 1.15 + go-version: ^1.15 - name: Run GoReleaser - run: goreleaser --rm-dist + uses: goreleaser/goreleaser-action@v2 + with: + version: latest + args: release --rm-dist env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 16ec869941..14b019c3ab 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,6 @@ wasp-cli.json .DS_Store ./tools/wasp-cli/wasp-cli .docusaurus -node_modules +**/node_modules/ goshimmer.log /*.sh diff --git a/.goreleaser.yml b/.goreleaser.yml index 4b47c9bbf8..c99d9da5da 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -12,8 +12,10 @@ builds: - -tags=builtin_static,rocksdb goos: - linux - - windows - - darwin + # Disabled until the grocksdb supports darwin and windows: + # See: https://github.com/gohornet/grocksdb/commit/0ad7d027aa822e322cd81b2ef7e6696b675472b6 + # - windows + # - darwin goarch: - amd64 @@ -39,7 +41,7 @@ archives: format: zip wrap_in_directory: true files: - - readme.md + - README.md - config.json - LICENSE diff --git a/client/callview.go b/client/callview.go index c64b5b45eb..192e16f8b3 100644 --- a/client/callview.go +++ b/client/callview.go @@ -28,7 +28,7 @@ func (c *WaspClient) CallView(chainID *iscp.ChainID, hContract iscp.Hname, funct var res dict.Dict var err error for { - err = c.do(http.MethodGet, routes.CallView(chainID.Base58(), hContract.String(), functionName), arguments, &res) + err = c.do(http.MethodPost, routes.CallView(chainID.Base58(), hContract.String(), functionName), arguments, &res) switch { case err == nil: return res, err diff --git a/client/chain_info.go b/client/chain_info.go new file mode 100644 index 0000000000..f328b36ca8 --- /dev/null +++ b/client/chain_info.go @@ -0,0 +1,21 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package client + +import ( + "net/http" + + "github.com/iotaledger/wasp/packages/iscp" + "github.com/iotaledger/wasp/packages/webapi/model" + "github.com/iotaledger/wasp/packages/webapi/routes" +) + +// GetChainRecord fetches ChainInfo by address +func (c *WaspClient) GetChainInfo(chID *iscp.ChainID) (*model.ChainInfo, error) { + res := &model.ChainInfo{} + if err := c.do(http.MethodGet, routes.GetChainInfo(chID.Base58()), nil, res); err != nil { + return nil, err + } + return res, nil +} diff --git a/client/chain_record.go b/client/chain_record.go index 8449b70f76..aaf1a3bfd2 100644 --- a/client/chain_record.go +++ b/client/chain_record.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package client import ( diff --git a/client/committee_record.go b/client/committee_record.go deleted file mode 100644 index 064f5091da..0000000000 --- a/client/committee_record.go +++ /dev/null @@ -1,34 +0,0 @@ -package client - -import ( - "net/http" - - "github.com/iotaledger/goshimmer/packages/ledgerstate" - "github.com/iotaledger/wasp/packages/iscp" - "github.com/iotaledger/wasp/packages/registry" - "github.com/iotaledger/wasp/packages/webapi/model" - "github.com/iotaledger/wasp/packages/webapi/routes" -) - -// PutCommitteeRecord sends a request to write a Record -func (c *WaspClient) PutCommitteeRecord(rec *registry.CommitteeRecord) error { - return c.do(http.MethodPost, routes.PutCommitteeRecord(), model.NewCommitteeRecord(rec), nil) -} - -// GetCommitteeRecord fetches a Record by address -func (c *WaspClient) GetCommitteeRecord(addr ledgerstate.Address) (*registry.CommitteeRecord, error) { - res := &model.CommitteeRecord{} - if err := c.do(http.MethodGet, routes.GetCommitteeRecord(addr.Base58()), nil, res); err != nil { - return nil, err - } - return res.Record(), nil -} - -// GetCommitteeForChain fetches the CommitteeRecord that manages the given chain -func (c *WaspClient) GetCommitteeForChain(chainID *iscp.ChainID) (*registry.CommitteeRecord, error) { - res := &model.CommitteeRecord{} - if err := c.do(http.MethodGet, routes.GetCommitteeForChain(chainID.Base58())+"?includeDeactivated=true", nil, res); err != nil { - return nil, err - } - return res.Record(), nil -} diff --git a/client/goshimmer/goshimmer.go b/client/goshimmer/goshimmer.go index 4ea6ac5df5..8315e974d2 100644 --- a/client/goshimmer/goshimmer.go +++ b/client/goshimmer/goshimmer.go @@ -69,17 +69,49 @@ func (c *Client) GetConfirmedOutputs(address ledgerstate.Address) ([]ledgerstate if err != nil { return nil, fmt.Errorf("GetUnspentOutputs: %w", err) } - ret := make([]ledgerstate.Output, len(r.Outputs)) - for i, out := range r.Outputs { + + // prevent calling c.IsTransactionConfirmed() twice for the same tx + confirmedCache := map[string]bool{} + isConfirmed := func(txID string) (bool, error) { + confirmed, ok := confirmedCache[txID] + if ok { + return confirmed, nil + } + confirmed, err = c.IsTransactionConfirmed(txID) + if err != nil { + return false, err + } + confirmedCache[txID] = confirmed + return confirmed, nil + } + + var ret []ledgerstate.Output + for _, out := range r.Outputs { var err error - ret[i], err = out.ToLedgerstateOutput() + confirmed, err := isConfirmed(out.OutputID.TransactionID) + if err != nil { + return nil, err + } + if !confirmed { + continue + } + output, err := out.ToLedgerstateOutput() if err != nil { return nil, err } + ret = append(ret, output) } return ret, nil } +func (c *Client) IsTransactionConfirmed(txID string) (bool, error) { + r, err := c.api.GetTransactionInclusionState(txID) + if err != nil { + return false, fmt.Errorf("IsTransactionConfirmed: %w", err) + } + return r.Confirmed && !r.Rejected, nil +} + func (c *Client) postTx(tx *ledgerstate.Transaction) error { data := tx.Bytes() if len(data) > parameters.MaxSerializedTransactionToGoshimmer { diff --git a/client/metrics.go b/client/metrics.go index ec241a3a89..6e4804b537 100644 --- a/client/metrics.go +++ b/client/metrics.go @@ -25,3 +25,12 @@ func (c *WaspClient) GetChainNodeConnectionMetrics(chID *iscp.ChainID) (*model.N } return ncmm, nil } + +// GetNodeConnectionMetrics fetches a consensus workflow status by address +func (c *WaspClient) GetChainConsensusWorkflowStatus(chID *iscp.ChainID) (*model.ConsensusWorkflowStatus, error) { + ncmm := &model.ConsensusWorkflowStatus{} + if err := c.do(http.MethodGet, routes.GetChainConsensusWorkflowStatus(chID.Base58()), nil, ncmm); err != nil { + return nil, err + } + return ncmm, nil +} diff --git a/client/multiclient/committee_record.go b/client/multiclient/committee_record.go deleted file mode 100644 index 850c139747..0000000000 --- a/client/multiclient/committee_record.go +++ /dev/null @@ -1,13 +0,0 @@ -package multiclient - -import ( - "github.com/iotaledger/wasp/client" - "github.com/iotaledger/wasp/packages/registry" -) - -// PutChainRecord calls PutChainRecord in all wasp nodes -func (m *MultiClient) PutCommitteeRecord(bd *registry.CommitteeRecord) error { - return m.Do(func(i int, w *client.WaspClient) error { - return w.PutCommitteeRecord(bd) - }) -} diff --git a/client/node_ownership.go b/client/node_ownership.go new file mode 100644 index 0000000000..6cde662c32 --- /dev/null +++ b/client/node_ownership.go @@ -0,0 +1,26 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package client + +import ( + "net/http" + + "github.com/iotaledger/goshimmer/packages/ledgerstate" + "github.com/iotaledger/hive.go/crypto/ed25519" + "github.com/iotaledger/wasp/packages/vm/core/governance" + "github.com/iotaledger/wasp/packages/webapi/model" + "github.com/iotaledger/wasp/packages/webapi/routes" +) + +func (c *WaspClient) NodeOwnershipCertificate(nodePubKey ed25519.PublicKey, ownerAddress ledgerstate.Address) (governance.NodeOwnershipCertificate, error) { + req := model.NodeOwnerCertificateRequest{ + NodePubKey: model.NewBytes(nodePubKey.Bytes()), + OwnerAddress: model.NewAddress(ownerAddress), + } + res := model.NodeOwnerCertificateResponse{} + if err := c.do(http.MethodPost, routes.AdmNodeOwnerCertificate(), req, &res); err != nil { + return nil, err + } + return governance.NewNodeOwnershipCertificateFromBytes(res.Certificate.Bytes()), nil +} diff --git a/config.json b/config.json index c346d1c406..afd7e70510 100644 --- a/config.json +++ b/config.json @@ -41,5 +41,9 @@ }, "nanomsg":{ "port": 5550 + }, + "metrics":{ + "bindAddress": "127.0.0.1:2112", + "enabled": true } } diff --git a/contracts/wasm/README.md b/contracts/wasm/README.md index 962066d3b0..b054cb71c2 100644 --- a/contracts/wasm/README.md +++ b/contracts/wasm/README.md @@ -72,14 +72,14 @@ Prerequisites: [downloaded here](https://rustwasm.github.io/wasm-pack/). Building a Rust smart contract is very simple when using the Rust plugin in any -IntelliJ based development environment. Open the _contracts/rust_ sub folder in +IntelliJ based development environment. Open the _contracts/wasm_ sub folder in your IntelliJ, which then provides you with the Rust workspace. The easiest way to create a new contract is to copy the _helloworld_ folder to a properly named new folder within the _rust_ sub folder. Next, change the fields in the first section of the new folder's _cargo.toml_ file to match your preferences. Make sure the package name equals the folder name. Finally, add the -new folder to the workspace in the _cargo.toml_ in the _contracts/rust_ folder. +new folder to the workspace in the _cargo.toml_ in the _contracts/wasm_ folder. To build the new smart contract select _Run->Edit Configurations_. Add a new configuration based on the _wasmpack_ template, type the _name_ of the new diff --git a/contracts/wasm/core_build.cmd b/contracts/wasm/core_build.cmd index 79d5f2e936..b6c208ba50 100644 --- a/contracts/wasm/core_build.cmd +++ b/contracts/wasm/core_build.cmd @@ -1,6 +1,8 @@ @echo off cd ..\..\packages\vm\wasmlib -schema -core -go -rust -ts -force +schema -core -go -rust -ts -client -force del /s /q d:\work\node_modules\wasmlib\*.* >nul: +del /s /q d:\work\node_modules\wasmclient\*.* >nul: +xcopy /s /q d:\Work\go\github.com\iotaledger\wasp\packages\vm\wasmlib\ts\wasmclient d:\work\node_modules\wasmclient xcopy /s /q d:\Work\go\github.com\iotaledger\wasp\packages\vm\wasmlib\ts\wasmlib d:\work\node_modules\wasmlib cd ..\..\..\contracts\wasm diff --git a/contracts/wasm/dividend/go/dividend/params.go b/contracts/wasm/dividend/go/dividend/params.go index 4306dec638..55d5460569 100644 --- a/contracts/wasm/dividend/go/dividend/params.go +++ b/contracts/wasm/dividend/go/dividend/params.go @@ -30,11 +30,11 @@ type ImmutableMemberParams struct { } func (s ImmutableMemberParams) Address() wasmlib.ScImmutableAddress { - return wasmlib.NewScImmutableAddress(s.id, idxMap[IdxParamAddress]) + return wasmlib.NewScImmutableAddress(s.id, wasmlib.KeyID(ParamAddress)) } func (s ImmutableMemberParams) Factor() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxParamFactor]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamFactor)) } type MutableMemberParams struct { @@ -42,11 +42,11 @@ type MutableMemberParams struct { } func (s MutableMemberParams) Address() wasmlib.ScMutableAddress { - return wasmlib.NewScMutableAddress(s.id, idxMap[IdxParamAddress]) + return wasmlib.NewScMutableAddress(s.id, wasmlib.KeyID(ParamAddress)) } func (s MutableMemberParams) Factor() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxParamFactor]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamFactor)) } type ImmutableSetOwnerParams struct { @@ -54,7 +54,7 @@ type ImmutableSetOwnerParams struct { } func (s ImmutableSetOwnerParams) Owner() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamOwner]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamOwner)) } type MutableSetOwnerParams struct { @@ -62,7 +62,7 @@ type MutableSetOwnerParams struct { } func (s MutableSetOwnerParams) Owner() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamOwner]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamOwner)) } type ImmutableGetFactorParams struct { @@ -70,7 +70,7 @@ type ImmutableGetFactorParams struct { } func (s ImmutableGetFactorParams) Address() wasmlib.ScImmutableAddress { - return wasmlib.NewScImmutableAddress(s.id, idxMap[IdxParamAddress]) + return wasmlib.NewScImmutableAddress(s.id, wasmlib.KeyID(ParamAddress)) } type MutableGetFactorParams struct { @@ -78,5 +78,5 @@ type MutableGetFactorParams struct { } func (s MutableGetFactorParams) Address() wasmlib.ScMutableAddress { - return wasmlib.NewScMutableAddress(s.id, idxMap[IdxParamAddress]) + return wasmlib.NewScMutableAddress(s.id, wasmlib.KeyID(ParamAddress)) } diff --git a/contracts/wasm/dividend/go/dividend/results.go b/contracts/wasm/dividend/go/dividend/results.go index 1e4f12e3ed..987b0fec57 100644 --- a/contracts/wasm/dividend/go/dividend/results.go +++ b/contracts/wasm/dividend/go/dividend/results.go @@ -14,7 +14,7 @@ type ImmutableGetFactorResults struct { } func (s ImmutableGetFactorResults) Factor() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultFactor]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultFactor)) } type MutableGetFactorResults struct { @@ -22,7 +22,7 @@ type MutableGetFactorResults struct { } func (s MutableGetFactorResults) Factor() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultFactor]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultFactor)) } type ImmutableGetOwnerResults struct { @@ -30,7 +30,7 @@ type ImmutableGetOwnerResults struct { } func (s ImmutableGetOwnerResults) Owner() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxResultOwner]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ResultOwner)) } type MutableGetOwnerResults struct { @@ -38,5 +38,5 @@ type MutableGetOwnerResults struct { } func (s MutableGetOwnerResults) Owner() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxResultOwner]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ResultOwner)) } diff --git a/contracts/wasm/dividend/go/dividend/state.go b/contracts/wasm/dividend/go/dividend/state.go index 91571d4443..b63408d3a3 100644 --- a/contracts/wasm/dividend/go/dividend/state.go +++ b/contracts/wasm/dividend/go/dividend/state.go @@ -34,21 +34,21 @@ type ImmutableDividendState struct { } func (s ImmutableDividendState) MemberList() ArrayOfImmutableAddress { - arrID := wasmlib.GetObjectID(s.id, idxMap[IdxStateMemberList], wasmlib.TYPE_ARRAY|wasmlib.TYPE_ADDRESS) + arrID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateMemberList), wasmlib.TYPE_ARRAY|wasmlib.TYPE_ADDRESS) return ArrayOfImmutableAddress{objID: arrID} } func (s ImmutableDividendState) Members() MapAddressToImmutableInt64 { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateMembers], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateMembers), wasmlib.TYPE_MAP) return MapAddressToImmutableInt64{objID: mapID} } func (s ImmutableDividendState) Owner() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxStateOwner]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(StateOwner)) } func (s ImmutableDividendState) TotalFactor() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxStateTotalFactor]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(StateTotalFactor)) } type ArrayOfMutableAddress struct { @@ -83,20 +83,24 @@ type MutableDividendState struct { id int32 } +func (s MutableDividendState) AsImmutable() ImmutableDividendState { + return ImmutableDividendState(s) +} + func (s MutableDividendState) MemberList() ArrayOfMutableAddress { - arrID := wasmlib.GetObjectID(s.id, idxMap[IdxStateMemberList], wasmlib.TYPE_ARRAY|wasmlib.TYPE_ADDRESS) + arrID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateMemberList), wasmlib.TYPE_ARRAY|wasmlib.TYPE_ADDRESS) return ArrayOfMutableAddress{objID: arrID} } func (s MutableDividendState) Members() MapAddressToMutableInt64 { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateMembers], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateMembers), wasmlib.TYPE_MAP) return MapAddressToMutableInt64{objID: mapID} } func (s MutableDividendState) Owner() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxStateOwner]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(StateOwner)) } func (s MutableDividendState) TotalFactor() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxStateTotalFactor]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(StateTotalFactor)) } diff --git a/contracts/wasm/dividend/go/main.go b/contracts/wasm/dividend/go/main.go index 13ca6f38f9..2b86f655a4 100644 --- a/contracts/wasm/dividend/go/main.go +++ b/contracts/wasm/dividend/go/main.go @@ -9,7 +9,7 @@ package main -import "github.com/iotaledger/wasp/packages/vm/wasmclient" +import "github.com/iotaledger/wasp/packages/vm/wasmvmhost" import "github.com/iotaledger/wasp/contracts/wasm/dividend/go/dividend" @@ -18,7 +18,7 @@ func main() { //export on_load func onLoad() { - h := &wasmclient.WasmVMHost{} + h := &wasmvmhost.WasmVMHost{} h.ConnectWasmHost() dividend.OnLoad() } diff --git a/contracts/wasm/dividend/src/params.rs b/contracts/wasm/dividend/src/params.rs index a8ddbef09f..abea99eece 100644 --- a/contracts/wasm/dividend/src/params.rs +++ b/contracts/wasm/dividend/src/params.rs @@ -43,11 +43,11 @@ pub struct ImmutableMemberParams { impl ImmutableMemberParams { pub fn address(&self) -> ScImmutableAddress { - ScImmutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) + ScImmutableAddress::new(self.id, PARAM_ADDRESS.get_key_id()) } pub fn factor(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_FACTOR)) + ScImmutableInt64::new(self.id, PARAM_FACTOR.get_key_id()) } } @@ -58,11 +58,11 @@ pub struct MutableMemberParams { impl MutableMemberParams { pub fn address(&self) -> ScMutableAddress { - ScMutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) + ScMutableAddress::new(self.id, PARAM_ADDRESS.get_key_id()) } pub fn factor(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_FACTOR)) + ScMutableInt64::new(self.id, PARAM_FACTOR.get_key_id()) } } @@ -73,7 +73,7 @@ pub struct ImmutableSetOwnerParams { impl ImmutableSetOwnerParams { pub fn owner(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_OWNER)) + ScImmutableAgentID::new(self.id, PARAM_OWNER.get_key_id()) } } @@ -84,7 +84,7 @@ pub struct MutableSetOwnerParams { impl MutableSetOwnerParams { pub fn owner(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_OWNER)) + ScMutableAgentID::new(self.id, PARAM_OWNER.get_key_id()) } } @@ -95,7 +95,7 @@ pub struct ImmutableGetFactorParams { impl ImmutableGetFactorParams { pub fn address(&self) -> ScImmutableAddress { - ScImmutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) + ScImmutableAddress::new(self.id, PARAM_ADDRESS.get_key_id()) } } @@ -106,6 +106,6 @@ pub struct MutableGetFactorParams { impl MutableGetFactorParams { pub fn address(&self) -> ScMutableAddress { - ScMutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) + ScMutableAddress::new(self.id, PARAM_ADDRESS.get_key_id()) } } diff --git a/contracts/wasm/dividend/src/results.rs b/contracts/wasm/dividend/src/results.rs index 373e293a53..9e6680e864 100644 --- a/contracts/wasm/dividend/src/results.rs +++ b/contracts/wasm/dividend/src/results.rs @@ -21,7 +21,7 @@ pub struct ImmutableGetFactorResults { impl ImmutableGetFactorResults { pub fn factor(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_FACTOR)) + ScImmutableInt64::new(self.id, RESULT_FACTOR.get_key_id()) } } @@ -32,7 +32,7 @@ pub struct MutableGetFactorResults { impl MutableGetFactorResults { pub fn factor(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_FACTOR)) + ScMutableInt64::new(self.id, RESULT_FACTOR.get_key_id()) } } @@ -43,7 +43,7 @@ pub struct ImmutableGetOwnerResults { impl ImmutableGetOwnerResults { pub fn owner(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_RESULT_OWNER)) + ScImmutableAgentID::new(self.id, RESULT_OWNER.get_key_id()) } } @@ -54,6 +54,6 @@ pub struct MutableGetOwnerResults { impl MutableGetOwnerResults { pub fn owner(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_RESULT_OWNER)) + ScMutableAgentID::new(self.id, RESULT_OWNER.get_key_id()) } } diff --git a/contracts/wasm/dividend/src/state.rs b/contracts/wasm/dividend/src/state.rs index 1181e0fd48..4cb5424635 100644 --- a/contracts/wasm/dividend/src/state.rs +++ b/contracts/wasm/dividend/src/state.rs @@ -14,6 +14,7 @@ use wasmlib::host::*; use crate::*; use crate::keys::*; +#[derive(Clone, Copy)] pub struct ArrayOfImmutableAddress { pub(crate) obj_id: i32, } @@ -28,6 +29,7 @@ impl ArrayOfImmutableAddress { } } +#[derive(Clone, Copy)] pub struct MapAddressToImmutableInt64 { pub(crate) obj_id: i32, } @@ -45,24 +47,25 @@ pub struct ImmutableDividendState { impl ImmutableDividendState { pub fn member_list(&self) -> ArrayOfImmutableAddress { - let arr_id = get_object_id(self.id, idx_map(IDX_STATE_MEMBER_LIST), TYPE_ARRAY | TYPE_ADDRESS); + let arr_id = get_object_id(self.id, STATE_MEMBER_LIST.get_key_id(), TYPE_ARRAY | TYPE_ADDRESS); ArrayOfImmutableAddress { obj_id: arr_id } } pub fn members(&self) -> MapAddressToImmutableInt64 { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_MEMBERS), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_MEMBERS.get_key_id(), TYPE_MAP); MapAddressToImmutableInt64 { obj_id: map_id } } pub fn owner(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_STATE_OWNER)) + ScImmutableAgentID::new(self.id, STATE_OWNER.get_key_id()) } pub fn total_factor(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_STATE_TOTAL_FACTOR)) + ScImmutableInt64::new(self.id, STATE_TOTAL_FACTOR.get_key_id()) } } +#[derive(Clone, Copy)] pub struct ArrayOfMutableAddress { pub(crate) obj_id: i32, } @@ -81,6 +84,7 @@ impl ArrayOfMutableAddress { } } +#[derive(Clone, Copy)] pub struct MapAddressToMutableInt64 { pub(crate) obj_id: i32, } @@ -101,21 +105,25 @@ pub struct MutableDividendState { } impl MutableDividendState { + pub fn as_immutable(&self) -> ImmutableDividendState { + ImmutableDividendState { id: self.id } + } + pub fn member_list(&self) -> ArrayOfMutableAddress { - let arr_id = get_object_id(self.id, idx_map(IDX_STATE_MEMBER_LIST), TYPE_ARRAY | TYPE_ADDRESS); + let arr_id = get_object_id(self.id, STATE_MEMBER_LIST.get_key_id(), TYPE_ARRAY | TYPE_ADDRESS); ArrayOfMutableAddress { obj_id: arr_id } } pub fn members(&self) -> MapAddressToMutableInt64 { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_MEMBERS), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_MEMBERS.get_key_id(), TYPE_MAP); MapAddressToMutableInt64 { obj_id: map_id } } pub fn owner(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_STATE_OWNER)) + ScMutableAgentID::new(self.id, STATE_OWNER.get_key_id()) } pub fn total_factor(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_STATE_TOTAL_FACTOR)) + ScMutableInt64::new(self.id, STATE_TOTAL_FACTOR.get_key_id()) } } diff --git a/contracts/wasm/dividend/test/dividend_bg.wasm b/contracts/wasm/dividend/test/dividend_bg.wasm index b80b9d3f38..d7848e5e3c 100644 Binary files a/contracts/wasm/dividend/test/dividend_bg.wasm and b/contracts/wasm/dividend/test/dividend_bg.wasm differ diff --git a/contracts/wasm/dividend/ts/dividend/params.ts b/contracts/wasm/dividend/ts/dividend/params.ts index 9182269073..7186afa1ec 100644 --- a/contracts/wasm/dividend/ts/dividend/params.ts +++ b/contracts/wasm/dividend/ts/dividend/params.ts @@ -22,44 +22,44 @@ export class MutableInitParams extends wasmlib.ScMapID { export class ImmutableMemberParams extends wasmlib.ScMapID { address(): wasmlib.ScImmutableAddress { - return new wasmlib.ScImmutableAddress(this.mapID, sc.idxMap[sc.IdxParamAddress]); + return new wasmlib.ScImmutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamAddress)); } factor(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamFactor]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamFactor)); } } export class MutableMemberParams extends wasmlib.ScMapID { address(): wasmlib.ScMutableAddress { - return new wasmlib.ScMutableAddress(this.mapID, sc.idxMap[sc.IdxParamAddress]); + return new wasmlib.ScMutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamAddress)); } factor(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamFactor]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamFactor)); } } export class ImmutableSetOwnerParams extends wasmlib.ScMapID { owner(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamOwner]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamOwner)); } } export class MutableSetOwnerParams extends wasmlib.ScMapID { owner(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamOwner]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamOwner)); } } export class ImmutableGetFactorParams extends wasmlib.ScMapID { address(): wasmlib.ScImmutableAddress { - return new wasmlib.ScImmutableAddress(this.mapID, sc.idxMap[sc.IdxParamAddress]); + return new wasmlib.ScImmutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamAddress)); } } export class MutableGetFactorParams extends wasmlib.ScMapID { address(): wasmlib.ScMutableAddress { - return new wasmlib.ScMutableAddress(this.mapID, sc.idxMap[sc.IdxParamAddress]); + return new wasmlib.ScMutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamAddress)); } } diff --git a/contracts/wasm/dividend/ts/dividend/results.ts b/contracts/wasm/dividend/ts/dividend/results.ts index 3bac84f77e..bf8821b726 100644 --- a/contracts/wasm/dividend/ts/dividend/results.ts +++ b/contracts/wasm/dividend/ts/dividend/results.ts @@ -10,24 +10,24 @@ import * as sc from "./index"; export class ImmutableGetFactorResults extends wasmlib.ScMapID { factor(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultFactor]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultFactor)); } } export class MutableGetFactorResults extends wasmlib.ScMapID { factor(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultFactor]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultFactor)); } } export class ImmutableGetOwnerResults extends wasmlib.ScMapID { owner(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxResultOwner]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ResultOwner)); } } export class MutableGetOwnerResults extends wasmlib.ScMapID { owner(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxResultOwner]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ResultOwner)); } } diff --git a/contracts/wasm/dividend/ts/dividend/state.ts b/contracts/wasm/dividend/ts/dividend/state.ts index b7a24f7015..0bd4aed4b3 100644 --- a/contracts/wasm/dividend/ts/dividend/state.ts +++ b/contracts/wasm/dividend/ts/dividend/state.ts @@ -38,21 +38,21 @@ export class MapAddressToImmutableInt64 { export class ImmutableDividendState extends wasmlib.ScMapID { memberList(): sc.ArrayOfImmutableAddress { - let arrID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateMemberList], wasmlib.TYPE_ARRAY|wasmlib.TYPE_ADDRESS); + let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateMemberList), wasmlib.TYPE_ARRAY|wasmlib.TYPE_ADDRESS); return new sc.ArrayOfImmutableAddress(arrID); } members(): sc.MapAddressToImmutableInt64 { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateMembers], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateMembers), wasmlib.TYPE_MAP); return new sc.MapAddressToImmutableInt64(mapID); } owner(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxStateOwner]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.StateOwner)); } totalFactor(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateTotalFactor]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateTotalFactor)); } } @@ -93,21 +93,27 @@ export class MapAddressToMutableInt64 { } export class MutableDividendState extends wasmlib.ScMapID { + asImmutable(): sc.ImmutableDividendState { + const imm = new sc.ImmutableDividendState(); + imm.mapID = this.mapID; + return imm; + } + memberList(): sc.ArrayOfMutableAddress { - let arrID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateMemberList], wasmlib.TYPE_ARRAY|wasmlib.TYPE_ADDRESS); + let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateMemberList), wasmlib.TYPE_ARRAY|wasmlib.TYPE_ADDRESS); return new sc.ArrayOfMutableAddress(arrID); } members(): sc.MapAddressToMutableInt64 { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateMembers], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateMembers), wasmlib.TYPE_MAP); return new sc.MapAddressToMutableInt64(mapID); } owner(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxStateOwner]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.StateOwner)); } totalFactor(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateTotalFactor]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateTotalFactor)); } } diff --git a/contracts/wasm/donatewithfeedback/go/donatewithfeedback/params.go b/contracts/wasm/donatewithfeedback/go/donatewithfeedback/params.go index 299c6dc2d4..caa10267bc 100644 --- a/contracts/wasm/donatewithfeedback/go/donatewithfeedback/params.go +++ b/contracts/wasm/donatewithfeedback/go/donatewithfeedback/params.go @@ -14,7 +14,7 @@ type ImmutableDonateParams struct { } func (s ImmutableDonateParams) Feedback() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxParamFeedback]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamFeedback)) } type MutableDonateParams struct { @@ -22,7 +22,7 @@ type MutableDonateParams struct { } func (s MutableDonateParams) Feedback() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxParamFeedback]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamFeedback)) } type ImmutableWithdrawParams struct { @@ -30,7 +30,7 @@ type ImmutableWithdrawParams struct { } func (s ImmutableWithdrawParams) Amount() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxParamAmount]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamAmount)) } type MutableWithdrawParams struct { @@ -38,7 +38,7 @@ type MutableWithdrawParams struct { } func (s MutableWithdrawParams) Amount() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxParamAmount]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamAmount)) } type ImmutableDonationParams struct { @@ -46,7 +46,7 @@ type ImmutableDonationParams struct { } func (s ImmutableDonationParams) Nr() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxParamNr]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamNr)) } type MutableDonationParams struct { @@ -54,5 +54,5 @@ type MutableDonationParams struct { } func (s MutableDonationParams) Nr() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxParamNr]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamNr)) } diff --git a/contracts/wasm/donatewithfeedback/go/donatewithfeedback/results.go b/contracts/wasm/donatewithfeedback/go/donatewithfeedback/results.go index 89abd2c897..85fa71ca2c 100644 --- a/contracts/wasm/donatewithfeedback/go/donatewithfeedback/results.go +++ b/contracts/wasm/donatewithfeedback/go/donatewithfeedback/results.go @@ -14,23 +14,23 @@ type ImmutableDonationResults struct { } func (s ImmutableDonationResults) Amount() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultAmount]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultAmount)) } func (s ImmutableDonationResults) Donator() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxResultDonator]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ResultDonator)) } func (s ImmutableDonationResults) Error() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxResultError]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ResultError)) } func (s ImmutableDonationResults) Feedback() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxResultFeedback]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ResultFeedback)) } func (s ImmutableDonationResults) Timestamp() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultTimestamp]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultTimestamp)) } type MutableDonationResults struct { @@ -38,23 +38,23 @@ type MutableDonationResults struct { } func (s MutableDonationResults) Amount() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultAmount]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultAmount)) } func (s MutableDonationResults) Donator() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxResultDonator]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ResultDonator)) } func (s MutableDonationResults) Error() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxResultError]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ResultError)) } func (s MutableDonationResults) Feedback() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxResultFeedback]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ResultFeedback)) } func (s MutableDonationResults) Timestamp() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultTimestamp]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultTimestamp)) } type ImmutableDonationInfoResults struct { @@ -62,15 +62,15 @@ type ImmutableDonationInfoResults struct { } func (s ImmutableDonationInfoResults) Count() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultCount]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultCount)) } func (s ImmutableDonationInfoResults) MaxDonation() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultMaxDonation]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultMaxDonation)) } func (s ImmutableDonationInfoResults) TotalDonation() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultTotalDonation]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultTotalDonation)) } type MutableDonationInfoResults struct { @@ -78,13 +78,13 @@ type MutableDonationInfoResults struct { } func (s MutableDonationInfoResults) Count() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultCount]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultCount)) } func (s MutableDonationInfoResults) MaxDonation() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultMaxDonation]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultMaxDonation)) } func (s MutableDonationInfoResults) TotalDonation() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultTotalDonation]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultTotalDonation)) } diff --git a/contracts/wasm/donatewithfeedback/go/donatewithfeedback/state.go b/contracts/wasm/donatewithfeedback/go/donatewithfeedback/state.go index 9cb723cdac..c74fcc94c1 100644 --- a/contracts/wasm/donatewithfeedback/go/donatewithfeedback/state.go +++ b/contracts/wasm/donatewithfeedback/go/donatewithfeedback/state.go @@ -26,16 +26,16 @@ type ImmutableDonateWithFeedbackState struct { } func (s ImmutableDonateWithFeedbackState) Log() ArrayOfImmutableDonation { - arrID := wasmlib.GetObjectID(s.id, idxMap[IdxStateLog], wasmlib.TYPE_ARRAY|wasmlib.TYPE_BYTES) + arrID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateLog), wasmlib.TYPE_ARRAY|wasmlib.TYPE_BYTES) return ArrayOfImmutableDonation{objID: arrID} } func (s ImmutableDonateWithFeedbackState) MaxDonation() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxStateMaxDonation]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(StateMaxDonation)) } func (s ImmutableDonateWithFeedbackState) TotalDonation() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxStateTotalDonation]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(StateTotalDonation)) } type ArrayOfMutableDonation struct { @@ -58,15 +58,19 @@ type MutableDonateWithFeedbackState struct { id int32 } +func (s MutableDonateWithFeedbackState) AsImmutable() ImmutableDonateWithFeedbackState { + return ImmutableDonateWithFeedbackState(s) +} + func (s MutableDonateWithFeedbackState) Log() ArrayOfMutableDonation { - arrID := wasmlib.GetObjectID(s.id, idxMap[IdxStateLog], wasmlib.TYPE_ARRAY|wasmlib.TYPE_BYTES) + arrID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateLog), wasmlib.TYPE_ARRAY|wasmlib.TYPE_BYTES) return ArrayOfMutableDonation{objID: arrID} } func (s MutableDonateWithFeedbackState) MaxDonation() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxStateMaxDonation]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(StateMaxDonation)) } func (s MutableDonateWithFeedbackState) TotalDonation() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxStateTotalDonation]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(StateTotalDonation)) } diff --git a/contracts/wasm/donatewithfeedback/go/main.go b/contracts/wasm/donatewithfeedback/go/main.go index a2260be5b6..a263164081 100644 --- a/contracts/wasm/donatewithfeedback/go/main.go +++ b/contracts/wasm/donatewithfeedback/go/main.go @@ -9,7 +9,7 @@ package main -import "github.com/iotaledger/wasp/packages/vm/wasmclient" +import "github.com/iotaledger/wasp/packages/vm/wasmvmhost" import "github.com/iotaledger/wasp/contracts/wasm/donatewithfeedback/go/donatewithfeedback" @@ -18,7 +18,7 @@ func main() { //export on_load func onLoad() { - h := &wasmclient.WasmVMHost{} + h := &wasmvmhost.WasmVMHost{} h.ConnectWasmHost() donatewithfeedback.OnLoad() } diff --git a/contracts/wasm/donatewithfeedback/src/params.rs b/contracts/wasm/donatewithfeedback/src/params.rs index 44fa12eb5b..9352539ea7 100644 --- a/contracts/wasm/donatewithfeedback/src/params.rs +++ b/contracts/wasm/donatewithfeedback/src/params.rs @@ -22,7 +22,7 @@ pub struct ImmutableDonateParams { impl ImmutableDonateParams { pub fn feedback(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_FEEDBACK)) + ScImmutableString::new(self.id, PARAM_FEEDBACK.get_key_id()) } } @@ -33,7 +33,7 @@ pub struct MutableDonateParams { impl MutableDonateParams { pub fn feedback(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_FEEDBACK)) + ScMutableString::new(self.id, PARAM_FEEDBACK.get_key_id()) } } @@ -44,7 +44,7 @@ pub struct ImmutableWithdrawParams { impl ImmutableWithdrawParams { pub fn amount(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) + ScImmutableInt64::new(self.id, PARAM_AMOUNT.get_key_id()) } } @@ -55,7 +55,7 @@ pub struct MutableWithdrawParams { impl MutableWithdrawParams { pub fn amount(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) + ScMutableInt64::new(self.id, PARAM_AMOUNT.get_key_id()) } } @@ -66,7 +66,7 @@ pub struct ImmutableDonationParams { impl ImmutableDonationParams { pub fn nr(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_NR)) + ScImmutableInt64::new(self.id, PARAM_NR.get_key_id()) } } @@ -77,6 +77,6 @@ pub struct MutableDonationParams { impl MutableDonationParams { pub fn nr(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_NR)) + ScMutableInt64::new(self.id, PARAM_NR.get_key_id()) } } diff --git a/contracts/wasm/donatewithfeedback/src/results.rs b/contracts/wasm/donatewithfeedback/src/results.rs index 6d3b0ad322..22e641f04f 100644 --- a/contracts/wasm/donatewithfeedback/src/results.rs +++ b/contracts/wasm/donatewithfeedback/src/results.rs @@ -22,23 +22,23 @@ pub struct ImmutableDonationResults { impl ImmutableDonationResults { pub fn amount(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_AMOUNT)) + ScImmutableInt64::new(self.id, RESULT_AMOUNT.get_key_id()) } pub fn donator(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_RESULT_DONATOR)) + ScImmutableAgentID::new(self.id, RESULT_DONATOR.get_key_id()) } pub fn error(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_RESULT_ERROR)) + ScImmutableString::new(self.id, RESULT_ERROR.get_key_id()) } pub fn feedback(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_RESULT_FEEDBACK)) + ScImmutableString::new(self.id, RESULT_FEEDBACK.get_key_id()) } pub fn timestamp(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_TIMESTAMP)) + ScImmutableInt64::new(self.id, RESULT_TIMESTAMP.get_key_id()) } } @@ -49,23 +49,23 @@ pub struct MutableDonationResults { impl MutableDonationResults { pub fn amount(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_AMOUNT)) + ScMutableInt64::new(self.id, RESULT_AMOUNT.get_key_id()) } pub fn donator(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_RESULT_DONATOR)) + ScMutableAgentID::new(self.id, RESULT_DONATOR.get_key_id()) } pub fn error(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_RESULT_ERROR)) + ScMutableString::new(self.id, RESULT_ERROR.get_key_id()) } pub fn feedback(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_RESULT_FEEDBACK)) + ScMutableString::new(self.id, RESULT_FEEDBACK.get_key_id()) } pub fn timestamp(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_TIMESTAMP)) + ScMutableInt64::new(self.id, RESULT_TIMESTAMP.get_key_id()) } } @@ -76,15 +76,15 @@ pub struct ImmutableDonationInfoResults { impl ImmutableDonationInfoResults { pub fn count(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_COUNT)) + ScImmutableInt64::new(self.id, RESULT_COUNT.get_key_id()) } pub fn max_donation(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_MAX_DONATION)) + ScImmutableInt64::new(self.id, RESULT_MAX_DONATION.get_key_id()) } pub fn total_donation(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_TOTAL_DONATION)) + ScImmutableInt64::new(self.id, RESULT_TOTAL_DONATION.get_key_id()) } } @@ -95,14 +95,14 @@ pub struct MutableDonationInfoResults { impl MutableDonationInfoResults { pub fn count(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_COUNT)) + ScMutableInt64::new(self.id, RESULT_COUNT.get_key_id()) } pub fn max_donation(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_MAX_DONATION)) + ScMutableInt64::new(self.id, RESULT_MAX_DONATION.get_key_id()) } pub fn total_donation(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_TOTAL_DONATION)) + ScMutableInt64::new(self.id, RESULT_TOTAL_DONATION.get_key_id()) } } diff --git a/contracts/wasm/donatewithfeedback/src/state.rs b/contracts/wasm/donatewithfeedback/src/state.rs index 9fc1c32e0f..5f8dc08729 100644 --- a/contracts/wasm/donatewithfeedback/src/state.rs +++ b/contracts/wasm/donatewithfeedback/src/state.rs @@ -15,6 +15,7 @@ use crate::*; use crate::keys::*; use crate::structs::*; +#[derive(Clone, Copy)] pub struct ArrayOfImmutableDonation { pub(crate) obj_id: i32, } @@ -36,19 +37,20 @@ pub struct ImmutableDonateWithFeedbackState { impl ImmutableDonateWithFeedbackState { pub fn log(&self) -> ArrayOfImmutableDonation { - let arr_id = get_object_id(self.id, idx_map(IDX_STATE_LOG), TYPE_ARRAY | TYPE_BYTES); + let arr_id = get_object_id(self.id, STATE_LOG.get_key_id(), TYPE_ARRAY | TYPE_BYTES); ArrayOfImmutableDonation { obj_id: arr_id } } pub fn max_donation(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_STATE_MAX_DONATION)) + ScImmutableInt64::new(self.id, STATE_MAX_DONATION.get_key_id()) } pub fn total_donation(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_STATE_TOTAL_DONATION)) + ScImmutableInt64::new(self.id, STATE_TOTAL_DONATION.get_key_id()) } } +#[derive(Clone, Copy)] pub struct ArrayOfMutableDonation { pub(crate) obj_id: i32, } @@ -73,16 +75,20 @@ pub struct MutableDonateWithFeedbackState { } impl MutableDonateWithFeedbackState { + pub fn as_immutable(&self) -> ImmutableDonateWithFeedbackState { + ImmutableDonateWithFeedbackState { id: self.id } + } + pub fn log(&self) -> ArrayOfMutableDonation { - let arr_id = get_object_id(self.id, idx_map(IDX_STATE_LOG), TYPE_ARRAY | TYPE_BYTES); + let arr_id = get_object_id(self.id, STATE_LOG.get_key_id(), TYPE_ARRAY | TYPE_BYTES); ArrayOfMutableDonation { obj_id: arr_id } } pub fn max_donation(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_STATE_MAX_DONATION)) + ScMutableInt64::new(self.id, STATE_MAX_DONATION.get_key_id()) } pub fn total_donation(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_STATE_TOTAL_DONATION)) + ScMutableInt64::new(self.id, STATE_TOTAL_DONATION.get_key_id()) } } diff --git a/contracts/wasm/donatewithfeedback/src/structs.rs b/contracts/wasm/donatewithfeedback/src/structs.rs index 8a15175075..b1ebbda1da 100644 --- a/contracts/wasm/donatewithfeedback/src/structs.rs +++ b/contracts/wasm/donatewithfeedback/src/structs.rs @@ -11,6 +11,7 @@ use wasmlib::*; use wasmlib::host::*; +#[derive(Clone)] pub struct Donation { pub amount : i64, // amount donated pub donator : ScAgentID, // who donated @@ -42,6 +43,7 @@ impl Donation { } } +#[derive(Clone, Copy)] pub struct ImmutableDonation { pub(crate) obj_id: i32, pub(crate) key_id: Key32, @@ -57,6 +59,7 @@ impl ImmutableDonation { } } +#[derive(Clone, Copy)] pub struct MutableDonation { pub(crate) obj_id: i32, pub(crate) key_id: Key32, diff --git a/contracts/wasm/donatewithfeedback/test/donatewithfeedback_bg.wasm b/contracts/wasm/donatewithfeedback/test/donatewithfeedback_bg.wasm index 7f50ea8a95..742ef0a8bc 100644 Binary files a/contracts/wasm/donatewithfeedback/test/donatewithfeedback_bg.wasm and b/contracts/wasm/donatewithfeedback/test/donatewithfeedback_bg.wasm differ diff --git a/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/params.ts b/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/params.ts index 81558202a8..6e57022c41 100644 --- a/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/params.ts +++ b/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/params.ts @@ -10,36 +10,36 @@ import * as sc from "./index"; export class ImmutableDonateParams extends wasmlib.ScMapID { feedback(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamFeedback]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamFeedback)); } } export class MutableDonateParams extends wasmlib.ScMapID { feedback(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamFeedback]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamFeedback)); } } export class ImmutableWithdrawParams extends wasmlib.ScMapID { amount(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamAmount]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamAmount)); } } export class MutableWithdrawParams extends wasmlib.ScMapID { amount(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamAmount]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamAmount)); } } export class ImmutableDonationParams extends wasmlib.ScMapID { nr(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamNr]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamNr)); } } export class MutableDonationParams extends wasmlib.ScMapID { nr(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamNr]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamNr)); } } diff --git a/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/results.ts b/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/results.ts index 2d9329bd9d..308ef3d0b7 100644 --- a/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/results.ts +++ b/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/results.ts @@ -10,72 +10,72 @@ import * as sc from "./index"; export class ImmutableDonationResults extends wasmlib.ScMapID { amount(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultAmount]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultAmount)); } donator(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxResultDonator]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ResultDonator)); } error(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxResultError]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultError)); } feedback(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxResultFeedback]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultFeedback)); } timestamp(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultTimestamp]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultTimestamp)); } } export class MutableDonationResults extends wasmlib.ScMapID { amount(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultAmount]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultAmount)); } donator(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxResultDonator]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ResultDonator)); } error(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxResultError]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultError)); } feedback(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxResultFeedback]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultFeedback)); } timestamp(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultTimestamp]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultTimestamp)); } } export class ImmutableDonationInfoResults extends wasmlib.ScMapID { count(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultCount]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultCount)); } maxDonation(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultMaxDonation]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultMaxDonation)); } totalDonation(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultTotalDonation]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultTotalDonation)); } } export class MutableDonationInfoResults extends wasmlib.ScMapID { count(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultCount]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultCount)); } maxDonation(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultMaxDonation]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultMaxDonation)); } totalDonation(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultTotalDonation]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultTotalDonation)); } } diff --git a/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/state.ts b/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/state.ts index 0a946bfcf1..50b1f395d0 100644 --- a/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/state.ts +++ b/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/state.ts @@ -26,16 +26,16 @@ export class ArrayOfImmutableDonation { export class ImmutableDonateWithFeedbackState extends wasmlib.ScMapID { log(): sc.ArrayOfImmutableDonation { - let arrID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateLog], wasmlib.TYPE_ARRAY|wasmlib.TYPE_BYTES); + let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateLog), wasmlib.TYPE_ARRAY|wasmlib.TYPE_BYTES); return new sc.ArrayOfImmutableDonation(arrID); } maxDonation(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateMaxDonation]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateMaxDonation)); } totalDonation(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateTotalDonation]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateTotalDonation)); } } @@ -60,16 +60,22 @@ export class ArrayOfMutableDonation { } export class MutableDonateWithFeedbackState extends wasmlib.ScMapID { + asImmutable(): sc.ImmutableDonateWithFeedbackState { + const imm = new sc.ImmutableDonateWithFeedbackState(); + imm.mapID = this.mapID; + return imm; + } + log(): sc.ArrayOfMutableDonation { - let arrID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateLog], wasmlib.TYPE_ARRAY|wasmlib.TYPE_BYTES); + let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateLog), wasmlib.TYPE_ARRAY|wasmlib.TYPE_BYTES); return new sc.ArrayOfMutableDonation(arrID); } maxDonation(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateMaxDonation]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateMaxDonation)); } totalDonation(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateTotalDonation]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateTotalDonation)); } } diff --git a/contracts/wasm/erc20/go/erc20/params.go b/contracts/wasm/erc20/go/erc20/params.go index b91f061931..2a1edfa0b7 100644 --- a/contracts/wasm/erc20/go/erc20/params.go +++ b/contracts/wasm/erc20/go/erc20/params.go @@ -14,11 +14,11 @@ type ImmutableApproveParams struct { } func (s ImmutableApproveParams) Amount() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxParamAmount]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamAmount)) } func (s ImmutableApproveParams) Delegation() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamDelegation]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamDelegation)) } type MutableApproveParams struct { @@ -26,11 +26,11 @@ type MutableApproveParams struct { } func (s MutableApproveParams) Amount() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxParamAmount]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamAmount)) } func (s MutableApproveParams) Delegation() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamDelegation]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamDelegation)) } type ImmutableInitParams struct { @@ -62,11 +62,11 @@ type ImmutableTransferParams struct { } func (s ImmutableTransferParams) Account() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamAccount]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamAccount)) } func (s ImmutableTransferParams) Amount() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxParamAmount]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamAmount)) } type MutableTransferParams struct { @@ -74,11 +74,11 @@ type MutableTransferParams struct { } func (s MutableTransferParams) Account() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamAccount]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamAccount)) } func (s MutableTransferParams) Amount() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxParamAmount]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamAmount)) } type ImmutableTransferFromParams struct { @@ -86,15 +86,15 @@ type ImmutableTransferFromParams struct { } func (s ImmutableTransferFromParams) Account() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamAccount]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamAccount)) } func (s ImmutableTransferFromParams) Amount() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxParamAmount]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamAmount)) } func (s ImmutableTransferFromParams) Recipient() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamRecipient]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamRecipient)) } type MutableTransferFromParams struct { @@ -102,15 +102,15 @@ type MutableTransferFromParams struct { } func (s MutableTransferFromParams) Account() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamAccount]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamAccount)) } func (s MutableTransferFromParams) Amount() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxParamAmount]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamAmount)) } func (s MutableTransferFromParams) Recipient() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamRecipient]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamRecipient)) } type ImmutableAllowanceParams struct { @@ -118,11 +118,11 @@ type ImmutableAllowanceParams struct { } func (s ImmutableAllowanceParams) Account() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamAccount]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamAccount)) } func (s ImmutableAllowanceParams) Delegation() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamDelegation]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamDelegation)) } type MutableAllowanceParams struct { @@ -130,11 +130,11 @@ type MutableAllowanceParams struct { } func (s MutableAllowanceParams) Account() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamAccount]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamAccount)) } func (s MutableAllowanceParams) Delegation() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamDelegation]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamDelegation)) } type ImmutableBalanceOfParams struct { @@ -142,7 +142,7 @@ type ImmutableBalanceOfParams struct { } func (s ImmutableBalanceOfParams) Account() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamAccount]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamAccount)) } type MutableBalanceOfParams struct { @@ -150,5 +150,5 @@ type MutableBalanceOfParams struct { } func (s MutableBalanceOfParams) Account() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamAccount]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamAccount)) } diff --git a/contracts/wasm/erc20/go/erc20/results.go b/contracts/wasm/erc20/go/erc20/results.go index 627016ca28..88b9fb4763 100644 --- a/contracts/wasm/erc20/go/erc20/results.go +++ b/contracts/wasm/erc20/go/erc20/results.go @@ -14,7 +14,7 @@ type ImmutableAllowanceResults struct { } func (s ImmutableAllowanceResults) Amount() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultAmount]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultAmount)) } type MutableAllowanceResults struct { @@ -22,7 +22,7 @@ type MutableAllowanceResults struct { } func (s MutableAllowanceResults) Amount() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultAmount]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultAmount)) } type ImmutableBalanceOfResults struct { @@ -30,7 +30,7 @@ type ImmutableBalanceOfResults struct { } func (s ImmutableBalanceOfResults) Amount() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultAmount]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultAmount)) } type MutableBalanceOfResults struct { @@ -38,7 +38,7 @@ type MutableBalanceOfResults struct { } func (s MutableBalanceOfResults) Amount() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultAmount]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultAmount)) } type ImmutableTotalSupplyResults struct { @@ -46,7 +46,7 @@ type ImmutableTotalSupplyResults struct { } func (s ImmutableTotalSupplyResults) Supply() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultSupply]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultSupply)) } type MutableTotalSupplyResults struct { @@ -54,5 +54,5 @@ type MutableTotalSupplyResults struct { } func (s MutableTotalSupplyResults) Supply() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultSupply]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultSupply)) } diff --git a/contracts/wasm/erc20/go/erc20/state.go b/contracts/wasm/erc20/go/erc20/state.go index 8736cc54c3..9d33d8ba92 100644 --- a/contracts/wasm/erc20/go/erc20/state.go +++ b/contracts/wasm/erc20/go/erc20/state.go @@ -23,17 +23,17 @@ type ImmutableErc20State struct { } func (s ImmutableErc20State) AllAllowances() MapAgentIDToImmutableAllowancesForAgent { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateAllAllowances], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateAllAllowances), wasmlib.TYPE_MAP) return MapAgentIDToImmutableAllowancesForAgent{objID: mapID} } func (s ImmutableErc20State) Balances() MapAgentIDToImmutableInt64 { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateBalances], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateBalances), wasmlib.TYPE_MAP) return MapAgentIDToImmutableInt64{objID: mapID} } func (s ImmutableErc20State) Supply() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxStateSupply]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(StateSupply)) } type MapAgentIDToMutableAllowancesForAgent struct { @@ -53,16 +53,20 @@ type MutableErc20State struct { id int32 } +func (s MutableErc20State) AsImmutable() ImmutableErc20State { + return ImmutableErc20State(s) +} + func (s MutableErc20State) AllAllowances() MapAgentIDToMutableAllowancesForAgent { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateAllAllowances], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateAllAllowances), wasmlib.TYPE_MAP) return MapAgentIDToMutableAllowancesForAgent{objID: mapID} } func (s MutableErc20State) Balances() MapAgentIDToMutableInt64 { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateBalances], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateBalances), wasmlib.TYPE_MAP) return MapAgentIDToMutableInt64{objID: mapID} } func (s MutableErc20State) Supply() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxStateSupply]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(StateSupply)) } diff --git a/contracts/wasm/erc20/go/main.go b/contracts/wasm/erc20/go/main.go index 876c78787d..ebb45b8642 100644 --- a/contracts/wasm/erc20/go/main.go +++ b/contracts/wasm/erc20/go/main.go @@ -9,7 +9,7 @@ package main -import "github.com/iotaledger/wasp/packages/vm/wasmclient" +import "github.com/iotaledger/wasp/packages/vm/wasmvmhost" import "github.com/iotaledger/wasp/contracts/wasm/erc20/go/erc20" @@ -18,7 +18,7 @@ func main() { //export on_load func onLoad() { - h := &wasmclient.WasmVMHost{} + h := &wasmvmhost.WasmVMHost{} h.ConnectWasmHost() erc20.OnLoad() } diff --git a/contracts/wasm/erc20/src/params.rs b/contracts/wasm/erc20/src/params.rs index e57011db0e..a491640560 100644 --- a/contracts/wasm/erc20/src/params.rs +++ b/contracts/wasm/erc20/src/params.rs @@ -22,11 +22,11 @@ pub struct ImmutableApproveParams { impl ImmutableApproveParams { pub fn amount(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) + ScImmutableInt64::new(self.id, PARAM_AMOUNT.get_key_id()) } pub fn delegation(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_DELEGATION)) + ScImmutableAgentID::new(self.id, PARAM_DELEGATION.get_key_id()) } } @@ -37,11 +37,11 @@ pub struct MutableApproveParams { impl MutableApproveParams { pub fn amount(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) + ScMutableInt64::new(self.id, PARAM_AMOUNT.get_key_id()) } pub fn delegation(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_DELEGATION)) + ScMutableAgentID::new(self.id, PARAM_DELEGATION.get_key_id()) } } @@ -82,11 +82,11 @@ pub struct ImmutableTransferParams { impl ImmutableTransferParams { pub fn account(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_ACCOUNT)) + ScImmutableAgentID::new(self.id, PARAM_ACCOUNT.get_key_id()) } pub fn amount(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) + ScImmutableInt64::new(self.id, PARAM_AMOUNT.get_key_id()) } } @@ -97,11 +97,11 @@ pub struct MutableTransferParams { impl MutableTransferParams { pub fn account(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_ACCOUNT)) + ScMutableAgentID::new(self.id, PARAM_ACCOUNT.get_key_id()) } pub fn amount(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) + ScMutableInt64::new(self.id, PARAM_AMOUNT.get_key_id()) } } @@ -112,15 +112,15 @@ pub struct ImmutableTransferFromParams { impl ImmutableTransferFromParams { pub fn account(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_ACCOUNT)) + ScImmutableAgentID::new(self.id, PARAM_ACCOUNT.get_key_id()) } pub fn amount(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) + ScImmutableInt64::new(self.id, PARAM_AMOUNT.get_key_id()) } pub fn recipient(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_RECIPIENT)) + ScImmutableAgentID::new(self.id, PARAM_RECIPIENT.get_key_id()) } } @@ -131,15 +131,15 @@ pub struct MutableTransferFromParams { impl MutableTransferFromParams { pub fn account(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_ACCOUNT)) + ScMutableAgentID::new(self.id, PARAM_ACCOUNT.get_key_id()) } pub fn amount(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) + ScMutableInt64::new(self.id, PARAM_AMOUNT.get_key_id()) } pub fn recipient(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_RECIPIENT)) + ScMutableAgentID::new(self.id, PARAM_RECIPIENT.get_key_id()) } } @@ -150,11 +150,11 @@ pub struct ImmutableAllowanceParams { impl ImmutableAllowanceParams { pub fn account(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_ACCOUNT)) + ScImmutableAgentID::new(self.id, PARAM_ACCOUNT.get_key_id()) } pub fn delegation(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_DELEGATION)) + ScImmutableAgentID::new(self.id, PARAM_DELEGATION.get_key_id()) } } @@ -165,11 +165,11 @@ pub struct MutableAllowanceParams { impl MutableAllowanceParams { pub fn account(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_ACCOUNT)) + ScMutableAgentID::new(self.id, PARAM_ACCOUNT.get_key_id()) } pub fn delegation(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_DELEGATION)) + ScMutableAgentID::new(self.id, PARAM_DELEGATION.get_key_id()) } } @@ -180,7 +180,7 @@ pub struct ImmutableBalanceOfParams { impl ImmutableBalanceOfParams { pub fn account(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_ACCOUNT)) + ScImmutableAgentID::new(self.id, PARAM_ACCOUNT.get_key_id()) } } @@ -191,6 +191,6 @@ pub struct MutableBalanceOfParams { impl MutableBalanceOfParams { pub fn account(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_ACCOUNT)) + ScMutableAgentID::new(self.id, PARAM_ACCOUNT.get_key_id()) } } diff --git a/contracts/wasm/erc20/src/results.rs b/contracts/wasm/erc20/src/results.rs index 8d01ae636d..dd77540b94 100644 --- a/contracts/wasm/erc20/src/results.rs +++ b/contracts/wasm/erc20/src/results.rs @@ -22,7 +22,7 @@ pub struct ImmutableAllowanceResults { impl ImmutableAllowanceResults { pub fn amount(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_AMOUNT)) + ScImmutableInt64::new(self.id, RESULT_AMOUNT.get_key_id()) } } @@ -33,7 +33,7 @@ pub struct MutableAllowanceResults { impl MutableAllowanceResults { pub fn amount(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_AMOUNT)) + ScMutableInt64::new(self.id, RESULT_AMOUNT.get_key_id()) } } @@ -44,7 +44,7 @@ pub struct ImmutableBalanceOfResults { impl ImmutableBalanceOfResults { pub fn amount(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_AMOUNT)) + ScImmutableInt64::new(self.id, RESULT_AMOUNT.get_key_id()) } } @@ -55,7 +55,7 @@ pub struct MutableBalanceOfResults { impl MutableBalanceOfResults { pub fn amount(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_AMOUNT)) + ScMutableInt64::new(self.id, RESULT_AMOUNT.get_key_id()) } } @@ -66,7 +66,7 @@ pub struct ImmutableTotalSupplyResults { impl ImmutableTotalSupplyResults { pub fn supply(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_SUPPLY)) + ScImmutableInt64::new(self.id, RESULT_SUPPLY.get_key_id()) } } @@ -77,6 +77,6 @@ pub struct MutableTotalSupplyResults { impl MutableTotalSupplyResults { pub fn supply(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_SUPPLY)) + ScMutableInt64::new(self.id, RESULT_SUPPLY.get_key_id()) } } diff --git a/contracts/wasm/erc20/src/state.rs b/contracts/wasm/erc20/src/state.rs index c67adb6537..e1e0ff3283 100644 --- a/contracts/wasm/erc20/src/state.rs +++ b/contracts/wasm/erc20/src/state.rs @@ -15,6 +15,7 @@ use crate::*; use crate::keys::*; use crate::typedefs::*; +#[derive(Clone, Copy)] pub struct MapAgentIDToImmutableAllowancesForAgent { pub(crate) obj_id: i32, } @@ -33,20 +34,21 @@ pub struct ImmutableErc20State { impl ImmutableErc20State { pub fn all_allowances(&self) -> MapAgentIDToImmutableAllowancesForAgent { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_ALL_ALLOWANCES), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_ALL_ALLOWANCES.get_key_id(), TYPE_MAP); MapAgentIDToImmutableAllowancesForAgent { obj_id: map_id } } pub fn balances(&self) -> MapAgentIDToImmutableInt64 { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_BALANCES), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_BALANCES.get_key_id(), TYPE_MAP); MapAgentIDToImmutableInt64 { obj_id: map_id } } pub fn supply(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_STATE_SUPPLY)) + ScImmutableInt64::new(self.id, STATE_SUPPLY.get_key_id()) } } +#[derive(Clone, Copy)] pub struct MapAgentIDToMutableAllowancesForAgent { pub(crate) obj_id: i32, } @@ -68,17 +70,21 @@ pub struct MutableErc20State { } impl MutableErc20State { + pub fn as_immutable(&self) -> ImmutableErc20State { + ImmutableErc20State { id: self.id } + } + pub fn all_allowances(&self) -> MapAgentIDToMutableAllowancesForAgent { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_ALL_ALLOWANCES), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_ALL_ALLOWANCES.get_key_id(), TYPE_MAP); MapAgentIDToMutableAllowancesForAgent { obj_id: map_id } } pub fn balances(&self) -> MapAgentIDToMutableInt64 { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_BALANCES), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_BALANCES.get_key_id(), TYPE_MAP); MapAgentIDToMutableInt64 { obj_id: map_id } } pub fn supply(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_STATE_SUPPLY)) + ScMutableInt64::new(self.id, STATE_SUPPLY.get_key_id()) } } diff --git a/contracts/wasm/erc20/src/typedefs.rs b/contracts/wasm/erc20/src/typedefs.rs index 530075de78..dc638d395a 100644 --- a/contracts/wasm/erc20/src/typedefs.rs +++ b/contracts/wasm/erc20/src/typedefs.rs @@ -10,6 +10,7 @@ use wasmlib::*; use wasmlib::host::*; +#[derive(Clone, Copy)] pub struct MapAgentIDToImmutableInt64 { pub(crate) obj_id: i32, } @@ -22,6 +23,7 @@ impl MapAgentIDToImmutableInt64 { pub type ImmutableAllowancesForAgent = MapAgentIDToImmutableInt64; +#[derive(Clone, Copy)] pub struct MapAgentIDToMutableInt64 { pub(crate) obj_id: i32, } diff --git a/contracts/wasm/erc20/test/erc20_bg.wasm b/contracts/wasm/erc20/test/erc20_bg.wasm index 4ba488aa6c..cfb81b91db 100644 Binary files a/contracts/wasm/erc20/test/erc20_bg.wasm and b/contracts/wasm/erc20/test/erc20_bg.wasm differ diff --git a/contracts/wasm/erc20/ts/erc20/contract.ts b/contracts/wasm/erc20/ts/erc20/contract.ts index 111b9e6733..d04ec0afa0 100644 --- a/contracts/wasm/erc20/ts/erc20/contract.ts +++ b/contracts/wasm/erc20/ts/erc20/contract.ts @@ -14,7 +14,7 @@ export class ApproveCall { } export class ApproveContext { - events: sc.Erc20Events = new sc.Erc20Events(); + events: sc.Erc20Events = new sc.Erc20Events(); params: sc.ImmutableApproveParams = new sc.ImmutableApproveParams(); state: sc.MutableErc20State = new sc.MutableErc20State(); } @@ -25,7 +25,7 @@ export class InitCall { } export class InitContext { - events: sc.Erc20Events = new sc.Erc20Events(); + events: sc.Erc20Events = new sc.Erc20Events(); params: sc.ImmutableInitParams = new sc.ImmutableInitParams(); state: sc.MutableErc20State = new sc.MutableErc20State(); } @@ -36,7 +36,7 @@ export class TransferCall { } export class TransferContext { - events: sc.Erc20Events = new sc.Erc20Events(); + events: sc.Erc20Events = new sc.Erc20Events(); params: sc.ImmutableTransferParams = new sc.ImmutableTransferParams(); state: sc.MutableErc20State = new sc.MutableErc20State(); } @@ -47,7 +47,7 @@ export class TransferFromCall { } export class TransferFromContext { - events: sc.Erc20Events = new sc.Erc20Events(); + events: sc.Erc20Events = new sc.Erc20Events(); params: sc.ImmutableTransferFromParams = new sc.ImmutableTransferFromParams(); state: sc.MutableErc20State = new sc.MutableErc20State(); } diff --git a/contracts/wasm/erc20/ts/erc20/params.ts b/contracts/wasm/erc20/ts/erc20/params.ts index 0fb5a88612..00e4d9d20e 100644 --- a/contracts/wasm/erc20/ts/erc20/params.ts +++ b/contracts/wasm/erc20/ts/erc20/params.ts @@ -10,21 +10,21 @@ import * as sc from "./index"; export class ImmutableApproveParams extends wasmlib.ScMapID { amount(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamAmount]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamAmount)); } delegation(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamDelegation]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamDelegation)); } } export class MutableApproveParams extends wasmlib.ScMapID { amount(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamAmount]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamAmount)); } delegation(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamDelegation]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamDelegation)); } } @@ -50,80 +50,80 @@ export class MutableInitParams extends wasmlib.ScMapID { export class ImmutableTransferParams extends wasmlib.ScMapID { account(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAccount]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAccount)); } amount(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamAmount]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamAmount)); } } export class MutableTransferParams extends wasmlib.ScMapID { account(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAccount]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAccount)); } amount(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamAmount]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamAmount)); } } export class ImmutableTransferFromParams extends wasmlib.ScMapID { account(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAccount]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAccount)); } amount(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamAmount]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamAmount)); } recipient(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamRecipient]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamRecipient)); } } export class MutableTransferFromParams extends wasmlib.ScMapID { account(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAccount]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAccount)); } amount(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamAmount]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamAmount)); } recipient(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamRecipient]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamRecipient)); } } export class ImmutableAllowanceParams extends wasmlib.ScMapID { account(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAccount]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAccount)); } delegation(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamDelegation]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamDelegation)); } } export class MutableAllowanceParams extends wasmlib.ScMapID { account(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAccount]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAccount)); } delegation(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamDelegation]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamDelegation)); } } export class ImmutableBalanceOfParams extends wasmlib.ScMapID { account(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAccount]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAccount)); } } export class MutableBalanceOfParams extends wasmlib.ScMapID { account(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAccount]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAccount)); } } diff --git a/contracts/wasm/erc20/ts/erc20/results.ts b/contracts/wasm/erc20/ts/erc20/results.ts index ceab965434..21b795a702 100644 --- a/contracts/wasm/erc20/ts/erc20/results.ts +++ b/contracts/wasm/erc20/ts/erc20/results.ts @@ -10,36 +10,36 @@ import * as sc from "./index"; export class ImmutableAllowanceResults extends wasmlib.ScMapID { amount(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultAmount]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultAmount)); } } export class MutableAllowanceResults extends wasmlib.ScMapID { amount(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultAmount]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultAmount)); } } export class ImmutableBalanceOfResults extends wasmlib.ScMapID { amount(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultAmount]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultAmount)); } } export class MutableBalanceOfResults extends wasmlib.ScMapID { amount(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultAmount]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultAmount)); } } export class ImmutableTotalSupplyResults extends wasmlib.ScMapID { supply(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultSupply]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultSupply)); } } export class MutableTotalSupplyResults extends wasmlib.ScMapID { supply(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultSupply]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultSupply)); } } diff --git a/contracts/wasm/erc20/ts/erc20/state.ts b/contracts/wasm/erc20/ts/erc20/state.ts index 132fad2c0b..9b91699eb3 100644 --- a/contracts/wasm/erc20/ts/erc20/state.ts +++ b/contracts/wasm/erc20/ts/erc20/state.ts @@ -23,17 +23,17 @@ export class MapAgentIDToImmutableAllowancesForAgent { export class ImmutableErc20State extends wasmlib.ScMapID { allAllowances(): sc.MapAgentIDToImmutableAllowancesForAgent { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateAllAllowances], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateAllAllowances), wasmlib.TYPE_MAP); return new sc.MapAgentIDToImmutableAllowancesForAgent(mapID); } balances(): sc.MapAgentIDToImmutableInt64 { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBalances], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateBalances), wasmlib.TYPE_MAP); return new sc.MapAgentIDToImmutableInt64(mapID); } supply(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateSupply]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateSupply)); } } @@ -55,17 +55,23 @@ export class MapAgentIDToMutableAllowancesForAgent { } export class MutableErc20State extends wasmlib.ScMapID { + asImmutable(): sc.ImmutableErc20State { + const imm = new sc.ImmutableErc20State(); + imm.mapID = this.mapID; + return imm; + } + allAllowances(): sc.MapAgentIDToMutableAllowancesForAgent { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateAllAllowances], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateAllAllowances), wasmlib.TYPE_MAP); return new sc.MapAgentIDToMutableAllowancesForAgent(mapID); } balances(): sc.MapAgentIDToMutableInt64 { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBalances], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateBalances), wasmlib.TYPE_MAP); return new sc.MapAgentIDToMutableInt64(mapID); } supply(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateSupply]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateSupply)); } } diff --git a/contracts/wasm/erc721/go/erc721/consts.go b/contracts/wasm/erc721/go/erc721/consts.go index f6d90db059..a40a421910 100644 --- a/contracts/wasm/erc721/go/erc721/consts.go +++ b/contracts/wasm/erc721/go/erc721/consts.go @@ -26,6 +26,7 @@ const ( ParamSymbol = "s" ParamTo = "to" ParamTokenID = "tokenID" + ParamTokenURI = "tokenURI" ) const ( @@ -45,6 +46,7 @@ const ( StateName = "name" StateOwners = "owners" StateSymbol = "symbol" + StateTokenURIs = "tokenURIs" ) const ( diff --git a/contracts/wasm/erc721/go/erc721/erc721.go b/contracts/wasm/erc721/go/erc721/erc721.go index c77513c27e..81b8cf78f1 100644 --- a/contracts/wasm/erc721/go/erc721/erc721.go +++ b/contracts/wasm/erc721/go/erc721/erc721.go @@ -141,6 +141,12 @@ func funcMint(ctx wasmlib.ScFuncContext, f *MintContext) { tokenOwner := f.State.Owners().GetAgentID(tokenID) ctx.Require(!tokenOwner.Exists(), "tokenID already minted") + // save optional token uri + tokenURI := f.Params.TokenURI() + if tokenURI.Exists() { + f.State.TokenURIs().GetString(tokenID).SetValue(tokenURI.Value()) + } + owner := ctx.Caller() tokenOwner.SetValue(owner) balance := f.State.Balances().GetUint64(owner) @@ -239,6 +245,11 @@ func viewSymbol(ctx wasmlib.ScViewContext, f *SymbolContext) { func viewTokenURI(ctx wasmlib.ScViewContext, f *TokenURIContext) { tokenID := f.Params.TokenID() if tokenID.Exists() { - f.Results.TokenURI().SetValue(baseURI + tokenID.String()) + tokenURI := baseURI + tokenID.String() + savedURI := f.State.TokenURIs().GetString(tokenID.Value()) + if savedURI.Exists() { + tokenURI = savedURI.Value() + } + f.Results.TokenURI().SetValue(tokenURI) } } diff --git a/contracts/wasm/erc721/go/erc721/keys.go b/contracts/wasm/erc721/go/erc721/keys.go index e9a054932e..a1f47ba9f4 100644 --- a/contracts/wasm/erc721/go/erc721/keys.go +++ b/contracts/wasm/erc721/go/erc721/keys.go @@ -20,24 +20,26 @@ const ( IdxParamSymbol = 7 IdxParamTo = 8 IdxParamTokenID = 9 + IdxParamTokenURI = 10 - IdxResultAmount = 10 - IdxResultApproval = 11 - IdxResultApproved = 12 - IdxResultName = 13 - IdxResultOwner = 14 - IdxResultSymbol = 15 - IdxResultTokenURI = 16 + IdxResultAmount = 11 + IdxResultApproval = 12 + IdxResultApproved = 13 + IdxResultName = 14 + IdxResultOwner = 15 + IdxResultSymbol = 16 + IdxResultTokenURI = 17 - IdxStateApprovedAccounts = 17 - IdxStateApprovedOperators = 18 - IdxStateBalances = 19 - IdxStateName = 20 - IdxStateOwners = 21 - IdxStateSymbol = 22 + IdxStateApprovedAccounts = 18 + IdxStateApprovedOperators = 19 + IdxStateBalances = 20 + IdxStateName = 21 + IdxStateOwners = 22 + IdxStateSymbol = 23 + IdxStateTokenURIs = 24 ) -const keyMapLen = 23 +const keyMapLen = 25 var keyMap = [keyMapLen]wasmlib.Key{ ParamApproval, @@ -50,6 +52,7 @@ var keyMap = [keyMapLen]wasmlib.Key{ ParamSymbol, ParamTo, ParamTokenID, + ParamTokenURI, ResultAmount, ResultApproval, ResultApproved, @@ -63,6 +66,7 @@ var keyMap = [keyMapLen]wasmlib.Key{ StateName, StateOwners, StateSymbol, + StateTokenURIs, } var idxMap [keyMapLen]wasmlib.Key32 diff --git a/contracts/wasm/erc721/go/erc721/params.go b/contracts/wasm/erc721/go/erc721/params.go index da0baa3669..63a30646d2 100644 --- a/contracts/wasm/erc721/go/erc721/params.go +++ b/contracts/wasm/erc721/go/erc721/params.go @@ -14,11 +14,11 @@ type ImmutableApproveParams struct { } func (s ImmutableApproveParams) Approved() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamApproved]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamApproved)) } func (s ImmutableApproveParams) TokenID() wasmlib.ScImmutableHash { - return wasmlib.NewScImmutableHash(s.id, idxMap[IdxParamTokenID]) + return wasmlib.NewScImmutableHash(s.id, wasmlib.KeyID(ParamTokenID)) } type MutableApproveParams struct { @@ -26,11 +26,11 @@ type MutableApproveParams struct { } func (s MutableApproveParams) Approved() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamApproved]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamApproved)) } func (s MutableApproveParams) TokenID() wasmlib.ScMutableHash { - return wasmlib.NewScMutableHash(s.id, idxMap[IdxParamTokenID]) + return wasmlib.NewScMutableHash(s.id, wasmlib.KeyID(ParamTokenID)) } type ImmutableBurnParams struct { @@ -38,7 +38,7 @@ type ImmutableBurnParams struct { } func (s ImmutableBurnParams) TokenID() wasmlib.ScImmutableHash { - return wasmlib.NewScImmutableHash(s.id, idxMap[IdxParamTokenID]) + return wasmlib.NewScImmutableHash(s.id, wasmlib.KeyID(ParamTokenID)) } type MutableBurnParams struct { @@ -46,7 +46,7 @@ type MutableBurnParams struct { } func (s MutableBurnParams) TokenID() wasmlib.ScMutableHash { - return wasmlib.NewScMutableHash(s.id, idxMap[IdxParamTokenID]) + return wasmlib.NewScMutableHash(s.id, wasmlib.KeyID(ParamTokenID)) } type ImmutableInitParams struct { @@ -78,7 +78,11 @@ type ImmutableMintParams struct { } func (s ImmutableMintParams) TokenID() wasmlib.ScImmutableHash { - return wasmlib.NewScImmutableHash(s.id, idxMap[IdxParamTokenID]) + return wasmlib.NewScImmutableHash(s.id, wasmlib.KeyID(ParamTokenID)) +} + +func (s ImmutableMintParams) TokenURI() wasmlib.ScImmutableString { + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamTokenURI)) } type MutableMintParams struct { @@ -86,7 +90,11 @@ type MutableMintParams struct { } func (s MutableMintParams) TokenID() wasmlib.ScMutableHash { - return wasmlib.NewScMutableHash(s.id, idxMap[IdxParamTokenID]) + return wasmlib.NewScMutableHash(s.id, wasmlib.KeyID(ParamTokenID)) +} + +func (s MutableMintParams) TokenURI() wasmlib.ScMutableString { + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamTokenURI)) } type ImmutableSafeTransferFromParams struct { @@ -94,19 +102,19 @@ type ImmutableSafeTransferFromParams struct { } func (s ImmutableSafeTransferFromParams) Data() wasmlib.ScImmutableBytes { - return wasmlib.NewScImmutableBytes(s.id, idxMap[IdxParamData]) + return wasmlib.NewScImmutableBytes(s.id, wasmlib.KeyID(ParamData)) } func (s ImmutableSafeTransferFromParams) From() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamFrom]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamFrom)) } func (s ImmutableSafeTransferFromParams) To() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamTo]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamTo)) } func (s ImmutableSafeTransferFromParams) TokenID() wasmlib.ScImmutableHash { - return wasmlib.NewScImmutableHash(s.id, idxMap[IdxParamTokenID]) + return wasmlib.NewScImmutableHash(s.id, wasmlib.KeyID(ParamTokenID)) } type MutableSafeTransferFromParams struct { @@ -114,19 +122,19 @@ type MutableSafeTransferFromParams struct { } func (s MutableSafeTransferFromParams) Data() wasmlib.ScMutableBytes { - return wasmlib.NewScMutableBytes(s.id, idxMap[IdxParamData]) + return wasmlib.NewScMutableBytes(s.id, wasmlib.KeyID(ParamData)) } func (s MutableSafeTransferFromParams) From() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamFrom]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamFrom)) } func (s MutableSafeTransferFromParams) To() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamTo]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamTo)) } func (s MutableSafeTransferFromParams) TokenID() wasmlib.ScMutableHash { - return wasmlib.NewScMutableHash(s.id, idxMap[IdxParamTokenID]) + return wasmlib.NewScMutableHash(s.id, wasmlib.KeyID(ParamTokenID)) } type ImmutableSetApprovalForAllParams struct { @@ -134,11 +142,11 @@ type ImmutableSetApprovalForAllParams struct { } func (s ImmutableSetApprovalForAllParams) Approval() wasmlib.ScImmutableBool { - return wasmlib.NewScImmutableBool(s.id, idxMap[IdxParamApproval]) + return wasmlib.NewScImmutableBool(s.id, wasmlib.KeyID(ParamApproval)) } func (s ImmutableSetApprovalForAllParams) Operator() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamOperator]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamOperator)) } type MutableSetApprovalForAllParams struct { @@ -146,11 +154,11 @@ type MutableSetApprovalForAllParams struct { } func (s MutableSetApprovalForAllParams) Approval() wasmlib.ScMutableBool { - return wasmlib.NewScMutableBool(s.id, idxMap[IdxParamApproval]) + return wasmlib.NewScMutableBool(s.id, wasmlib.KeyID(ParamApproval)) } func (s MutableSetApprovalForAllParams) Operator() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamOperator]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamOperator)) } type ImmutableTransferFromParams struct { @@ -158,15 +166,15 @@ type ImmutableTransferFromParams struct { } func (s ImmutableTransferFromParams) From() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamFrom]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamFrom)) } func (s ImmutableTransferFromParams) To() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamTo]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamTo)) } func (s ImmutableTransferFromParams) TokenID() wasmlib.ScImmutableHash { - return wasmlib.NewScImmutableHash(s.id, idxMap[IdxParamTokenID]) + return wasmlib.NewScImmutableHash(s.id, wasmlib.KeyID(ParamTokenID)) } type MutableTransferFromParams struct { @@ -174,15 +182,15 @@ type MutableTransferFromParams struct { } func (s MutableTransferFromParams) From() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamFrom]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamFrom)) } func (s MutableTransferFromParams) To() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamTo]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamTo)) } func (s MutableTransferFromParams) TokenID() wasmlib.ScMutableHash { - return wasmlib.NewScMutableHash(s.id, idxMap[IdxParamTokenID]) + return wasmlib.NewScMutableHash(s.id, wasmlib.KeyID(ParamTokenID)) } type ImmutableBalanceOfParams struct { @@ -190,7 +198,7 @@ type ImmutableBalanceOfParams struct { } func (s ImmutableBalanceOfParams) Owner() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamOwner]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamOwner)) } type MutableBalanceOfParams struct { @@ -198,7 +206,7 @@ type MutableBalanceOfParams struct { } func (s MutableBalanceOfParams) Owner() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamOwner]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamOwner)) } type ImmutableGetApprovedParams struct { @@ -206,7 +214,7 @@ type ImmutableGetApprovedParams struct { } func (s ImmutableGetApprovedParams) TokenID() wasmlib.ScImmutableHash { - return wasmlib.NewScImmutableHash(s.id, idxMap[IdxParamTokenID]) + return wasmlib.NewScImmutableHash(s.id, wasmlib.KeyID(ParamTokenID)) } type MutableGetApprovedParams struct { @@ -214,7 +222,7 @@ type MutableGetApprovedParams struct { } func (s MutableGetApprovedParams) TokenID() wasmlib.ScMutableHash { - return wasmlib.NewScMutableHash(s.id, idxMap[IdxParamTokenID]) + return wasmlib.NewScMutableHash(s.id, wasmlib.KeyID(ParamTokenID)) } type ImmutableIsApprovedForAllParams struct { @@ -222,11 +230,11 @@ type ImmutableIsApprovedForAllParams struct { } func (s ImmutableIsApprovedForAllParams) Operator() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamOperator]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamOperator)) } func (s ImmutableIsApprovedForAllParams) Owner() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamOwner]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamOwner)) } type MutableIsApprovedForAllParams struct { @@ -234,11 +242,11 @@ type MutableIsApprovedForAllParams struct { } func (s MutableIsApprovedForAllParams) Operator() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamOperator]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamOperator)) } func (s MutableIsApprovedForAllParams) Owner() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamOwner]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamOwner)) } type ImmutableOwnerOfParams struct { @@ -246,7 +254,7 @@ type ImmutableOwnerOfParams struct { } func (s ImmutableOwnerOfParams) TokenID() wasmlib.ScImmutableHash { - return wasmlib.NewScImmutableHash(s.id, idxMap[IdxParamTokenID]) + return wasmlib.NewScImmutableHash(s.id, wasmlib.KeyID(ParamTokenID)) } type MutableOwnerOfParams struct { @@ -254,7 +262,7 @@ type MutableOwnerOfParams struct { } func (s MutableOwnerOfParams) TokenID() wasmlib.ScMutableHash { - return wasmlib.NewScMutableHash(s.id, idxMap[IdxParamTokenID]) + return wasmlib.NewScMutableHash(s.id, wasmlib.KeyID(ParamTokenID)) } type ImmutableTokenURIParams struct { @@ -262,7 +270,7 @@ type ImmutableTokenURIParams struct { } func (s ImmutableTokenURIParams) TokenID() wasmlib.ScImmutableHash { - return wasmlib.NewScImmutableHash(s.id, idxMap[IdxParamTokenID]) + return wasmlib.NewScImmutableHash(s.id, wasmlib.KeyID(ParamTokenID)) } type MutableTokenURIParams struct { @@ -270,5 +278,5 @@ type MutableTokenURIParams struct { } func (s MutableTokenURIParams) TokenID() wasmlib.ScMutableHash { - return wasmlib.NewScMutableHash(s.id, idxMap[IdxParamTokenID]) + return wasmlib.NewScMutableHash(s.id, wasmlib.KeyID(ParamTokenID)) } diff --git a/contracts/wasm/erc721/go/erc721/results.go b/contracts/wasm/erc721/go/erc721/results.go index ac16050ca7..ff831db9c0 100644 --- a/contracts/wasm/erc721/go/erc721/results.go +++ b/contracts/wasm/erc721/go/erc721/results.go @@ -14,7 +14,7 @@ type ImmutableBalanceOfResults struct { } func (s ImmutableBalanceOfResults) Amount() wasmlib.ScImmutableUint64 { - return wasmlib.NewScImmutableUint64(s.id, idxMap[IdxResultAmount]) + return wasmlib.NewScImmutableUint64(s.id, wasmlib.KeyID(ResultAmount)) } type MutableBalanceOfResults struct { @@ -22,7 +22,7 @@ type MutableBalanceOfResults struct { } func (s MutableBalanceOfResults) Amount() wasmlib.ScMutableUint64 { - return wasmlib.NewScMutableUint64(s.id, idxMap[IdxResultAmount]) + return wasmlib.NewScMutableUint64(s.id, wasmlib.KeyID(ResultAmount)) } type ImmutableGetApprovedResults struct { @@ -30,7 +30,7 @@ type ImmutableGetApprovedResults struct { } func (s ImmutableGetApprovedResults) Approved() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxResultApproved]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ResultApproved)) } type MutableGetApprovedResults struct { @@ -38,7 +38,7 @@ type MutableGetApprovedResults struct { } func (s MutableGetApprovedResults) Approved() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxResultApproved]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ResultApproved)) } type ImmutableIsApprovedForAllResults struct { @@ -46,7 +46,7 @@ type ImmutableIsApprovedForAllResults struct { } func (s ImmutableIsApprovedForAllResults) Approval() wasmlib.ScImmutableBool { - return wasmlib.NewScImmutableBool(s.id, idxMap[IdxResultApproval]) + return wasmlib.NewScImmutableBool(s.id, wasmlib.KeyID(ResultApproval)) } type MutableIsApprovedForAllResults struct { @@ -54,7 +54,7 @@ type MutableIsApprovedForAllResults struct { } func (s MutableIsApprovedForAllResults) Approval() wasmlib.ScMutableBool { - return wasmlib.NewScMutableBool(s.id, idxMap[IdxResultApproval]) + return wasmlib.NewScMutableBool(s.id, wasmlib.KeyID(ResultApproval)) } type ImmutableNameResults struct { @@ -62,7 +62,7 @@ type ImmutableNameResults struct { } func (s ImmutableNameResults) Name() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxResultName]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ResultName)) } type MutableNameResults struct { @@ -70,7 +70,7 @@ type MutableNameResults struct { } func (s MutableNameResults) Name() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxResultName]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ResultName)) } type ImmutableOwnerOfResults struct { @@ -78,7 +78,7 @@ type ImmutableOwnerOfResults struct { } func (s ImmutableOwnerOfResults) Owner() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxResultOwner]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ResultOwner)) } type MutableOwnerOfResults struct { @@ -86,7 +86,7 @@ type MutableOwnerOfResults struct { } func (s MutableOwnerOfResults) Owner() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxResultOwner]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ResultOwner)) } type ImmutableSymbolResults struct { @@ -94,7 +94,7 @@ type ImmutableSymbolResults struct { } func (s ImmutableSymbolResults) Symbol() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxResultSymbol]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ResultSymbol)) } type MutableSymbolResults struct { @@ -102,7 +102,7 @@ type MutableSymbolResults struct { } func (s MutableSymbolResults) Symbol() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxResultSymbol]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ResultSymbol)) } type ImmutableTokenURIResults struct { @@ -110,7 +110,7 @@ type ImmutableTokenURIResults struct { } func (s ImmutableTokenURIResults) TokenURI() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxResultTokenURI]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ResultTokenURI)) } type MutableTokenURIResults struct { @@ -118,5 +118,5 @@ type MutableTokenURIResults struct { } func (s MutableTokenURIResults) TokenURI() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxResultTokenURI]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ResultTokenURI)) } diff --git a/contracts/wasm/erc721/go/erc721/state.go b/contracts/wasm/erc721/go/erc721/state.go index c3ad62781b..e2204b0108 100644 --- a/contracts/wasm/erc721/go/erc721/state.go +++ b/contracts/wasm/erc721/go/erc721/state.go @@ -34,36 +34,49 @@ func (m MapAgentIDToImmutableUint64) GetUint64(key wasmlib.ScAgentID) wasmlib.Sc return wasmlib.NewScImmutableUint64(m.objID, key.KeyID()) } +type MapHashToImmutableString struct { + objID int32 +} + +func (m MapHashToImmutableString) GetString(key wasmlib.ScHash) wasmlib.ScImmutableString { + return wasmlib.NewScImmutableString(m.objID, key.KeyID()) +} + type ImmutableErc721State struct { id int32 } func (s ImmutableErc721State) ApprovedAccounts() MapHashToImmutableAgentID { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateApprovedAccounts], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateApprovedAccounts), wasmlib.TYPE_MAP) return MapHashToImmutableAgentID{objID: mapID} } func (s ImmutableErc721State) ApprovedOperators() MapAgentIDToImmutableOperators { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateApprovedOperators], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateApprovedOperators), wasmlib.TYPE_MAP) return MapAgentIDToImmutableOperators{objID: mapID} } func (s ImmutableErc721State) Balances() MapAgentIDToImmutableUint64 { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateBalances], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateBalances), wasmlib.TYPE_MAP) return MapAgentIDToImmutableUint64{objID: mapID} } func (s ImmutableErc721State) Name() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxStateName]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(StateName)) } func (s ImmutableErc721State) Owners() MapHashToImmutableAgentID { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateOwners], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateOwners), wasmlib.TYPE_MAP) return MapHashToImmutableAgentID{objID: mapID} } func (s ImmutableErc721State) Symbol() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxStateSymbol]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(StateSymbol)) +} + +func (s ImmutableErc721State) TokenURIs() MapHashToImmutableString { + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateTokenURIs), wasmlib.TYPE_MAP) + return MapHashToImmutableString{objID: mapID} } type MapHashToMutableAgentID struct { @@ -103,34 +116,55 @@ func (m MapAgentIDToMutableUint64) GetUint64(key wasmlib.ScAgentID) wasmlib.ScMu return wasmlib.NewScMutableUint64(m.objID, key.KeyID()) } +type MapHashToMutableString struct { + objID int32 +} + +func (m MapHashToMutableString) Clear() { + wasmlib.Clear(m.objID) +} + +func (m MapHashToMutableString) GetString(key wasmlib.ScHash) wasmlib.ScMutableString { + return wasmlib.NewScMutableString(m.objID, key.KeyID()) +} + type MutableErc721State struct { id int32 } +func (s MutableErc721State) AsImmutable() ImmutableErc721State { + return ImmutableErc721State(s) +} + func (s MutableErc721State) ApprovedAccounts() MapHashToMutableAgentID { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateApprovedAccounts], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateApprovedAccounts), wasmlib.TYPE_MAP) return MapHashToMutableAgentID{objID: mapID} } func (s MutableErc721State) ApprovedOperators() MapAgentIDToMutableOperators { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateApprovedOperators], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateApprovedOperators), wasmlib.TYPE_MAP) return MapAgentIDToMutableOperators{objID: mapID} } func (s MutableErc721State) Balances() MapAgentIDToMutableUint64 { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateBalances], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateBalances), wasmlib.TYPE_MAP) return MapAgentIDToMutableUint64{objID: mapID} } func (s MutableErc721State) Name() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxStateName]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(StateName)) } func (s MutableErc721State) Owners() MapHashToMutableAgentID { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateOwners], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateOwners), wasmlib.TYPE_MAP) return MapHashToMutableAgentID{objID: mapID} } func (s MutableErc721State) Symbol() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxStateSymbol]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(StateSymbol)) +} + +func (s MutableErc721State) TokenURIs() MapHashToMutableString { + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateTokenURIs), wasmlib.TYPE_MAP) + return MapHashToMutableString{objID: mapID} } diff --git a/contracts/wasm/erc721/go/main.go b/contracts/wasm/erc721/go/main.go index b863c75bb9..f06a3059cc 100644 --- a/contracts/wasm/erc721/go/main.go +++ b/contracts/wasm/erc721/go/main.go @@ -9,7 +9,7 @@ package main -import "github.com/iotaledger/wasp/packages/vm/wasmclient" +import "github.com/iotaledger/wasp/packages/vm/wasmvmhost" import "github.com/iotaledger/wasp/contracts/wasm/erc721/go/erc721" @@ -18,7 +18,7 @@ func main() { //export on_load func onLoad() { - h := &wasmclient.WasmVMHost{} + h := &wasmvmhost.WasmVMHost{} h.ConnectWasmHost() erc721.OnLoad() } diff --git a/contracts/wasm/erc721/schema.yaml b/contracts/wasm/erc721/schema.yaml index 450632f03a..5a96e6db04 100644 --- a/contracts/wasm/erc721/schema.yaml +++ b/contracts/wasm/erc721/schema.yaml @@ -30,6 +30,7 @@ state: approvedAccounts: map[Hash]AgentID // approved token controller agents balances: map[AgentID]Uint64 // number of tokens held by owners approvedOperators: map[AgentID]Operators // approved operators per owner + tokenURIs: map[Hash]String // token uri per token id funcs: approve: params: @@ -45,6 +46,7 @@ funcs: mint: params: tokenID: Hash // New token id + tokenURI: String? // Optional token URI that overrides default safeTransferFrom: params: from: AgentID // from account @@ -65,18 +67,18 @@ views: params: owner: AgentID // account owner results: - amount: Uint64 //amount of tokens (owner) + amount: Uint64? // amount of tokens owned by owner getApproved: params: tokenID: Hash results: - approved: AgentID + approved: AgentID? isApprovedForAll: params: owner: AgentID operator: AgentID results: - approval: Bool + approval: Bool? name: results: name: String @@ -84,7 +86,7 @@ views: params: tokenID: Hash results: - owner: AgentID + owner: AgentID? symbol: results: symbol: String @@ -92,4 +94,4 @@ views: params: tokenID: Hash results: - tokenURI: String + tokenURI: String? diff --git a/contracts/wasm/erc721/src/consts.rs b/contracts/wasm/erc721/src/consts.rs index 69c5bce108..61777ea8cc 100644 --- a/contracts/wasm/erc721/src/consts.rs +++ b/contracts/wasm/erc721/src/consts.rs @@ -13,16 +13,17 @@ pub const SC_NAME : &str = "erc721"; pub const SC_DESCRIPTION : &str = "ERC-721 NFT PoC for IOTA Smart Contracts"; pub const HSC_NAME : ScHname = ScHname(0xd967c216); -pub const PARAM_APPROVAL : &str = "approval"; -pub const PARAM_APPROVED : &str = "approved"; -pub const PARAM_DATA : &str = "data"; -pub const PARAM_FROM : &str = "from"; -pub const PARAM_NAME : &str = "n"; -pub const PARAM_OPERATOR : &str = "operator"; -pub const PARAM_OWNER : &str = "owner"; -pub const PARAM_SYMBOL : &str = "s"; -pub const PARAM_TO : &str = "to"; -pub const PARAM_TOKEN_ID : &str = "tokenID"; +pub const PARAM_APPROVAL : &str = "approval"; +pub const PARAM_APPROVED : &str = "approved"; +pub const PARAM_DATA : &str = "data"; +pub const PARAM_FROM : &str = "from"; +pub const PARAM_NAME : &str = "n"; +pub const PARAM_OPERATOR : &str = "operator"; +pub const PARAM_OWNER : &str = "owner"; +pub const PARAM_SYMBOL : &str = "s"; +pub const PARAM_TO : &str = "to"; +pub const PARAM_TOKEN_ID : &str = "tokenID"; +pub const PARAM_TOKEN_URI : &str = "tokenURI"; pub const RESULT_AMOUNT : &str = "amount"; pub const RESULT_APPROVAL : &str = "approval"; @@ -38,6 +39,7 @@ pub const STATE_BALANCES : &str = "balances"; pub const STATE_NAME : &str = "name"; pub const STATE_OWNERS : &str = "owners"; pub const STATE_SYMBOL : &str = "symbol"; +pub const STATE_TOKEN_UR_IS : &str = "tokenURIs"; pub const FUNC_APPROVE : &str = "approve"; pub const FUNC_BURN : &str = "burn"; diff --git a/contracts/wasm/erc721/src/erc721.rs b/contracts/wasm/erc721/src/erc721.rs index c313ad4727..26b0263492 100644 --- a/contracts/wasm/erc721/src/erc721.rs +++ b/contracts/wasm/erc721/src/erc721.rs @@ -140,6 +140,12 @@ pub fn func_mint(ctx: &ScFuncContext, f: &MintContext) { let token_owner = f.state.owners().get_agent_id(&token_id); ctx.require(!token_owner.exists(), "tokenID already minted"); + // save optional token uri + let token_uri = f.params.token_uri(); + if token_uri.exists() { + f.state.token_ur_is().get_string(&token_id).set_value(&token_uri.value()); + } + let owner = ctx.caller(); token_owner.set_value(&owner); let balance = f.state.balances().get_uint64(&owner); @@ -238,6 +244,11 @@ pub fn view_symbol(_ctx: &ScViewContext, f: &SymbolContext) { pub fn view_token_uri(_ctx: &ScViewContext, f: &TokenURIContext) { let token_id = f.params.token_id(); if token_id.exists() { - f.results.token_uri().set_value(&(BASE_URI.to_owned() + &token_id.to_string())); + let mut token_uri = BASE_URI.to_owned() + &token_id.to_string(); + let saved_uri = f.state.token_ur_is().get_string(&token_id.value()); + if saved_uri.exists() { + token_uri = saved_uri.value(); + } + f.results.token_uri().set_value(&token_uri); } } diff --git a/contracts/wasm/erc721/src/keys.rs b/contracts/wasm/erc721/src/keys.rs index a806243367..dacf7d5ea9 100644 --- a/contracts/wasm/erc721/src/keys.rs +++ b/contracts/wasm/erc721/src/keys.rs @@ -11,33 +11,35 @@ use wasmlib::*; use crate::*; -pub(crate) const IDX_PARAM_APPROVAL : usize = 0; -pub(crate) const IDX_PARAM_APPROVED : usize = 1; -pub(crate) const IDX_PARAM_DATA : usize = 2; -pub(crate) const IDX_PARAM_FROM : usize = 3; -pub(crate) const IDX_PARAM_NAME : usize = 4; -pub(crate) const IDX_PARAM_OPERATOR : usize = 5; -pub(crate) const IDX_PARAM_OWNER : usize = 6; -pub(crate) const IDX_PARAM_SYMBOL : usize = 7; -pub(crate) const IDX_PARAM_TO : usize = 8; -pub(crate) const IDX_PARAM_TOKEN_ID : usize = 9; +pub(crate) const IDX_PARAM_APPROVAL : usize = 0; +pub(crate) const IDX_PARAM_APPROVED : usize = 1; +pub(crate) const IDX_PARAM_DATA : usize = 2; +pub(crate) const IDX_PARAM_FROM : usize = 3; +pub(crate) const IDX_PARAM_NAME : usize = 4; +pub(crate) const IDX_PARAM_OPERATOR : usize = 5; +pub(crate) const IDX_PARAM_OWNER : usize = 6; +pub(crate) const IDX_PARAM_SYMBOL : usize = 7; +pub(crate) const IDX_PARAM_TO : usize = 8; +pub(crate) const IDX_PARAM_TOKEN_ID : usize = 9; +pub(crate) const IDX_PARAM_TOKEN_URI : usize = 10; -pub(crate) const IDX_RESULT_AMOUNT : usize = 10; -pub(crate) const IDX_RESULT_APPROVAL : usize = 11; -pub(crate) const IDX_RESULT_APPROVED : usize = 12; -pub(crate) const IDX_RESULT_NAME : usize = 13; -pub(crate) const IDX_RESULT_OWNER : usize = 14; -pub(crate) const IDX_RESULT_SYMBOL : usize = 15; -pub(crate) const IDX_RESULT_TOKEN_URI : usize = 16; +pub(crate) const IDX_RESULT_AMOUNT : usize = 11; +pub(crate) const IDX_RESULT_APPROVAL : usize = 12; +pub(crate) const IDX_RESULT_APPROVED : usize = 13; +pub(crate) const IDX_RESULT_NAME : usize = 14; +pub(crate) const IDX_RESULT_OWNER : usize = 15; +pub(crate) const IDX_RESULT_SYMBOL : usize = 16; +pub(crate) const IDX_RESULT_TOKEN_URI : usize = 17; -pub(crate) const IDX_STATE_APPROVED_ACCOUNTS : usize = 17; -pub(crate) const IDX_STATE_APPROVED_OPERATORS : usize = 18; -pub(crate) const IDX_STATE_BALANCES : usize = 19; -pub(crate) const IDX_STATE_NAME : usize = 20; -pub(crate) const IDX_STATE_OWNERS : usize = 21; -pub(crate) const IDX_STATE_SYMBOL : usize = 22; +pub(crate) const IDX_STATE_APPROVED_ACCOUNTS : usize = 18; +pub(crate) const IDX_STATE_APPROVED_OPERATORS : usize = 19; +pub(crate) const IDX_STATE_BALANCES : usize = 20; +pub(crate) const IDX_STATE_NAME : usize = 21; +pub(crate) const IDX_STATE_OWNERS : usize = 22; +pub(crate) const IDX_STATE_SYMBOL : usize = 23; +pub(crate) const IDX_STATE_TOKEN_UR_IS : usize = 24; -pub const KEY_MAP_LEN: usize = 23; +pub const KEY_MAP_LEN: usize = 25; pub const KEY_MAP: [&str; KEY_MAP_LEN] = [ PARAM_APPROVAL, @@ -50,6 +52,7 @@ pub const KEY_MAP: [&str; KEY_MAP_LEN] = [ PARAM_SYMBOL, PARAM_TO, PARAM_TOKEN_ID, + PARAM_TOKEN_URI, RESULT_AMOUNT, RESULT_APPROVAL, RESULT_APPROVED, @@ -63,6 +66,7 @@ pub const KEY_MAP: [&str; KEY_MAP_LEN] = [ STATE_NAME, STATE_OWNERS, STATE_SYMBOL, + STATE_TOKEN_UR_IS, ]; pub static mut IDX_MAP: [Key32; KEY_MAP_LEN] = [Key32(0); KEY_MAP_LEN]; diff --git a/contracts/wasm/erc721/src/params.rs b/contracts/wasm/erc721/src/params.rs index 3f9b03d32a..14db52728e 100644 --- a/contracts/wasm/erc721/src/params.rs +++ b/contracts/wasm/erc721/src/params.rs @@ -22,11 +22,11 @@ pub struct ImmutableApproveParams { impl ImmutableApproveParams { pub fn approved(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_APPROVED)) + ScImmutableAgentID::new(self.id, PARAM_APPROVED.get_key_id()) } pub fn token_id(&self) -> ScImmutableHash { - ScImmutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + ScImmutableHash::new(self.id, PARAM_TOKEN_ID.get_key_id()) } } @@ -37,11 +37,11 @@ pub struct MutableApproveParams { impl MutableApproveParams { pub fn approved(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_APPROVED)) + ScMutableAgentID::new(self.id, PARAM_APPROVED.get_key_id()) } pub fn token_id(&self) -> ScMutableHash { - ScMutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + ScMutableHash::new(self.id, PARAM_TOKEN_ID.get_key_id()) } } @@ -52,7 +52,7 @@ pub struct ImmutableBurnParams { impl ImmutableBurnParams { pub fn token_id(&self) -> ScImmutableHash { - ScImmutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + ScImmutableHash::new(self.id, PARAM_TOKEN_ID.get_key_id()) } } @@ -63,7 +63,7 @@ pub struct MutableBurnParams { impl MutableBurnParams { pub fn token_id(&self) -> ScMutableHash { - ScMutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + ScMutableHash::new(self.id, PARAM_TOKEN_ID.get_key_id()) } } @@ -104,7 +104,11 @@ pub struct ImmutableMintParams { impl ImmutableMintParams { pub fn token_id(&self) -> ScImmutableHash { - ScImmutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + ScImmutableHash::new(self.id, PARAM_TOKEN_ID.get_key_id()) + } + + pub fn token_uri(&self) -> ScImmutableString { + ScImmutableString::new(self.id, PARAM_TOKEN_URI.get_key_id()) } } @@ -115,7 +119,11 @@ pub struct MutableMintParams { impl MutableMintParams { pub fn token_id(&self) -> ScMutableHash { - ScMutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + ScMutableHash::new(self.id, PARAM_TOKEN_ID.get_key_id()) + } + + pub fn token_uri(&self) -> ScMutableString { + ScMutableString::new(self.id, PARAM_TOKEN_URI.get_key_id()) } } @@ -126,19 +134,19 @@ pub struct ImmutableSafeTransferFromParams { impl ImmutableSafeTransferFromParams { pub fn data(&self) -> ScImmutableBytes { - ScImmutableBytes::new(self.id, idx_map(IDX_PARAM_DATA)) + ScImmutableBytes::new(self.id, PARAM_DATA.get_key_id()) } pub fn from(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_FROM)) + ScImmutableAgentID::new(self.id, PARAM_FROM.get_key_id()) } pub fn to(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_TO)) + ScImmutableAgentID::new(self.id, PARAM_TO.get_key_id()) } pub fn token_id(&self) -> ScImmutableHash { - ScImmutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + ScImmutableHash::new(self.id, PARAM_TOKEN_ID.get_key_id()) } } @@ -149,19 +157,19 @@ pub struct MutableSafeTransferFromParams { impl MutableSafeTransferFromParams { pub fn data(&self) -> ScMutableBytes { - ScMutableBytes::new(self.id, idx_map(IDX_PARAM_DATA)) + ScMutableBytes::new(self.id, PARAM_DATA.get_key_id()) } pub fn from(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_FROM)) + ScMutableAgentID::new(self.id, PARAM_FROM.get_key_id()) } pub fn to(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_TO)) + ScMutableAgentID::new(self.id, PARAM_TO.get_key_id()) } pub fn token_id(&self) -> ScMutableHash { - ScMutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + ScMutableHash::new(self.id, PARAM_TOKEN_ID.get_key_id()) } } @@ -172,11 +180,11 @@ pub struct ImmutableSetApprovalForAllParams { impl ImmutableSetApprovalForAllParams { pub fn approval(&self) -> ScImmutableBool { - ScImmutableBool::new(self.id, idx_map(IDX_PARAM_APPROVAL)) + ScImmutableBool::new(self.id, PARAM_APPROVAL.get_key_id()) } pub fn operator(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_OPERATOR)) + ScImmutableAgentID::new(self.id, PARAM_OPERATOR.get_key_id()) } } @@ -187,11 +195,11 @@ pub struct MutableSetApprovalForAllParams { impl MutableSetApprovalForAllParams { pub fn approval(&self) -> ScMutableBool { - ScMutableBool::new(self.id, idx_map(IDX_PARAM_APPROVAL)) + ScMutableBool::new(self.id, PARAM_APPROVAL.get_key_id()) } pub fn operator(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_OPERATOR)) + ScMutableAgentID::new(self.id, PARAM_OPERATOR.get_key_id()) } } @@ -202,15 +210,15 @@ pub struct ImmutableTransferFromParams { impl ImmutableTransferFromParams { pub fn from(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_FROM)) + ScImmutableAgentID::new(self.id, PARAM_FROM.get_key_id()) } pub fn to(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_TO)) + ScImmutableAgentID::new(self.id, PARAM_TO.get_key_id()) } pub fn token_id(&self) -> ScImmutableHash { - ScImmutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + ScImmutableHash::new(self.id, PARAM_TOKEN_ID.get_key_id()) } } @@ -221,15 +229,15 @@ pub struct MutableTransferFromParams { impl MutableTransferFromParams { pub fn from(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_FROM)) + ScMutableAgentID::new(self.id, PARAM_FROM.get_key_id()) } pub fn to(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_TO)) + ScMutableAgentID::new(self.id, PARAM_TO.get_key_id()) } pub fn token_id(&self) -> ScMutableHash { - ScMutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + ScMutableHash::new(self.id, PARAM_TOKEN_ID.get_key_id()) } } @@ -240,7 +248,7 @@ pub struct ImmutableBalanceOfParams { impl ImmutableBalanceOfParams { pub fn owner(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_OWNER)) + ScImmutableAgentID::new(self.id, PARAM_OWNER.get_key_id()) } } @@ -251,7 +259,7 @@ pub struct MutableBalanceOfParams { impl MutableBalanceOfParams { pub fn owner(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_OWNER)) + ScMutableAgentID::new(self.id, PARAM_OWNER.get_key_id()) } } @@ -262,7 +270,7 @@ pub struct ImmutableGetApprovedParams { impl ImmutableGetApprovedParams { pub fn token_id(&self) -> ScImmutableHash { - ScImmutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + ScImmutableHash::new(self.id, PARAM_TOKEN_ID.get_key_id()) } } @@ -273,7 +281,7 @@ pub struct MutableGetApprovedParams { impl MutableGetApprovedParams { pub fn token_id(&self) -> ScMutableHash { - ScMutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + ScMutableHash::new(self.id, PARAM_TOKEN_ID.get_key_id()) } } @@ -284,11 +292,11 @@ pub struct ImmutableIsApprovedForAllParams { impl ImmutableIsApprovedForAllParams { pub fn operator(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_OPERATOR)) + ScImmutableAgentID::new(self.id, PARAM_OPERATOR.get_key_id()) } pub fn owner(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_OWNER)) + ScImmutableAgentID::new(self.id, PARAM_OWNER.get_key_id()) } } @@ -299,11 +307,11 @@ pub struct MutableIsApprovedForAllParams { impl MutableIsApprovedForAllParams { pub fn operator(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_OPERATOR)) + ScMutableAgentID::new(self.id, PARAM_OPERATOR.get_key_id()) } pub fn owner(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_OWNER)) + ScMutableAgentID::new(self.id, PARAM_OWNER.get_key_id()) } } @@ -314,7 +322,7 @@ pub struct ImmutableOwnerOfParams { impl ImmutableOwnerOfParams { pub fn token_id(&self) -> ScImmutableHash { - ScImmutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + ScImmutableHash::new(self.id, PARAM_TOKEN_ID.get_key_id()) } } @@ -325,7 +333,7 @@ pub struct MutableOwnerOfParams { impl MutableOwnerOfParams { pub fn token_id(&self) -> ScMutableHash { - ScMutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + ScMutableHash::new(self.id, PARAM_TOKEN_ID.get_key_id()) } } @@ -336,7 +344,7 @@ pub struct ImmutableTokenURIParams { impl ImmutableTokenURIParams { pub fn token_id(&self) -> ScImmutableHash { - ScImmutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + ScImmutableHash::new(self.id, PARAM_TOKEN_ID.get_key_id()) } } @@ -347,6 +355,6 @@ pub struct MutableTokenURIParams { impl MutableTokenURIParams { pub fn token_id(&self) -> ScMutableHash { - ScMutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + ScMutableHash::new(self.id, PARAM_TOKEN_ID.get_key_id()) } } diff --git a/contracts/wasm/erc721/src/results.rs b/contracts/wasm/erc721/src/results.rs index 7a62221715..12dc895e67 100644 --- a/contracts/wasm/erc721/src/results.rs +++ b/contracts/wasm/erc721/src/results.rs @@ -22,7 +22,7 @@ pub struct ImmutableBalanceOfResults { impl ImmutableBalanceOfResults { pub fn amount(&self) -> ScImmutableUint64 { - ScImmutableUint64::new(self.id, idx_map(IDX_RESULT_AMOUNT)) + ScImmutableUint64::new(self.id, RESULT_AMOUNT.get_key_id()) } } @@ -33,7 +33,7 @@ pub struct MutableBalanceOfResults { impl MutableBalanceOfResults { pub fn amount(&self) -> ScMutableUint64 { - ScMutableUint64::new(self.id, idx_map(IDX_RESULT_AMOUNT)) + ScMutableUint64::new(self.id, RESULT_AMOUNT.get_key_id()) } } @@ -44,7 +44,7 @@ pub struct ImmutableGetApprovedResults { impl ImmutableGetApprovedResults { pub fn approved(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_RESULT_APPROVED)) + ScImmutableAgentID::new(self.id, RESULT_APPROVED.get_key_id()) } } @@ -55,7 +55,7 @@ pub struct MutableGetApprovedResults { impl MutableGetApprovedResults { pub fn approved(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_RESULT_APPROVED)) + ScMutableAgentID::new(self.id, RESULT_APPROVED.get_key_id()) } } @@ -66,7 +66,7 @@ pub struct ImmutableIsApprovedForAllResults { impl ImmutableIsApprovedForAllResults { pub fn approval(&self) -> ScImmutableBool { - ScImmutableBool::new(self.id, idx_map(IDX_RESULT_APPROVAL)) + ScImmutableBool::new(self.id, RESULT_APPROVAL.get_key_id()) } } @@ -77,7 +77,7 @@ pub struct MutableIsApprovedForAllResults { impl MutableIsApprovedForAllResults { pub fn approval(&self) -> ScMutableBool { - ScMutableBool::new(self.id, idx_map(IDX_RESULT_APPROVAL)) + ScMutableBool::new(self.id, RESULT_APPROVAL.get_key_id()) } } @@ -88,7 +88,7 @@ pub struct ImmutableNameResults { impl ImmutableNameResults { pub fn name(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_RESULT_NAME)) + ScImmutableString::new(self.id, RESULT_NAME.get_key_id()) } } @@ -99,7 +99,7 @@ pub struct MutableNameResults { impl MutableNameResults { pub fn name(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_RESULT_NAME)) + ScMutableString::new(self.id, RESULT_NAME.get_key_id()) } } @@ -110,7 +110,7 @@ pub struct ImmutableOwnerOfResults { impl ImmutableOwnerOfResults { pub fn owner(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_RESULT_OWNER)) + ScImmutableAgentID::new(self.id, RESULT_OWNER.get_key_id()) } } @@ -121,7 +121,7 @@ pub struct MutableOwnerOfResults { impl MutableOwnerOfResults { pub fn owner(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_RESULT_OWNER)) + ScMutableAgentID::new(self.id, RESULT_OWNER.get_key_id()) } } @@ -132,7 +132,7 @@ pub struct ImmutableSymbolResults { impl ImmutableSymbolResults { pub fn symbol(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_RESULT_SYMBOL)) + ScImmutableString::new(self.id, RESULT_SYMBOL.get_key_id()) } } @@ -143,7 +143,7 @@ pub struct MutableSymbolResults { impl MutableSymbolResults { pub fn symbol(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_RESULT_SYMBOL)) + ScMutableString::new(self.id, RESULT_SYMBOL.get_key_id()) } } @@ -154,7 +154,7 @@ pub struct ImmutableTokenURIResults { impl ImmutableTokenURIResults { pub fn token_uri(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_RESULT_TOKEN_URI)) + ScImmutableString::new(self.id, RESULT_TOKEN_URI.get_key_id()) } } @@ -165,6 +165,6 @@ pub struct MutableTokenURIResults { impl MutableTokenURIResults { pub fn token_uri(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_RESULT_TOKEN_URI)) + ScMutableString::new(self.id, RESULT_TOKEN_URI.get_key_id()) } } diff --git a/contracts/wasm/erc721/src/state.rs b/contracts/wasm/erc721/src/state.rs index 134d226129..48a77bd618 100644 --- a/contracts/wasm/erc721/src/state.rs +++ b/contracts/wasm/erc721/src/state.rs @@ -15,6 +15,7 @@ use crate::*; use crate::keys::*; use crate::typedefs::*; +#[derive(Clone, Copy)] pub struct MapHashToImmutableAgentID { pub(crate) obj_id: i32, } @@ -25,6 +26,7 @@ impl MapHashToImmutableAgentID { } } +#[derive(Clone, Copy)] pub struct MapAgentIDToImmutableOperators { pub(crate) obj_id: i32, } @@ -36,6 +38,7 @@ impl MapAgentIDToImmutableOperators { } } +#[derive(Clone, Copy)] pub struct MapAgentIDToImmutableUint64 { pub(crate) obj_id: i32, } @@ -46,6 +49,17 @@ impl MapAgentIDToImmutableUint64 { } } +#[derive(Clone, Copy)] +pub struct MapHashToImmutableString { + pub(crate) obj_id: i32, +} + +impl MapHashToImmutableString { + pub fn get_string(&self, key: &ScHash) -> ScImmutableString { + ScImmutableString::new(self.obj_id, key.get_key_id()) + } +} + #[derive(Clone, Copy)] pub struct ImmutableErc721State { pub(crate) id: i32, @@ -53,34 +67,40 @@ pub struct ImmutableErc721State { impl ImmutableErc721State { pub fn approved_accounts(&self) -> MapHashToImmutableAgentID { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_APPROVED_ACCOUNTS), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_APPROVED_ACCOUNTS.get_key_id(), TYPE_MAP); MapHashToImmutableAgentID { obj_id: map_id } } pub fn approved_operators(&self) -> MapAgentIDToImmutableOperators { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_APPROVED_OPERATORS), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_APPROVED_OPERATORS.get_key_id(), TYPE_MAP); MapAgentIDToImmutableOperators { obj_id: map_id } } pub fn balances(&self) -> MapAgentIDToImmutableUint64 { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_BALANCES), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_BALANCES.get_key_id(), TYPE_MAP); MapAgentIDToImmutableUint64 { obj_id: map_id } } pub fn name(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_STATE_NAME)) + ScImmutableString::new(self.id, STATE_NAME.get_key_id()) } pub fn owners(&self) -> MapHashToImmutableAgentID { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_OWNERS), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_OWNERS.get_key_id(), TYPE_MAP); MapHashToImmutableAgentID { obj_id: map_id } } pub fn symbol(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_STATE_SYMBOL)) + ScImmutableString::new(self.id, STATE_SYMBOL.get_key_id()) + } + + pub fn token_ur_is(&self) -> MapHashToImmutableString { + let map_id = get_object_id(self.id, STATE_TOKEN_UR_IS.get_key_id(), TYPE_MAP); + MapHashToImmutableString { obj_id: map_id } } } +#[derive(Clone, Copy)] pub struct MapHashToMutableAgentID { pub(crate) obj_id: i32, } @@ -95,6 +115,7 @@ impl MapHashToMutableAgentID { } } +#[derive(Clone, Copy)] pub struct MapAgentIDToMutableOperators { pub(crate) obj_id: i32, } @@ -110,6 +131,7 @@ impl MapAgentIDToMutableOperators { } } +#[derive(Clone, Copy)] pub struct MapAgentIDToMutableUint64 { pub(crate) obj_id: i32, } @@ -124,37 +146,61 @@ impl MapAgentIDToMutableUint64 { } } +#[derive(Clone, Copy)] +pub struct MapHashToMutableString { + pub(crate) obj_id: i32, +} + +impl MapHashToMutableString { + pub fn clear(&self) { + clear(self.obj_id); + } + + pub fn get_string(&self, key: &ScHash) -> ScMutableString { + ScMutableString::new(self.obj_id, key.get_key_id()) + } +} + #[derive(Clone, Copy)] pub struct MutableErc721State { pub(crate) id: i32, } impl MutableErc721State { + pub fn as_immutable(&self) -> ImmutableErc721State { + ImmutableErc721State { id: self.id } + } + pub fn approved_accounts(&self) -> MapHashToMutableAgentID { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_APPROVED_ACCOUNTS), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_APPROVED_ACCOUNTS.get_key_id(), TYPE_MAP); MapHashToMutableAgentID { obj_id: map_id } } pub fn approved_operators(&self) -> MapAgentIDToMutableOperators { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_APPROVED_OPERATORS), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_APPROVED_OPERATORS.get_key_id(), TYPE_MAP); MapAgentIDToMutableOperators { obj_id: map_id } } pub fn balances(&self) -> MapAgentIDToMutableUint64 { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_BALANCES), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_BALANCES.get_key_id(), TYPE_MAP); MapAgentIDToMutableUint64 { obj_id: map_id } } pub fn name(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_STATE_NAME)) + ScMutableString::new(self.id, STATE_NAME.get_key_id()) } pub fn owners(&self) -> MapHashToMutableAgentID { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_OWNERS), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_OWNERS.get_key_id(), TYPE_MAP); MapHashToMutableAgentID { obj_id: map_id } } pub fn symbol(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_STATE_SYMBOL)) + ScMutableString::new(self.id, STATE_SYMBOL.get_key_id()) + } + + pub fn token_ur_is(&self) -> MapHashToMutableString { + let map_id = get_object_id(self.id, STATE_TOKEN_UR_IS.get_key_id(), TYPE_MAP); + MapHashToMutableString { obj_id: map_id } } } diff --git a/contracts/wasm/erc721/src/typedefs.rs b/contracts/wasm/erc721/src/typedefs.rs index 33eacd20c5..63cd1a30d9 100644 --- a/contracts/wasm/erc721/src/typedefs.rs +++ b/contracts/wasm/erc721/src/typedefs.rs @@ -10,6 +10,7 @@ use wasmlib::*; use wasmlib::host::*; +#[derive(Clone, Copy)] pub struct MapAgentIDToImmutableBool { pub(crate) obj_id: i32, } @@ -22,6 +23,7 @@ impl MapAgentIDToImmutableBool { pub type ImmutableOperators = MapAgentIDToImmutableBool; +#[derive(Clone, Copy)] pub struct MapAgentIDToMutableBool { pub(crate) obj_id: i32, } diff --git a/contracts/wasm/erc721/test/erc721_bg.wasm b/contracts/wasm/erc721/test/erc721_bg.wasm index 5b758abf0e..5031bf39d0 100644 Binary files a/contracts/wasm/erc721/test/erc721_bg.wasm and b/contracts/wasm/erc721/test/erc721_bg.wasm differ diff --git a/contracts/wasm/erc721/ts/erc721/consts.ts b/contracts/wasm/erc721/ts/erc721/consts.ts index 443f42c825..e32306cfa0 100644 --- a/contracts/wasm/erc721/ts/erc721/consts.ts +++ b/contracts/wasm/erc721/ts/erc721/consts.ts @@ -21,6 +21,7 @@ export const ParamOwner = "owner"; export const ParamSymbol = "s"; export const ParamTo = "to"; export const ParamTokenID = "tokenID"; +export const ParamTokenURI = "tokenURI"; export const ResultAmount = "amount"; export const ResultApproval = "approval"; @@ -36,6 +37,7 @@ export const StateBalances = "balances"; export const StateName = "name"; export const StateOwners = "owners"; export const StateSymbol = "symbol"; +export const StateTokenURIs = "tokenURIs"; export const FuncApprove = "approve"; export const FuncBurn = "burn"; diff --git a/contracts/wasm/erc721/ts/erc721/contract.ts b/contracts/wasm/erc721/ts/erc721/contract.ts index 4f33962168..e14506cc23 100644 --- a/contracts/wasm/erc721/ts/erc721/contract.ts +++ b/contracts/wasm/erc721/ts/erc721/contract.ts @@ -14,7 +14,7 @@ export class ApproveCall { } export class ApproveContext { - events: sc.Erc721Events = new sc.Erc721Events(); + events: sc.Erc721Events = new sc.Erc721Events(); params: sc.ImmutableApproveParams = new sc.ImmutableApproveParams(); state: sc.MutableErc721State = new sc.MutableErc721State(); } @@ -25,7 +25,7 @@ export class BurnCall { } export class BurnContext { - events: sc.Erc721Events = new sc.Erc721Events(); + events: sc.Erc721Events = new sc.Erc721Events(); params: sc.ImmutableBurnParams = new sc.ImmutableBurnParams(); state: sc.MutableErc721State = new sc.MutableErc721State(); } @@ -36,7 +36,7 @@ export class InitCall { } export class InitContext { - events: sc.Erc721Events = new sc.Erc721Events(); + events: sc.Erc721Events = new sc.Erc721Events(); params: sc.ImmutableInitParams = new sc.ImmutableInitParams(); state: sc.MutableErc721State = new sc.MutableErc721State(); } @@ -47,7 +47,7 @@ export class MintCall { } export class MintContext { - events: sc.Erc721Events = new sc.Erc721Events(); + events: sc.Erc721Events = new sc.Erc721Events(); params: sc.ImmutableMintParams = new sc.ImmutableMintParams(); state: sc.MutableErc721State = new sc.MutableErc721State(); } @@ -58,7 +58,7 @@ export class SafeTransferFromCall { } export class SafeTransferFromContext { - events: sc.Erc721Events = new sc.Erc721Events(); + events: sc.Erc721Events = new sc.Erc721Events(); params: sc.ImmutableSafeTransferFromParams = new sc.ImmutableSafeTransferFromParams(); state: sc.MutableErc721State = new sc.MutableErc721State(); } @@ -69,7 +69,7 @@ export class SetApprovalForAllCall { } export class SetApprovalForAllContext { - events: sc.Erc721Events = new sc.Erc721Events(); + events: sc.Erc721Events = new sc.Erc721Events(); params: sc.ImmutableSetApprovalForAllParams = new sc.ImmutableSetApprovalForAllParams(); state: sc.MutableErc721State = new sc.MutableErc721State(); } @@ -80,7 +80,7 @@ export class TransferFromCall { } export class TransferFromContext { - events: sc.Erc721Events = new sc.Erc721Events(); + events: sc.Erc721Events = new sc.Erc721Events(); params: sc.ImmutableTransferFromParams = new sc.ImmutableTransferFromParams(); state: sc.MutableErc721State = new sc.MutableErc721State(); } diff --git a/contracts/wasm/erc721/ts/erc721/erc721.ts b/contracts/wasm/erc721/ts/erc721/erc721.ts index 1cd4d73655..3a0612f769 100644 --- a/contracts/wasm/erc721/ts/erc721/erc721.ts +++ b/contracts/wasm/erc721/ts/erc721/erc721.ts @@ -139,6 +139,12 @@ export function funcMint(ctx: wasmlib.ScFuncContext, f: sc.MintContext): void { let tokenOwner = f.state.owners().getAgentID(tokenID); ctx.require(!tokenOwner.exists(), "tokenID already minted"); + // save optional token uri + let tokenURI = f.params.tokenURI(); + if (tokenURI.exists()) { + f.state.tokenURIs().getString(tokenID).setValue(tokenURI.value()); + } + let owner = ctx.caller(); tokenOwner.setValue(owner); let balance = f.state.balances().getUint64(owner); @@ -237,6 +243,11 @@ export function viewSymbol(ctx: wasmlib.ScViewContext, f: sc.SymbolContext): voi export function viewTokenURI(ctx: wasmlib.ScViewContext, f: sc.TokenURIContext): void { let tokenID = f.params.tokenID(); if (tokenID.exists()) { - f.results.tokenURI().setValue(BASE_URI + tokenID.toString()); + let tokenURI = BASE_URI + tokenID.toString(); + let savedURI = f.state.tokenURIs().getString(tokenID.value()); + if (savedURI.exists()) { + tokenURI = savedURI.value(); + } + f.results.tokenURI().setValue(tokenURI); } } diff --git a/contracts/wasm/erc721/ts/erc721/keys.ts b/contracts/wasm/erc721/ts/erc721/keys.ts index d7fc649be8..fc32f134a8 100644 --- a/contracts/wasm/erc721/ts/erc721/keys.ts +++ b/contracts/wasm/erc721/ts/erc721/keys.ts @@ -18,21 +18,23 @@ export const IdxParamOwner = 6; export const IdxParamSymbol = 7; export const IdxParamTo = 8; export const IdxParamTokenID = 9; +export const IdxParamTokenURI = 10; -export const IdxResultAmount = 10; -export const IdxResultApproval = 11; -export const IdxResultApproved = 12; -export const IdxResultName = 13; -export const IdxResultOwner = 14; -export const IdxResultSymbol = 15; -export const IdxResultTokenURI = 16; +export const IdxResultAmount = 11; +export const IdxResultApproval = 12; +export const IdxResultApproved = 13; +export const IdxResultName = 14; +export const IdxResultOwner = 15; +export const IdxResultSymbol = 16; +export const IdxResultTokenURI = 17; -export const IdxStateApprovedAccounts = 17; -export const IdxStateApprovedOperators = 18; -export const IdxStateBalances = 19; -export const IdxStateName = 20; -export const IdxStateOwners = 21; -export const IdxStateSymbol = 22; +export const IdxStateApprovedAccounts = 18; +export const IdxStateApprovedOperators = 19; +export const IdxStateBalances = 20; +export const IdxStateName = 21; +export const IdxStateOwners = 22; +export const IdxStateSymbol = 23; +export const IdxStateTokenURIs = 24; export let keyMap: string[] = [ sc.ParamApproval, @@ -45,6 +47,7 @@ export let keyMap: string[] = [ sc.ParamSymbol, sc.ParamTo, sc.ParamTokenID, + sc.ParamTokenURI, sc.ResultAmount, sc.ResultApproval, sc.ResultApproved, @@ -58,6 +61,7 @@ export let keyMap: string[] = [ sc.StateName, sc.StateOwners, sc.StateSymbol, + sc.StateTokenURIs, ]; export let idxMap: wasmlib.Key32[] = new Array(keyMap.length); diff --git a/contracts/wasm/erc721/ts/erc721/params.ts b/contracts/wasm/erc721/ts/erc721/params.ts index 92eaed30f6..509be4795f 100644 --- a/contracts/wasm/erc721/ts/erc721/params.ts +++ b/contracts/wasm/erc721/ts/erc721/params.ts @@ -10,33 +10,33 @@ import * as sc from "./index"; export class ImmutableApproveParams extends wasmlib.ScMapID { approved(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamApproved]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamApproved)); } tokenID(): wasmlib.ScImmutableHash { - return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + return new wasmlib.ScImmutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamTokenID)); } } export class MutableApproveParams extends wasmlib.ScMapID { approved(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamApproved]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamApproved)); } tokenID(): wasmlib.ScMutableHash { - return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + return new wasmlib.ScMutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamTokenID)); } } export class ImmutableBurnParams extends wasmlib.ScMapID { tokenID(): wasmlib.ScImmutableHash { - return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + return new wasmlib.ScImmutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamTokenID)); } } export class MutableBurnParams extends wasmlib.ScMapID { tokenID(): wasmlib.ScMutableHash { - return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + return new wasmlib.ScMutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamTokenID)); } } @@ -62,164 +62,172 @@ export class MutableInitParams extends wasmlib.ScMapID { export class ImmutableMintParams extends wasmlib.ScMapID { tokenID(): wasmlib.ScImmutableHash { - return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + return new wasmlib.ScImmutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamTokenID)); + } + + tokenURI(): wasmlib.ScImmutableString { + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamTokenURI)); } } export class MutableMintParams extends wasmlib.ScMapID { tokenID(): wasmlib.ScMutableHash { - return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + return new wasmlib.ScMutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamTokenID)); + } + + tokenURI(): wasmlib.ScMutableString { + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamTokenURI)); } } export class ImmutableSafeTransferFromParams extends wasmlib.ScMapID { data(): wasmlib.ScImmutableBytes { - return new wasmlib.ScImmutableBytes(this.mapID, sc.idxMap[sc.IdxParamData]); + return new wasmlib.ScImmutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ParamData)); } from(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamFrom]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamFrom)); } to(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamTo]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamTo)); } tokenID(): wasmlib.ScImmutableHash { - return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + return new wasmlib.ScImmutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamTokenID)); } } export class MutableSafeTransferFromParams extends wasmlib.ScMapID { data(): wasmlib.ScMutableBytes { - return new wasmlib.ScMutableBytes(this.mapID, sc.idxMap[sc.IdxParamData]); + return new wasmlib.ScMutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ParamData)); } from(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamFrom]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamFrom)); } to(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamTo]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamTo)); } tokenID(): wasmlib.ScMutableHash { - return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + return new wasmlib.ScMutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamTokenID)); } } export class ImmutableSetApprovalForAllParams extends wasmlib.ScMapID { approval(): wasmlib.ScImmutableBool { - return new wasmlib.ScImmutableBool(this.mapID, sc.idxMap[sc.IdxParamApproval]); + return new wasmlib.ScImmutableBool(this.mapID, wasmlib.Key32.fromString(sc.ParamApproval)); } operator(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamOperator]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamOperator)); } } export class MutableSetApprovalForAllParams extends wasmlib.ScMapID { approval(): wasmlib.ScMutableBool { - return new wasmlib.ScMutableBool(this.mapID, sc.idxMap[sc.IdxParamApproval]); + return new wasmlib.ScMutableBool(this.mapID, wasmlib.Key32.fromString(sc.ParamApproval)); } operator(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamOperator]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamOperator)); } } export class ImmutableTransferFromParams extends wasmlib.ScMapID { from(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamFrom]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamFrom)); } to(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamTo]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamTo)); } tokenID(): wasmlib.ScImmutableHash { - return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + return new wasmlib.ScImmutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamTokenID)); } } export class MutableTransferFromParams extends wasmlib.ScMapID { from(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamFrom]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamFrom)); } to(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamTo]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamTo)); } tokenID(): wasmlib.ScMutableHash { - return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + return new wasmlib.ScMutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamTokenID)); } } export class ImmutableBalanceOfParams extends wasmlib.ScMapID { owner(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamOwner]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamOwner)); } } export class MutableBalanceOfParams extends wasmlib.ScMapID { owner(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamOwner]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamOwner)); } } export class ImmutableGetApprovedParams extends wasmlib.ScMapID { tokenID(): wasmlib.ScImmutableHash { - return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + return new wasmlib.ScImmutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamTokenID)); } } export class MutableGetApprovedParams extends wasmlib.ScMapID { tokenID(): wasmlib.ScMutableHash { - return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + return new wasmlib.ScMutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamTokenID)); } } export class ImmutableIsApprovedForAllParams extends wasmlib.ScMapID { operator(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamOperator]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamOperator)); } owner(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamOwner]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamOwner)); } } export class MutableIsApprovedForAllParams extends wasmlib.ScMapID { operator(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamOperator]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamOperator)); } owner(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamOwner]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamOwner)); } } export class ImmutableOwnerOfParams extends wasmlib.ScMapID { tokenID(): wasmlib.ScImmutableHash { - return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + return new wasmlib.ScImmutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamTokenID)); } } export class MutableOwnerOfParams extends wasmlib.ScMapID { tokenID(): wasmlib.ScMutableHash { - return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + return new wasmlib.ScMutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamTokenID)); } } export class ImmutableTokenURIParams extends wasmlib.ScMapID { tokenID(): wasmlib.ScImmutableHash { - return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + return new wasmlib.ScImmutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamTokenID)); } } export class MutableTokenURIParams extends wasmlib.ScMapID { tokenID(): wasmlib.ScMutableHash { - return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + return new wasmlib.ScMutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamTokenID)); } } diff --git a/contracts/wasm/erc721/ts/erc721/results.ts b/contracts/wasm/erc721/ts/erc721/results.ts index 34f4237014..30edca4097 100644 --- a/contracts/wasm/erc721/ts/erc721/results.ts +++ b/contracts/wasm/erc721/ts/erc721/results.ts @@ -10,84 +10,84 @@ import * as sc from "./index"; export class ImmutableBalanceOfResults extends wasmlib.ScMapID { amount(): wasmlib.ScImmutableUint64 { - return new wasmlib.ScImmutableUint64(this.mapID, sc.idxMap[sc.IdxResultAmount]); + return new wasmlib.ScImmutableUint64(this.mapID, wasmlib.Key32.fromString(sc.ResultAmount)); } } export class MutableBalanceOfResults extends wasmlib.ScMapID { amount(): wasmlib.ScMutableUint64 { - return new wasmlib.ScMutableUint64(this.mapID, sc.idxMap[sc.IdxResultAmount]); + return new wasmlib.ScMutableUint64(this.mapID, wasmlib.Key32.fromString(sc.ResultAmount)); } } export class ImmutableGetApprovedResults extends wasmlib.ScMapID { approved(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxResultApproved]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ResultApproved)); } } export class MutableGetApprovedResults extends wasmlib.ScMapID { approved(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxResultApproved]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ResultApproved)); } } export class ImmutableIsApprovedForAllResults extends wasmlib.ScMapID { approval(): wasmlib.ScImmutableBool { - return new wasmlib.ScImmutableBool(this.mapID, sc.idxMap[sc.IdxResultApproval]); + return new wasmlib.ScImmutableBool(this.mapID, wasmlib.Key32.fromString(sc.ResultApproval)); } } export class MutableIsApprovedForAllResults extends wasmlib.ScMapID { approval(): wasmlib.ScMutableBool { - return new wasmlib.ScMutableBool(this.mapID, sc.idxMap[sc.IdxResultApproval]); + return new wasmlib.ScMutableBool(this.mapID, wasmlib.Key32.fromString(sc.ResultApproval)); } } export class ImmutableNameResults extends wasmlib.ScMapID { name(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxResultName]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultName)); } } export class MutableNameResults extends wasmlib.ScMapID { name(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxResultName]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultName)); } } export class ImmutableOwnerOfResults extends wasmlib.ScMapID { owner(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxResultOwner]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ResultOwner)); } } export class MutableOwnerOfResults extends wasmlib.ScMapID { owner(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxResultOwner]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ResultOwner)); } } export class ImmutableSymbolResults extends wasmlib.ScMapID { symbol(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxResultSymbol]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultSymbol)); } } export class MutableSymbolResults extends wasmlib.ScMapID { symbol(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxResultSymbol]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultSymbol)); } } export class ImmutableTokenURIResults extends wasmlib.ScMapID { tokenURI(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxResultTokenURI]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultTokenURI)); } } export class MutableTokenURIResults extends wasmlib.ScMapID { tokenURI(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxResultTokenURI]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultTokenURI)); } } diff --git a/contracts/wasm/erc721/ts/erc721/state.ts b/contracts/wasm/erc721/ts/erc721/state.ts index d85b7c9295..b16ed14851 100644 --- a/contracts/wasm/erc721/ts/erc721/state.ts +++ b/contracts/wasm/erc721/ts/erc721/state.ts @@ -45,33 +45,50 @@ export class MapAgentIDToImmutableUint64 { } } +export class MapHashToImmutableString { + objID: i32; + + constructor(objID: i32) { + this.objID = objID; + } + + getString(key: wasmlib.ScHash): wasmlib.ScImmutableString { + return new wasmlib.ScImmutableString(this.objID, key.getKeyID()); + } +} + export class ImmutableErc721State extends wasmlib.ScMapID { approvedAccounts(): sc.MapHashToImmutableAgentID { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateApprovedAccounts], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateApprovedAccounts), wasmlib.TYPE_MAP); return new sc.MapHashToImmutableAgentID(mapID); } approvedOperators(): sc.MapAgentIDToImmutableOperators { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateApprovedOperators], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateApprovedOperators), wasmlib.TYPE_MAP); return new sc.MapAgentIDToImmutableOperators(mapID); } balances(): sc.MapAgentIDToImmutableUint64 { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBalances], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateBalances), wasmlib.TYPE_MAP); return new sc.MapAgentIDToImmutableUint64(mapID); } name(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxStateName]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.StateName)); } owners(): sc.MapHashToImmutableAgentID { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateOwners], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateOwners), wasmlib.TYPE_MAP); return new sc.MapHashToImmutableAgentID(mapID); } symbol(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxStateSymbol]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.StateSymbol)); + } + + tokenURIs(): sc.MapHashToImmutableString { + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateTokenURIs), wasmlib.TYPE_MAP); + return new sc.MapHashToImmutableString(mapID); } } @@ -124,32 +141,59 @@ export class MapAgentIDToMutableUint64 { } } +export class MapHashToMutableString { + objID: i32; + + constructor(objID: i32) { + this.objID = objID; + } + + clear(): void { + wasmlib.clear(this.objID); + } + + getString(key: wasmlib.ScHash): wasmlib.ScMutableString { + return new wasmlib.ScMutableString(this.objID, key.getKeyID()); + } +} + export class MutableErc721State extends wasmlib.ScMapID { + asImmutable(): sc.ImmutableErc721State { + const imm = new sc.ImmutableErc721State(); + imm.mapID = this.mapID; + return imm; + } + approvedAccounts(): sc.MapHashToMutableAgentID { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateApprovedAccounts], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateApprovedAccounts), wasmlib.TYPE_MAP); return new sc.MapHashToMutableAgentID(mapID); } approvedOperators(): sc.MapAgentIDToMutableOperators { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateApprovedOperators], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateApprovedOperators), wasmlib.TYPE_MAP); return new sc.MapAgentIDToMutableOperators(mapID); } balances(): sc.MapAgentIDToMutableUint64 { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBalances], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateBalances), wasmlib.TYPE_MAP); return new sc.MapAgentIDToMutableUint64(mapID); } name(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxStateName]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.StateName)); } owners(): sc.MapHashToMutableAgentID { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateOwners], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateOwners), wasmlib.TYPE_MAP); return new sc.MapHashToMutableAgentID(mapID); } symbol(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxStateSymbol]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.StateSymbol)); + } + + tokenURIs(): sc.MapHashToMutableString { + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateTokenURIs), wasmlib.TYPE_MAP); + return new sc.MapHashToMutableString(mapID); } } diff --git a/contracts/wasm/fairauction/go/fairauction/params.go b/contracts/wasm/fairauction/go/fairauction/params.go index 7e85c051fb..2174a6361a 100644 --- a/contracts/wasm/fairauction/go/fairauction/params.go +++ b/contracts/wasm/fairauction/go/fairauction/params.go @@ -14,7 +14,7 @@ type ImmutableFinalizeAuctionParams struct { } func (s ImmutableFinalizeAuctionParams) Color() wasmlib.ScImmutableColor { - return wasmlib.NewScImmutableColor(s.id, idxMap[IdxParamColor]) + return wasmlib.NewScImmutableColor(s.id, wasmlib.KeyID(ParamColor)) } type MutableFinalizeAuctionParams struct { @@ -22,7 +22,7 @@ type MutableFinalizeAuctionParams struct { } func (s MutableFinalizeAuctionParams) Color() wasmlib.ScMutableColor { - return wasmlib.NewScMutableColor(s.id, idxMap[IdxParamColor]) + return wasmlib.NewScMutableColor(s.id, wasmlib.KeyID(ParamColor)) } type ImmutablePlaceBidParams struct { @@ -30,7 +30,7 @@ type ImmutablePlaceBidParams struct { } func (s ImmutablePlaceBidParams) Color() wasmlib.ScImmutableColor { - return wasmlib.NewScImmutableColor(s.id, idxMap[IdxParamColor]) + return wasmlib.NewScImmutableColor(s.id, wasmlib.KeyID(ParamColor)) } type MutablePlaceBidParams struct { @@ -38,7 +38,7 @@ type MutablePlaceBidParams struct { } func (s MutablePlaceBidParams) Color() wasmlib.ScMutableColor { - return wasmlib.NewScMutableColor(s.id, idxMap[IdxParamColor]) + return wasmlib.NewScMutableColor(s.id, wasmlib.KeyID(ParamColor)) } type ImmutableSetOwnerMarginParams struct { @@ -46,7 +46,7 @@ type ImmutableSetOwnerMarginParams struct { } func (s ImmutableSetOwnerMarginParams) OwnerMargin() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxParamOwnerMargin]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamOwnerMargin)) } type MutableSetOwnerMarginParams struct { @@ -54,7 +54,7 @@ type MutableSetOwnerMarginParams struct { } func (s MutableSetOwnerMarginParams) OwnerMargin() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxParamOwnerMargin]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamOwnerMargin)) } type ImmutableStartAuctionParams struct { @@ -62,19 +62,19 @@ type ImmutableStartAuctionParams struct { } func (s ImmutableStartAuctionParams) Color() wasmlib.ScImmutableColor { - return wasmlib.NewScImmutableColor(s.id, idxMap[IdxParamColor]) + return wasmlib.NewScImmutableColor(s.id, wasmlib.KeyID(ParamColor)) } func (s ImmutableStartAuctionParams) Description() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxParamDescription]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamDescription)) } func (s ImmutableStartAuctionParams) Duration() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, idxMap[IdxParamDuration]) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ParamDuration)) } func (s ImmutableStartAuctionParams) MinimumBid() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxParamMinimumBid]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamMinimumBid)) } type MutableStartAuctionParams struct { @@ -82,19 +82,19 @@ type MutableStartAuctionParams struct { } func (s MutableStartAuctionParams) Color() wasmlib.ScMutableColor { - return wasmlib.NewScMutableColor(s.id, idxMap[IdxParamColor]) + return wasmlib.NewScMutableColor(s.id, wasmlib.KeyID(ParamColor)) } func (s MutableStartAuctionParams) Description() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxParamDescription]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamDescription)) } func (s MutableStartAuctionParams) Duration() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, idxMap[IdxParamDuration]) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ParamDuration)) } func (s MutableStartAuctionParams) MinimumBid() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxParamMinimumBid]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamMinimumBid)) } type ImmutableGetInfoParams struct { @@ -102,7 +102,7 @@ type ImmutableGetInfoParams struct { } func (s ImmutableGetInfoParams) Color() wasmlib.ScImmutableColor { - return wasmlib.NewScImmutableColor(s.id, idxMap[IdxParamColor]) + return wasmlib.NewScImmutableColor(s.id, wasmlib.KeyID(ParamColor)) } type MutableGetInfoParams struct { @@ -110,5 +110,5 @@ type MutableGetInfoParams struct { } func (s MutableGetInfoParams) Color() wasmlib.ScMutableColor { - return wasmlib.NewScMutableColor(s.id, idxMap[IdxParamColor]) + return wasmlib.NewScMutableColor(s.id, wasmlib.KeyID(ParamColor)) } diff --git a/contracts/wasm/fairauction/go/fairauction/results.go b/contracts/wasm/fairauction/go/fairauction/results.go index 3e10283f12..033177634d 100644 --- a/contracts/wasm/fairauction/go/fairauction/results.go +++ b/contracts/wasm/fairauction/go/fairauction/results.go @@ -14,51 +14,51 @@ type ImmutableGetInfoResults struct { } func (s ImmutableGetInfoResults) Bidders() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, idxMap[IdxResultBidders]) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ResultBidders)) } func (s ImmutableGetInfoResults) Color() wasmlib.ScImmutableColor { - return wasmlib.NewScImmutableColor(s.id, idxMap[IdxResultColor]) + return wasmlib.NewScImmutableColor(s.id, wasmlib.KeyID(ResultColor)) } func (s ImmutableGetInfoResults) Creator() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxResultCreator]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ResultCreator)) } func (s ImmutableGetInfoResults) Deposit() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultDeposit]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultDeposit)) } func (s ImmutableGetInfoResults) Description() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxResultDescription]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ResultDescription)) } func (s ImmutableGetInfoResults) Duration() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, idxMap[IdxResultDuration]) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ResultDuration)) } func (s ImmutableGetInfoResults) HighestBid() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultHighestBid]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultHighestBid)) } func (s ImmutableGetInfoResults) HighestBidder() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxResultHighestBidder]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ResultHighestBidder)) } func (s ImmutableGetInfoResults) MinimumBid() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultMinimumBid]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultMinimumBid)) } func (s ImmutableGetInfoResults) NumTokens() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultNumTokens]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultNumTokens)) } func (s ImmutableGetInfoResults) OwnerMargin() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultOwnerMargin]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultOwnerMargin)) } func (s ImmutableGetInfoResults) WhenStarted() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultWhenStarted]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultWhenStarted)) } type MutableGetInfoResults struct { @@ -66,49 +66,49 @@ type MutableGetInfoResults struct { } func (s MutableGetInfoResults) Bidders() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, idxMap[IdxResultBidders]) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ResultBidders)) } func (s MutableGetInfoResults) Color() wasmlib.ScMutableColor { - return wasmlib.NewScMutableColor(s.id, idxMap[IdxResultColor]) + return wasmlib.NewScMutableColor(s.id, wasmlib.KeyID(ResultColor)) } func (s MutableGetInfoResults) Creator() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxResultCreator]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ResultCreator)) } func (s MutableGetInfoResults) Deposit() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultDeposit]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultDeposit)) } func (s MutableGetInfoResults) Description() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxResultDescription]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ResultDescription)) } func (s MutableGetInfoResults) Duration() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, idxMap[IdxResultDuration]) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ResultDuration)) } func (s MutableGetInfoResults) HighestBid() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultHighestBid]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultHighestBid)) } func (s MutableGetInfoResults) HighestBidder() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxResultHighestBidder]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ResultHighestBidder)) } func (s MutableGetInfoResults) MinimumBid() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultMinimumBid]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultMinimumBid)) } func (s MutableGetInfoResults) NumTokens() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultNumTokens]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultNumTokens)) } func (s MutableGetInfoResults) OwnerMargin() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultOwnerMargin]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultOwnerMargin)) } func (s MutableGetInfoResults) WhenStarted() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultWhenStarted]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultWhenStarted)) } diff --git a/contracts/wasm/fairauction/go/fairauction/state.go b/contracts/wasm/fairauction/go/fairauction/state.go index aa6ae8655b..4fce8d8fba 100644 --- a/contracts/wasm/fairauction/go/fairauction/state.go +++ b/contracts/wasm/fairauction/go/fairauction/state.go @@ -40,22 +40,22 @@ type ImmutableFairAuctionState struct { } func (s ImmutableFairAuctionState) Auctions() MapColorToImmutableAuction { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateAuctions], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateAuctions), wasmlib.TYPE_MAP) return MapColorToImmutableAuction{objID: mapID} } func (s ImmutableFairAuctionState) BidderList() MapColorToImmutableBidderList { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateBidderList], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateBidderList), wasmlib.TYPE_MAP) return MapColorToImmutableBidderList{objID: mapID} } func (s ImmutableFairAuctionState) Bids() MapColorToImmutableBids { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateBids], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateBids), wasmlib.TYPE_MAP) return MapColorToImmutableBids{objID: mapID} } func (s ImmutableFairAuctionState) OwnerMargin() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxStateOwnerMargin]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(StateOwnerMargin)) } type MapColorToMutableAuction struct { @@ -100,21 +100,25 @@ type MutableFairAuctionState struct { id int32 } +func (s MutableFairAuctionState) AsImmutable() ImmutableFairAuctionState { + return ImmutableFairAuctionState(s) +} + func (s MutableFairAuctionState) Auctions() MapColorToMutableAuction { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateAuctions], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateAuctions), wasmlib.TYPE_MAP) return MapColorToMutableAuction{objID: mapID} } func (s MutableFairAuctionState) BidderList() MapColorToMutableBidderList { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateBidderList], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateBidderList), wasmlib.TYPE_MAP) return MapColorToMutableBidderList{objID: mapID} } func (s MutableFairAuctionState) Bids() MapColorToMutableBids { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateBids], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateBids), wasmlib.TYPE_MAP) return MapColorToMutableBids{objID: mapID} } func (s MutableFairAuctionState) OwnerMargin() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxStateOwnerMargin]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(StateOwnerMargin)) } diff --git a/contracts/wasm/fairauction/go/main.go b/contracts/wasm/fairauction/go/main.go index be0f4b3c1b..031df458fb 100644 --- a/contracts/wasm/fairauction/go/main.go +++ b/contracts/wasm/fairauction/go/main.go @@ -9,7 +9,7 @@ package main -import "github.com/iotaledger/wasp/packages/vm/wasmclient" +import "github.com/iotaledger/wasp/packages/vm/wasmvmhost" import "github.com/iotaledger/wasp/contracts/wasm/fairauction/go/fairauction" @@ -18,7 +18,7 @@ func main() { //export on_load func onLoad() { - h := &wasmclient.WasmVMHost{} + h := &wasmvmhost.WasmVMHost{} h.ConnectWasmHost() fairauction.OnLoad() } diff --git a/contracts/wasm/fairauction/src/params.rs b/contracts/wasm/fairauction/src/params.rs index 8dcbe76892..bcc902b795 100644 --- a/contracts/wasm/fairauction/src/params.rs +++ b/contracts/wasm/fairauction/src/params.rs @@ -23,7 +23,7 @@ pub struct ImmutableFinalizeAuctionParams { impl ImmutableFinalizeAuctionParams { pub fn color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + ScImmutableColor::new(self.id, PARAM_COLOR.get_key_id()) } } @@ -34,7 +34,7 @@ pub struct MutableFinalizeAuctionParams { impl MutableFinalizeAuctionParams { pub fn color(&self) -> ScMutableColor { - ScMutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + ScMutableColor::new(self.id, PARAM_COLOR.get_key_id()) } } @@ -45,7 +45,7 @@ pub struct ImmutablePlaceBidParams { impl ImmutablePlaceBidParams { pub fn color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + ScImmutableColor::new(self.id, PARAM_COLOR.get_key_id()) } } @@ -56,7 +56,7 @@ pub struct MutablePlaceBidParams { impl MutablePlaceBidParams { pub fn color(&self) -> ScMutableColor { - ScMutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + ScMutableColor::new(self.id, PARAM_COLOR.get_key_id()) } } @@ -67,7 +67,7 @@ pub struct ImmutableSetOwnerMarginParams { impl ImmutableSetOwnerMarginParams { pub fn owner_margin(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_OWNER_MARGIN)) + ScImmutableInt64::new(self.id, PARAM_OWNER_MARGIN.get_key_id()) } } @@ -78,7 +78,7 @@ pub struct MutableSetOwnerMarginParams { impl MutableSetOwnerMarginParams { pub fn owner_margin(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_OWNER_MARGIN)) + ScMutableInt64::new(self.id, PARAM_OWNER_MARGIN.get_key_id()) } } @@ -89,19 +89,19 @@ pub struct ImmutableStartAuctionParams { impl ImmutableStartAuctionParams { pub fn color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + ScImmutableColor::new(self.id, PARAM_COLOR.get_key_id()) } pub fn description(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_DESCRIPTION)) + ScImmutableString::new(self.id, PARAM_DESCRIPTION.get_key_id()) } pub fn duration(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_PARAM_DURATION)) + ScImmutableInt32::new(self.id, PARAM_DURATION.get_key_id()) } pub fn minimum_bid(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_MINIMUM_BID)) + ScImmutableInt64::new(self.id, PARAM_MINIMUM_BID.get_key_id()) } } @@ -112,19 +112,19 @@ pub struct MutableStartAuctionParams { impl MutableStartAuctionParams { pub fn color(&self) -> ScMutableColor { - ScMutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + ScMutableColor::new(self.id, PARAM_COLOR.get_key_id()) } pub fn description(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_DESCRIPTION)) + ScMutableString::new(self.id, PARAM_DESCRIPTION.get_key_id()) } pub fn duration(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_PARAM_DURATION)) + ScMutableInt32::new(self.id, PARAM_DURATION.get_key_id()) } pub fn minimum_bid(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_MINIMUM_BID)) + ScMutableInt64::new(self.id, PARAM_MINIMUM_BID.get_key_id()) } } @@ -135,7 +135,7 @@ pub struct ImmutableGetInfoParams { impl ImmutableGetInfoParams { pub fn color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + ScImmutableColor::new(self.id, PARAM_COLOR.get_key_id()) } } @@ -146,6 +146,6 @@ pub struct MutableGetInfoParams { impl MutableGetInfoParams { pub fn color(&self) -> ScMutableColor { - ScMutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + ScMutableColor::new(self.id, PARAM_COLOR.get_key_id()) } } diff --git a/contracts/wasm/fairauction/src/results.rs b/contracts/wasm/fairauction/src/results.rs index 9c97fda447..649bd85b43 100644 --- a/contracts/wasm/fairauction/src/results.rs +++ b/contracts/wasm/fairauction/src/results.rs @@ -23,51 +23,51 @@ pub struct ImmutableGetInfoResults { impl ImmutableGetInfoResults { pub fn bidders(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_RESULT_BIDDERS)) + ScImmutableInt32::new(self.id, RESULT_BIDDERS.get_key_id()) } pub fn color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, idx_map(IDX_RESULT_COLOR)) + ScImmutableColor::new(self.id, RESULT_COLOR.get_key_id()) } pub fn creator(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_RESULT_CREATOR)) + ScImmutableAgentID::new(self.id, RESULT_CREATOR.get_key_id()) } pub fn deposit(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_DEPOSIT)) + ScImmutableInt64::new(self.id, RESULT_DEPOSIT.get_key_id()) } pub fn description(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_RESULT_DESCRIPTION)) + ScImmutableString::new(self.id, RESULT_DESCRIPTION.get_key_id()) } pub fn duration(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_RESULT_DURATION)) + ScImmutableInt32::new(self.id, RESULT_DURATION.get_key_id()) } pub fn highest_bid(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_HIGHEST_BID)) + ScImmutableInt64::new(self.id, RESULT_HIGHEST_BID.get_key_id()) } pub fn highest_bidder(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_RESULT_HIGHEST_BIDDER)) + ScImmutableAgentID::new(self.id, RESULT_HIGHEST_BIDDER.get_key_id()) } pub fn minimum_bid(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_MINIMUM_BID)) + ScImmutableInt64::new(self.id, RESULT_MINIMUM_BID.get_key_id()) } pub fn num_tokens(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_NUM_TOKENS)) + ScImmutableInt64::new(self.id, RESULT_NUM_TOKENS.get_key_id()) } pub fn owner_margin(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_OWNER_MARGIN)) + ScImmutableInt64::new(self.id, RESULT_OWNER_MARGIN.get_key_id()) } pub fn when_started(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_WHEN_STARTED)) + ScImmutableInt64::new(self.id, RESULT_WHEN_STARTED.get_key_id()) } } @@ -78,50 +78,50 @@ pub struct MutableGetInfoResults { impl MutableGetInfoResults { pub fn bidders(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_RESULT_BIDDERS)) + ScMutableInt32::new(self.id, RESULT_BIDDERS.get_key_id()) } pub fn color(&self) -> ScMutableColor { - ScMutableColor::new(self.id, idx_map(IDX_RESULT_COLOR)) + ScMutableColor::new(self.id, RESULT_COLOR.get_key_id()) } pub fn creator(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_RESULT_CREATOR)) + ScMutableAgentID::new(self.id, RESULT_CREATOR.get_key_id()) } pub fn deposit(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_DEPOSIT)) + ScMutableInt64::new(self.id, RESULT_DEPOSIT.get_key_id()) } pub fn description(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_RESULT_DESCRIPTION)) + ScMutableString::new(self.id, RESULT_DESCRIPTION.get_key_id()) } pub fn duration(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_RESULT_DURATION)) + ScMutableInt32::new(self.id, RESULT_DURATION.get_key_id()) } pub fn highest_bid(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_HIGHEST_BID)) + ScMutableInt64::new(self.id, RESULT_HIGHEST_BID.get_key_id()) } pub fn highest_bidder(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_RESULT_HIGHEST_BIDDER)) + ScMutableAgentID::new(self.id, RESULT_HIGHEST_BIDDER.get_key_id()) } pub fn minimum_bid(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_MINIMUM_BID)) + ScMutableInt64::new(self.id, RESULT_MINIMUM_BID.get_key_id()) } pub fn num_tokens(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_NUM_TOKENS)) + ScMutableInt64::new(self.id, RESULT_NUM_TOKENS.get_key_id()) } pub fn owner_margin(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_OWNER_MARGIN)) + ScMutableInt64::new(self.id, RESULT_OWNER_MARGIN.get_key_id()) } pub fn when_started(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_WHEN_STARTED)) + ScMutableInt64::new(self.id, RESULT_WHEN_STARTED.get_key_id()) } } diff --git a/contracts/wasm/fairauction/src/state.rs b/contracts/wasm/fairauction/src/state.rs index aeff8bb397..8f7b0007f1 100644 --- a/contracts/wasm/fairauction/src/state.rs +++ b/contracts/wasm/fairauction/src/state.rs @@ -16,6 +16,7 @@ use crate::keys::*; use crate::structs::*; use crate::typedefs::*; +#[derive(Clone, Copy)] pub struct MapColorToImmutableAuction { pub(crate) obj_id: i32, } @@ -26,6 +27,7 @@ impl MapColorToImmutableAuction { } } +#[derive(Clone, Copy)] pub struct MapColorToImmutableBidderList { pub(crate) obj_id: i32, } @@ -37,6 +39,7 @@ impl MapColorToImmutableBidderList { } } +#[derive(Clone, Copy)] pub struct MapColorToImmutableBids { pub(crate) obj_id: i32, } @@ -55,25 +58,26 @@ pub struct ImmutableFairAuctionState { impl ImmutableFairAuctionState { pub fn auctions(&self) -> MapColorToImmutableAuction { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_AUCTIONS), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_AUCTIONS.get_key_id(), TYPE_MAP); MapColorToImmutableAuction { obj_id: map_id } } pub fn bidder_list(&self) -> MapColorToImmutableBidderList { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_BIDDER_LIST), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_BIDDER_LIST.get_key_id(), TYPE_MAP); MapColorToImmutableBidderList { obj_id: map_id } } pub fn bids(&self) -> MapColorToImmutableBids { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_BIDS), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_BIDS.get_key_id(), TYPE_MAP); MapColorToImmutableBids { obj_id: map_id } } pub fn owner_margin(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_STATE_OWNER_MARGIN)) + ScImmutableInt64::new(self.id, STATE_OWNER_MARGIN.get_key_id()) } } +#[derive(Clone, Copy)] pub struct MapColorToMutableAuction { pub(crate) obj_id: i32, } @@ -88,6 +92,7 @@ impl MapColorToMutableAuction { } } +#[derive(Clone, Copy)] pub struct MapColorToMutableBidderList { pub(crate) obj_id: i32, } @@ -103,6 +108,7 @@ impl MapColorToMutableBidderList { } } +#[derive(Clone, Copy)] pub struct MapColorToMutableBids { pub(crate) obj_id: i32, } @@ -124,22 +130,26 @@ pub struct MutableFairAuctionState { } impl MutableFairAuctionState { + pub fn as_immutable(&self) -> ImmutableFairAuctionState { + ImmutableFairAuctionState { id: self.id } + } + pub fn auctions(&self) -> MapColorToMutableAuction { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_AUCTIONS), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_AUCTIONS.get_key_id(), TYPE_MAP); MapColorToMutableAuction { obj_id: map_id } } pub fn bidder_list(&self) -> MapColorToMutableBidderList { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_BIDDER_LIST), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_BIDDER_LIST.get_key_id(), TYPE_MAP); MapColorToMutableBidderList { obj_id: map_id } } pub fn bids(&self) -> MapColorToMutableBids { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_BIDS), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_BIDS.get_key_id(), TYPE_MAP); MapColorToMutableBids { obj_id: map_id } } pub fn owner_margin(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_STATE_OWNER_MARGIN)) + ScMutableInt64::new(self.id, STATE_OWNER_MARGIN.get_key_id()) } } diff --git a/contracts/wasm/fairauction/src/structs.rs b/contracts/wasm/fairauction/src/structs.rs index a59feab046..8a0f7e7194 100644 --- a/contracts/wasm/fairauction/src/structs.rs +++ b/contracts/wasm/fairauction/src/structs.rs @@ -12,6 +12,7 @@ use wasmlib::*; use wasmlib::host::*; use crate::typedefs::*; +#[derive(Clone)] pub struct Auction { pub color : ScColor, // color of tokens for sale pub creator : ScAgentID, // issuer of start_auction transaction @@ -61,6 +62,7 @@ impl Auction { } } +#[derive(Clone, Copy)] pub struct ImmutableAuction { pub(crate) obj_id: i32, pub(crate) key_id: Key32, @@ -76,6 +78,7 @@ impl ImmutableAuction { } } +#[derive(Clone, Copy)] pub struct MutableAuction { pub(crate) obj_id: i32, pub(crate) key_id: Key32, @@ -99,6 +102,7 @@ impl MutableAuction { } } +#[derive(Clone)] pub struct Bid { pub amount : i64, // cumulative amount of bids from same bidder pub index : i32, // index of bidder in bidder list @@ -124,6 +128,7 @@ impl Bid { } } +#[derive(Clone, Copy)] pub struct ImmutableBid { pub(crate) obj_id: i32, pub(crate) key_id: Key32, @@ -139,6 +144,7 @@ impl ImmutableBid { } } +#[derive(Clone, Copy)] pub struct MutableBid { pub(crate) obj_id: i32, pub(crate) key_id: Key32, diff --git a/contracts/wasm/fairauction/src/typedefs.rs b/contracts/wasm/fairauction/src/typedefs.rs index dc306d8ad5..83938d4385 100644 --- a/contracts/wasm/fairauction/src/typedefs.rs +++ b/contracts/wasm/fairauction/src/typedefs.rs @@ -11,6 +11,7 @@ use wasmlib::*; use wasmlib::host::*; use crate::structs::*; +#[derive(Clone, Copy)] pub struct ArrayOfImmutableAgentID { pub(crate) obj_id: i32, } @@ -27,6 +28,7 @@ impl ArrayOfImmutableAgentID { pub type ImmutableBidderList = ArrayOfImmutableAgentID; +#[derive(Clone, Copy)] pub struct ArrayOfMutableAgentID { pub(crate) obj_id: i32, } @@ -47,6 +49,7 @@ impl ArrayOfMutableAgentID { pub type MutableBidderList = ArrayOfMutableAgentID; +#[derive(Clone, Copy)] pub struct MapAgentIDToImmutableBid { pub(crate) obj_id: i32, } @@ -59,6 +62,7 @@ impl MapAgentIDToImmutableBid { pub type ImmutableBids = MapAgentIDToImmutableBid; +#[derive(Clone, Copy)] pub struct MapAgentIDToMutableBid { pub(crate) obj_id: i32, } diff --git a/contracts/wasm/fairauction/test/fairauction_bg.wasm b/contracts/wasm/fairauction/test/fairauction_bg.wasm index 86bf39de87..e2ded07e63 100644 Binary files a/contracts/wasm/fairauction/test/fairauction_bg.wasm and b/contracts/wasm/fairauction/test/fairauction_bg.wasm differ diff --git a/contracts/wasm/fairauction/ts/fairauction/params.ts b/contracts/wasm/fairauction/ts/fairauction/params.ts index eccc9a4cb5..ee3ad774c6 100644 --- a/contracts/wasm/fairauction/ts/fairauction/params.ts +++ b/contracts/wasm/fairauction/ts/fairauction/params.ts @@ -10,84 +10,84 @@ import * as sc from "./index"; export class ImmutableFinalizeAuctionParams extends wasmlib.ScMapID { color(): wasmlib.ScImmutableColor { - return new wasmlib.ScImmutableColor(this.mapID, sc.idxMap[sc.IdxParamColor]); + return new wasmlib.ScImmutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamColor)); } } export class MutableFinalizeAuctionParams extends wasmlib.ScMapID { color(): wasmlib.ScMutableColor { - return new wasmlib.ScMutableColor(this.mapID, sc.idxMap[sc.IdxParamColor]); + return new wasmlib.ScMutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamColor)); } } export class ImmutablePlaceBidParams extends wasmlib.ScMapID { color(): wasmlib.ScImmutableColor { - return new wasmlib.ScImmutableColor(this.mapID, sc.idxMap[sc.IdxParamColor]); + return new wasmlib.ScImmutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamColor)); } } export class MutablePlaceBidParams extends wasmlib.ScMapID { color(): wasmlib.ScMutableColor { - return new wasmlib.ScMutableColor(this.mapID, sc.idxMap[sc.IdxParamColor]); + return new wasmlib.ScMutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamColor)); } } export class ImmutableSetOwnerMarginParams extends wasmlib.ScMapID { ownerMargin(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamOwnerMargin]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamOwnerMargin)); } } export class MutableSetOwnerMarginParams extends wasmlib.ScMapID { ownerMargin(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamOwnerMargin]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamOwnerMargin)); } } export class ImmutableStartAuctionParams extends wasmlib.ScMapID { color(): wasmlib.ScImmutableColor { - return new wasmlib.ScImmutableColor(this.mapID, sc.idxMap[sc.IdxParamColor]); + return new wasmlib.ScImmutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamColor)); } description(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamDescription]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamDescription)); } duration(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxParamDuration]); + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamDuration)); } minimumBid(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamMinimumBid]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamMinimumBid)); } } export class MutableStartAuctionParams extends wasmlib.ScMapID { color(): wasmlib.ScMutableColor { - return new wasmlib.ScMutableColor(this.mapID, sc.idxMap[sc.IdxParamColor]); + return new wasmlib.ScMutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamColor)); } description(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamDescription]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamDescription)); } duration(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxParamDuration]); + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamDuration)); } minimumBid(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamMinimumBid]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamMinimumBid)); } } export class ImmutableGetInfoParams extends wasmlib.ScMapID { color(): wasmlib.ScImmutableColor { - return new wasmlib.ScImmutableColor(this.mapID, sc.idxMap[sc.IdxParamColor]); + return new wasmlib.ScImmutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamColor)); } } export class MutableGetInfoParams extends wasmlib.ScMapID { color(): wasmlib.ScMutableColor { - return new wasmlib.ScMutableColor(this.mapID, sc.idxMap[sc.IdxParamColor]); + return new wasmlib.ScMutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamColor)); } } diff --git a/contracts/wasm/fairauction/ts/fairauction/results.ts b/contracts/wasm/fairauction/ts/fairauction/results.ts index 3e55c1bb0e..659f739093 100644 --- a/contracts/wasm/fairauction/ts/fairauction/results.ts +++ b/contracts/wasm/fairauction/ts/fairauction/results.ts @@ -10,100 +10,100 @@ import * as sc from "./index"; export class ImmutableGetInfoResults extends wasmlib.ScMapID { bidders(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxResultBidders]); + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultBidders)); } color(): wasmlib.ScImmutableColor { - return new wasmlib.ScImmutableColor(this.mapID, sc.idxMap[sc.IdxResultColor]); + return new wasmlib.ScImmutableColor(this.mapID, wasmlib.Key32.fromString(sc.ResultColor)); } creator(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxResultCreator]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ResultCreator)); } deposit(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultDeposit]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultDeposit)); } description(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxResultDescription]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultDescription)); } duration(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxResultDuration]); + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultDuration)); } highestBid(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultHighestBid]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultHighestBid)); } highestBidder(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxResultHighestBidder]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ResultHighestBidder)); } minimumBid(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultMinimumBid]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultMinimumBid)); } numTokens(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultNumTokens]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultNumTokens)); } ownerMargin(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultOwnerMargin]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultOwnerMargin)); } whenStarted(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultWhenStarted]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultWhenStarted)); } } export class MutableGetInfoResults extends wasmlib.ScMapID { bidders(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxResultBidders]); + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultBidders)); } color(): wasmlib.ScMutableColor { - return new wasmlib.ScMutableColor(this.mapID, sc.idxMap[sc.IdxResultColor]); + return new wasmlib.ScMutableColor(this.mapID, wasmlib.Key32.fromString(sc.ResultColor)); } creator(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxResultCreator]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ResultCreator)); } deposit(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultDeposit]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultDeposit)); } description(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxResultDescription]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultDescription)); } duration(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxResultDuration]); + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultDuration)); } highestBid(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultHighestBid]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultHighestBid)); } highestBidder(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxResultHighestBidder]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ResultHighestBidder)); } minimumBid(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultMinimumBid]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultMinimumBid)); } numTokens(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultNumTokens]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultNumTokens)); } ownerMargin(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultOwnerMargin]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultOwnerMargin)); } whenStarted(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultWhenStarted]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultWhenStarted)); } } diff --git a/contracts/wasm/fairauction/ts/fairauction/state.ts b/contracts/wasm/fairauction/ts/fairauction/state.ts index cc35e60b89..5c87258728 100644 --- a/contracts/wasm/fairauction/ts/fairauction/state.ts +++ b/contracts/wasm/fairauction/ts/fairauction/state.ts @@ -48,22 +48,22 @@ export class MapColorToImmutableBids { export class ImmutableFairAuctionState extends wasmlib.ScMapID { auctions(): sc.MapColorToImmutableAuction { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateAuctions], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateAuctions), wasmlib.TYPE_MAP); return new sc.MapColorToImmutableAuction(mapID); } bidderList(): sc.MapColorToImmutableBidderList { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBidderList], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateBidderList), wasmlib.TYPE_MAP); return new sc.MapColorToImmutableBidderList(mapID); } bids(): sc.MapColorToImmutableBids { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBids], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateBids), wasmlib.TYPE_MAP); return new sc.MapColorToImmutableBids(mapID); } ownerMargin(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateOwnerMargin]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateOwnerMargin)); } } @@ -118,22 +118,28 @@ export class MapColorToMutableBids { } export class MutableFairAuctionState extends wasmlib.ScMapID { + asImmutable(): sc.ImmutableFairAuctionState { + const imm = new sc.ImmutableFairAuctionState(); + imm.mapID = this.mapID; + return imm; + } + auctions(): sc.MapColorToMutableAuction { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateAuctions], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateAuctions), wasmlib.TYPE_MAP); return new sc.MapColorToMutableAuction(mapID); } bidderList(): sc.MapColorToMutableBidderList { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBidderList], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateBidderList), wasmlib.TYPE_MAP); return new sc.MapColorToMutableBidderList(mapID); } bids(): sc.MapColorToMutableBids { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBids], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateBids), wasmlib.TYPE_MAP); return new sc.MapColorToMutableBids(mapID); } ownerMargin(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateOwnerMargin]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateOwnerMargin)); } } diff --git a/contracts/wasm/fairroulette/frontend/package-lock.json b/contracts/wasm/fairroulette/frontend/package-lock.json index 20257cd895..cccc8d9e98 100644 --- a/contracts/wasm/fairroulette/frontend/package-lock.json +++ b/contracts/wasm/fairroulette/frontend/package-lock.json @@ -4245,12 +4245,6 @@ "glob": "^7.1.2" } }, - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - }, "tsutils": { "version": "3.21.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", diff --git a/contracts/wasm/fairroulette/frontend/package.json b/contracts/wasm/fairroulette/frontend/package.json index db687958bd..3ea890b88c 100644 --- a/contracts/wasm/fairroulette/frontend/package.json +++ b/contracts/wasm/fairroulette/frontend/package.json @@ -42,7 +42,6 @@ "svelte-check": "^2.0.0", "svelte-preprocess": "^4.0.0", "threads": "^1.6.5", - "tslib": "^2.0.0", "tweetnacl": "^1.0.3", "typescript": "^4.0.0", "uuid": "^8.3.2" diff --git a/contracts/wasm/fairroulette/frontend/src/lib/fairroulette_client/fair_roulette_service.ts b/contracts/wasm/fairroulette/frontend/src/lib/fairroulette_client/fair_roulette_service.ts index 8c9e21baf0..a50ff3b622 100644 --- a/contracts/wasm/fairroulette/frontend/src/lib/fairroulette_client/fair_roulette_service.ts +++ b/contracts/wasm/fairroulette/frontend/src/lib/fairroulette_client/fair_roulette_service.ts @@ -62,11 +62,11 @@ export class FairRouletteService { private handleVmMessage(message: string[]): void { const messageHandlers: MessageHandlers = { - 'fairroulette.bet': (index) => { + 'fairroulette.bet': () => { const bet: Bet = { - better: message[index + 2], - amount: Number(message[index + 3]), - betNumber: Number(message[index + 4]), + better: message[2], + amount: Number(message[3]), + betNumber: Number(message[4]), }; this.emitter.emit('betPlaced', bet); @@ -74,8 +74,8 @@ export class FairRouletteService { 'fairroulette.payout': (index) => { const bet: Bet = { - better: message[index + 2], - amount: Number(message[index + 3]), + better: message[2], + amount: Number(message[3]), betNumber: undefined, }; @@ -83,11 +83,11 @@ export class FairRouletteService { }, 'fairroulette.round': (index) => { - this.emitter.emit('roundNumber', message[index + 2] || 0); + this.emitter.emit('roundNumber', message[2] || 0); }, 'fairroulette.start': (index) => { - this.emitter.emit('roundStarted', message[index + 1] || 0); + this.emitter.emit('roundStarted', message[1] || 0); }, 'fairroulette.stop': (index) => { @@ -95,30 +95,24 @@ export class FairRouletteService { }, 'fairroulette.winner': (index) => { - this.emitter.emit('winningNumber', message[index + 2] || 0); + this.emitter.emit('winningNumber', message[2] || 0); }, }; - const topicIndex = 3; - const topic = message[topicIndex]; - + const topic = message[0]; if (typeof messageHandlers[topic] != 'undefined') { - messageHandlers[topic](topicIndex); + messageHandlers[topic](0); } } private handleIncomingMessage(message: MessageEvent): void { - const msg = message.data.toString().split('|'); - - if (msg.length == 0) { - return; - } - - if (msg[0] != 'vmmsg') { + // expect vmmsg contract.event|param1|param2|... + const msg = message.data.toString().split(' '); + if (msg.length != 4 || msg[0] != 'vmmsg') { return; } - - this.handleVmMessage(msg); + const topics = msg[3].split('|'); + this.handleVmMessage(topics); } public async placeBetOffLedger(keyPair: IKeyPair, betNumber: number, take: bigint): Promise { @@ -128,7 +122,7 @@ export class FairRouletteService { balances: [{ balance: take, color: Colors.IOTA_COLOR_BYTES }], contract: HName.HashAsNumber(this.scName), entrypoint: HName.HashAsNumber(this.scPlaceBet), - noonce: BigInt(performance.now() + performance.timeOrigin * 10000000), + nonce: BigInt(performance.now() + performance.timeOrigin * 10000000), }; betRequest = OffLedger.Sign(betRequest, keyPair); diff --git a/contracts/wasm/fairroulette/frontend/src/lib/wasp_client/binary_models/IOffLedger.ts b/contracts/wasm/fairroulette/frontend/src/lib/wasp_client/binary_models/IOffLedger.ts index cbe10ce46f..35e52b1fcb 100644 --- a/contracts/wasm/fairroulette/frontend/src/lib/wasp_client/binary_models/IOffLedger.ts +++ b/contracts/wasm/fairroulette/frontend/src/lib/wasp_client/binary_models/IOffLedger.ts @@ -12,10 +12,11 @@ export interface Balance { export interface IOffLedger { requestType?: number; + chainID: Buffer; contract: number; entrypoint: number; arguments: OffLedgerArgument[]; - noonce: bigint; + nonce: bigint; balances: Balance[]; // Public Key and Signature will get set in the Sign function, so no inital set is required diff --git a/contracts/wasm/fairroulette/frontend/src/lib/wasp_client/binary_models/off_ledger.ts b/contracts/wasm/fairroulette/frontend/src/lib/wasp_client/binary_models/off_ledger.ts index cd9e674287..f25491249d 100644 --- a/contracts/wasm/fairroulette/frontend/src/lib/wasp_client/binary_models/off_ledger.ts +++ b/contracts/wasm/fairroulette/frontend/src/lib/wasp_client/binary_models/off_ledger.ts @@ -7,6 +7,7 @@ import type { IOffLedger } from './IOffLedger'; export class OffLedger { public static ToStruct(buffer: Buffer): IOffLedger { + const chainIDSize = 32; const publicKeySize = 32; const colorLength = 32; const signatureSize = 64; @@ -14,6 +15,7 @@ export class OffLedger { const reader = new SimpleBufferCursor(buffer); const requestType = reader.readIntBE(1); + const chainID = reader.readBytes(chainIDSize); const contract = reader.readUInt32LE(); const entrypoint = reader.readUInt32LE(); const numArguments = reader.readUInt32LE(); @@ -46,11 +48,12 @@ export class OffLedger { const offLedgerStruct: IOffLedger = { requestType: requestType, + chainID: Buffer.from(chainID), contract: contract, entrypoint: entrypoint, arguments: args, publicKey: Buffer.from(publicKey), - noonce: noonce, + nonce: noonce, balances: balances, signature: Buffer.from(signature), }; @@ -61,15 +64,15 @@ export class OffLedger { public static ToBuffer(req: IOffLedger): Buffer { const buffer = new SimpleBufferCursor(Buffer.alloc(0)); - if ([0, 1].includes(req.requestType)) { - buffer.writeIntBE(req.requestType, 1); + if (req.requestType) { + buffer.writeInt8(1); } + buffer.writeBytes(req.chainID); buffer.writeUInt32LE(req.contract); buffer.writeUInt32LE(req.entrypoint); buffer.writeUInt32LE(req.arguments.length || 0); - if (req.arguments) { req.arguments.sort((lhs,rhs)=> lhs.key.localeCompare(rhs.key)); for (const arg of req.arguments) { @@ -78,6 +81,7 @@ export class OffLedger { buffer.writeUInt16LE(keyBuffer.length); buffer.writeBytes(keyBuffer); + //TODO FIXME: always a number? const valueBuffer = Buffer.alloc(8); valueBuffer.writeInt32LE(arg.value, 0); @@ -87,10 +91,9 @@ export class OffLedger { } buffer.writeBytes(req.publicKey); - buffer.writeUInt64LE(req.noonce); + buffer.writeUInt64LE(req.nonce); buffer.writeUInt32LE(req.balances.length || 0); - if (req.balances) { for (const balance of req.balances) { buffer.writeBytes(balance.color); @@ -111,9 +114,10 @@ export class OffLedger { const cleanCopyOfRequest: IOffLedger = { arguments: request.arguments, balances: request.balances, + chainID: request.chainID, contract: request.contract, entrypoint: request.entrypoint, - noonce: request.noonce, + nonce: request.nonce, publicKey: keyPair.publicKey, requestType: null, diff --git a/contracts/wasm/fairroulette/frontend/src/lib/wasp_client/binary_models/on_ledger.ts b/contracts/wasm/fairroulette/frontend/src/lib/wasp_client/binary_models/on_ledger.ts index 968bbaac3b..e991e2d2ee 100644 --- a/contracts/wasm/fairroulette/frontend/src/lib/wasp_client/binary_models/on_ledger.ts +++ b/contracts/wasm/fairroulette/frontend/src/lib/wasp_client/binary_models/on_ledger.ts @@ -11,13 +11,11 @@ export class OnLedger { const numArguments = reader.readUInt32LE(); const args = []; - for (let i = 0; i < numArguments; i++) { const sz16 = reader.readUInt16LE(); const key = reader.readBytes(sz16); const sz32 = reader.readUInt32LE(); const value = reader.readBytes(sz32); - args.push({ key: key, value: value }); } @@ -40,7 +38,6 @@ export class OnLedger { buffer.writeBytes(Buffer.alloc(1, 0)); buffer.writeUInt32LE(req.arguments.length || 0); - if (req.arguments) { req.arguments.sort((lhs,rhs)=> lhs.key.localeCompare(rhs.key)); for (const arg of req.arguments) { diff --git a/contracts/wasm/fairroulette/go/fairroulette/params.go b/contracts/wasm/fairroulette/go/fairroulette/params.go index f049718b87..7a02cc2470 100644 --- a/contracts/wasm/fairroulette/go/fairroulette/params.go +++ b/contracts/wasm/fairroulette/go/fairroulette/params.go @@ -14,7 +14,7 @@ type ImmutablePlaceBetParams struct { } func (s ImmutablePlaceBetParams) Number() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxParamNumber]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamNumber)) } type MutablePlaceBetParams struct { @@ -22,7 +22,7 @@ type MutablePlaceBetParams struct { } func (s MutablePlaceBetParams) Number() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxParamNumber]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamNumber)) } type ImmutablePlayPeriodParams struct { @@ -30,7 +30,7 @@ type ImmutablePlayPeriodParams struct { } func (s ImmutablePlayPeriodParams) PlayPeriod() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, idxMap[IdxParamPlayPeriod]) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ParamPlayPeriod)) } type MutablePlayPeriodParams struct { @@ -38,5 +38,5 @@ type MutablePlayPeriodParams struct { } func (s MutablePlayPeriodParams) PlayPeriod() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, idxMap[IdxParamPlayPeriod]) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ParamPlayPeriod)) } diff --git a/contracts/wasm/fairroulette/go/fairroulette/results.go b/contracts/wasm/fairroulette/go/fairroulette/results.go index 284847a184..8f4946533c 100644 --- a/contracts/wasm/fairroulette/go/fairroulette/results.go +++ b/contracts/wasm/fairroulette/go/fairroulette/results.go @@ -14,7 +14,7 @@ type ImmutableLastWinningNumberResults struct { } func (s ImmutableLastWinningNumberResults) LastWinningNumber() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultLastWinningNumber]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultLastWinningNumber)) } type MutableLastWinningNumberResults struct { @@ -22,7 +22,7 @@ type MutableLastWinningNumberResults struct { } func (s MutableLastWinningNumberResults) LastWinningNumber() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultLastWinningNumber]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultLastWinningNumber)) } type ImmutableRoundNumberResults struct { @@ -30,7 +30,7 @@ type ImmutableRoundNumberResults struct { } func (s ImmutableRoundNumberResults) RoundNumber() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultRoundNumber]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultRoundNumber)) } type MutableRoundNumberResults struct { @@ -38,7 +38,7 @@ type MutableRoundNumberResults struct { } func (s MutableRoundNumberResults) RoundNumber() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultRoundNumber]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultRoundNumber)) } type ImmutableRoundStartedAtResults struct { @@ -46,7 +46,7 @@ type ImmutableRoundStartedAtResults struct { } func (s ImmutableRoundStartedAtResults) RoundStartedAt() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, idxMap[IdxResultRoundStartedAt]) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ResultRoundStartedAt)) } type MutableRoundStartedAtResults struct { @@ -54,7 +54,7 @@ type MutableRoundStartedAtResults struct { } func (s MutableRoundStartedAtResults) RoundStartedAt() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, idxMap[IdxResultRoundStartedAt]) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ResultRoundStartedAt)) } type ImmutableRoundStatusResults struct { @@ -62,7 +62,7 @@ type ImmutableRoundStatusResults struct { } func (s ImmutableRoundStatusResults) RoundStatus() wasmlib.ScImmutableInt16 { - return wasmlib.NewScImmutableInt16(s.id, idxMap[IdxResultRoundStatus]) + return wasmlib.NewScImmutableInt16(s.id, wasmlib.KeyID(ResultRoundStatus)) } type MutableRoundStatusResults struct { @@ -70,5 +70,5 @@ type MutableRoundStatusResults struct { } func (s MutableRoundStatusResults) RoundStatus() wasmlib.ScMutableInt16 { - return wasmlib.NewScMutableInt16(s.id, idxMap[IdxResultRoundStatus]) + return wasmlib.NewScMutableInt16(s.id, wasmlib.KeyID(ResultRoundStatus)) } diff --git a/contracts/wasm/fairroulette/go/fairroulette/state.go b/contracts/wasm/fairroulette/go/fairroulette/state.go index f69f330f7e..e7ce804afe 100644 --- a/contracts/wasm/fairroulette/go/fairroulette/state.go +++ b/contracts/wasm/fairroulette/go/fairroulette/state.go @@ -26,28 +26,28 @@ type ImmutableFairRouletteState struct { } func (s ImmutableFairRouletteState) Bets() ArrayOfImmutableBet { - arrID := wasmlib.GetObjectID(s.id, idxMap[IdxStateBets], wasmlib.TYPE_ARRAY|wasmlib.TYPE_BYTES) + arrID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateBets), wasmlib.TYPE_ARRAY|wasmlib.TYPE_BYTES) return ArrayOfImmutableBet{objID: arrID} } func (s ImmutableFairRouletteState) LastWinningNumber() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxStateLastWinningNumber]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(StateLastWinningNumber)) } func (s ImmutableFairRouletteState) PlayPeriod() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, idxMap[IdxStatePlayPeriod]) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(StatePlayPeriod)) } func (s ImmutableFairRouletteState) RoundNumber() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxStateRoundNumber]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(StateRoundNumber)) } func (s ImmutableFairRouletteState) RoundStartedAt() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, idxMap[IdxStateRoundStartedAt]) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(StateRoundStartedAt)) } func (s ImmutableFairRouletteState) RoundStatus() wasmlib.ScImmutableInt16 { - return wasmlib.NewScImmutableInt16(s.id, idxMap[IdxStateRoundStatus]) + return wasmlib.NewScImmutableInt16(s.id, wasmlib.KeyID(StateRoundStatus)) } type ArrayOfMutableBet struct { @@ -70,27 +70,31 @@ type MutableFairRouletteState struct { id int32 } +func (s MutableFairRouletteState) AsImmutable() ImmutableFairRouletteState { + return ImmutableFairRouletteState(s) +} + func (s MutableFairRouletteState) Bets() ArrayOfMutableBet { - arrID := wasmlib.GetObjectID(s.id, idxMap[IdxStateBets], wasmlib.TYPE_ARRAY|wasmlib.TYPE_BYTES) + arrID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateBets), wasmlib.TYPE_ARRAY|wasmlib.TYPE_BYTES) return ArrayOfMutableBet{objID: arrID} } func (s MutableFairRouletteState) LastWinningNumber() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxStateLastWinningNumber]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(StateLastWinningNumber)) } func (s MutableFairRouletteState) PlayPeriod() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, idxMap[IdxStatePlayPeriod]) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(StatePlayPeriod)) } func (s MutableFairRouletteState) RoundNumber() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxStateRoundNumber]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(StateRoundNumber)) } func (s MutableFairRouletteState) RoundStartedAt() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, idxMap[IdxStateRoundStartedAt]) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(StateRoundStartedAt)) } func (s MutableFairRouletteState) RoundStatus() wasmlib.ScMutableInt16 { - return wasmlib.NewScMutableInt16(s.id, idxMap[IdxStateRoundStatus]) + return wasmlib.NewScMutableInt16(s.id, wasmlib.KeyID(StateRoundStatus)) } diff --git a/contracts/wasm/fairroulette/go/main.go b/contracts/wasm/fairroulette/go/main.go index 17d9e08530..c4f5e312dc 100644 --- a/contracts/wasm/fairroulette/go/main.go +++ b/contracts/wasm/fairroulette/go/main.go @@ -9,7 +9,7 @@ package main -import "github.com/iotaledger/wasp/packages/vm/wasmclient" +import "github.com/iotaledger/wasp/packages/vm/wasmvmhost" import "github.com/iotaledger/wasp/contracts/wasm/fairroulette/go/fairroulette" @@ -18,7 +18,7 @@ func main() { //export on_load func onLoad() { - h := &wasmclient.WasmVMHost{} + h := &wasmvmhost.WasmVMHost{} h.ConnectWasmHost() fairroulette.OnLoad() } diff --git a/contracts/wasm/fairroulette/src/params.rs b/contracts/wasm/fairroulette/src/params.rs index 34de8c2ed4..cfb876a057 100644 --- a/contracts/wasm/fairroulette/src/params.rs +++ b/contracts/wasm/fairroulette/src/params.rs @@ -22,7 +22,7 @@ pub struct ImmutablePlaceBetParams { impl ImmutablePlaceBetParams { pub fn number(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_NUMBER)) + ScImmutableInt64::new(self.id, PARAM_NUMBER.get_key_id()) } } @@ -33,7 +33,7 @@ pub struct MutablePlaceBetParams { impl MutablePlaceBetParams { pub fn number(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_NUMBER)) + ScMutableInt64::new(self.id, PARAM_NUMBER.get_key_id()) } } @@ -44,7 +44,7 @@ pub struct ImmutablePlayPeriodParams { impl ImmutablePlayPeriodParams { pub fn play_period(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_PARAM_PLAY_PERIOD)) + ScImmutableInt32::new(self.id, PARAM_PLAY_PERIOD.get_key_id()) } } @@ -55,6 +55,6 @@ pub struct MutablePlayPeriodParams { impl MutablePlayPeriodParams { pub fn play_period(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_PARAM_PLAY_PERIOD)) + ScMutableInt32::new(self.id, PARAM_PLAY_PERIOD.get_key_id()) } } diff --git a/contracts/wasm/fairroulette/src/results.rs b/contracts/wasm/fairroulette/src/results.rs index 2b6d0b4360..3786d0f879 100644 --- a/contracts/wasm/fairroulette/src/results.rs +++ b/contracts/wasm/fairroulette/src/results.rs @@ -22,7 +22,7 @@ pub struct ImmutableLastWinningNumberResults { impl ImmutableLastWinningNumberResults { pub fn last_winning_number(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_LAST_WINNING_NUMBER)) + ScImmutableInt64::new(self.id, RESULT_LAST_WINNING_NUMBER.get_key_id()) } } @@ -33,7 +33,7 @@ pub struct MutableLastWinningNumberResults { impl MutableLastWinningNumberResults { pub fn last_winning_number(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_LAST_WINNING_NUMBER)) + ScMutableInt64::new(self.id, RESULT_LAST_WINNING_NUMBER.get_key_id()) } } @@ -44,7 +44,7 @@ pub struct ImmutableRoundNumberResults { impl ImmutableRoundNumberResults { pub fn round_number(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_ROUND_NUMBER)) + ScImmutableInt64::new(self.id, RESULT_ROUND_NUMBER.get_key_id()) } } @@ -55,7 +55,7 @@ pub struct MutableRoundNumberResults { impl MutableRoundNumberResults { pub fn round_number(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_ROUND_NUMBER)) + ScMutableInt64::new(self.id, RESULT_ROUND_NUMBER.get_key_id()) } } @@ -66,7 +66,7 @@ pub struct ImmutableRoundStartedAtResults { impl ImmutableRoundStartedAtResults { pub fn round_started_at(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_RESULT_ROUND_STARTED_AT)) + ScImmutableInt32::new(self.id, RESULT_ROUND_STARTED_AT.get_key_id()) } } @@ -77,7 +77,7 @@ pub struct MutableRoundStartedAtResults { impl MutableRoundStartedAtResults { pub fn round_started_at(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_RESULT_ROUND_STARTED_AT)) + ScMutableInt32::new(self.id, RESULT_ROUND_STARTED_AT.get_key_id()) } } @@ -88,7 +88,7 @@ pub struct ImmutableRoundStatusResults { impl ImmutableRoundStatusResults { pub fn round_status(&self) -> ScImmutableInt16 { - ScImmutableInt16::new(self.id, idx_map(IDX_RESULT_ROUND_STATUS)) + ScImmutableInt16::new(self.id, RESULT_ROUND_STATUS.get_key_id()) } } @@ -99,6 +99,6 @@ pub struct MutableRoundStatusResults { impl MutableRoundStatusResults { pub fn round_status(&self) -> ScMutableInt16 { - ScMutableInt16::new(self.id, idx_map(IDX_RESULT_ROUND_STATUS)) + ScMutableInt16::new(self.id, RESULT_ROUND_STATUS.get_key_id()) } } diff --git a/contracts/wasm/fairroulette/src/state.rs b/contracts/wasm/fairroulette/src/state.rs index 7277b6f457..1eab6abc50 100644 --- a/contracts/wasm/fairroulette/src/state.rs +++ b/contracts/wasm/fairroulette/src/state.rs @@ -15,6 +15,7 @@ use crate::*; use crate::keys::*; use crate::structs::*; +#[derive(Clone, Copy)] pub struct ArrayOfImmutableBet { pub(crate) obj_id: i32, } @@ -36,31 +37,32 @@ pub struct ImmutableFairRouletteState { impl ImmutableFairRouletteState { pub fn bets(&self) -> ArrayOfImmutableBet { - let arr_id = get_object_id(self.id, idx_map(IDX_STATE_BETS), TYPE_ARRAY | TYPE_BYTES); + let arr_id = get_object_id(self.id, STATE_BETS.get_key_id(), TYPE_ARRAY | TYPE_BYTES); ArrayOfImmutableBet { obj_id: arr_id } } pub fn last_winning_number(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_STATE_LAST_WINNING_NUMBER)) + ScImmutableInt64::new(self.id, STATE_LAST_WINNING_NUMBER.get_key_id()) } pub fn play_period(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_STATE_PLAY_PERIOD)) + ScImmutableInt32::new(self.id, STATE_PLAY_PERIOD.get_key_id()) } pub fn round_number(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_STATE_ROUND_NUMBER)) + ScImmutableInt64::new(self.id, STATE_ROUND_NUMBER.get_key_id()) } pub fn round_started_at(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_STATE_ROUND_STARTED_AT)) + ScImmutableInt32::new(self.id, STATE_ROUND_STARTED_AT.get_key_id()) } pub fn round_status(&self) -> ScImmutableInt16 { - ScImmutableInt16::new(self.id, idx_map(IDX_STATE_ROUND_STATUS)) + ScImmutableInt16::new(self.id, STATE_ROUND_STATUS.get_key_id()) } } +#[derive(Clone, Copy)] pub struct ArrayOfMutableBet { pub(crate) obj_id: i32, } @@ -85,28 +87,32 @@ pub struct MutableFairRouletteState { } impl MutableFairRouletteState { + pub fn as_immutable(&self) -> ImmutableFairRouletteState { + ImmutableFairRouletteState { id: self.id } + } + pub fn bets(&self) -> ArrayOfMutableBet { - let arr_id = get_object_id(self.id, idx_map(IDX_STATE_BETS), TYPE_ARRAY | TYPE_BYTES); + let arr_id = get_object_id(self.id, STATE_BETS.get_key_id(), TYPE_ARRAY | TYPE_BYTES); ArrayOfMutableBet { obj_id: arr_id } } pub fn last_winning_number(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_STATE_LAST_WINNING_NUMBER)) + ScMutableInt64::new(self.id, STATE_LAST_WINNING_NUMBER.get_key_id()) } pub fn play_period(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_STATE_PLAY_PERIOD)) + ScMutableInt32::new(self.id, STATE_PLAY_PERIOD.get_key_id()) } pub fn round_number(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_STATE_ROUND_NUMBER)) + ScMutableInt64::new(self.id, STATE_ROUND_NUMBER.get_key_id()) } pub fn round_started_at(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_STATE_ROUND_STARTED_AT)) + ScMutableInt32::new(self.id, STATE_ROUND_STARTED_AT.get_key_id()) } pub fn round_status(&self) -> ScMutableInt16 { - ScMutableInt16::new(self.id, idx_map(IDX_STATE_ROUND_STATUS)) + ScMutableInt16::new(self.id, STATE_ROUND_STATUS.get_key_id()) } } diff --git a/contracts/wasm/fairroulette/src/structs.rs b/contracts/wasm/fairroulette/src/structs.rs index 501d719fbf..4bd7f082bc 100644 --- a/contracts/wasm/fairroulette/src/structs.rs +++ b/contracts/wasm/fairroulette/src/structs.rs @@ -11,6 +11,7 @@ use wasmlib::*; use wasmlib::host::*; +#[derive(Clone)] pub struct Bet { pub amount : i64, pub better : ScAgentID, @@ -36,6 +37,7 @@ impl Bet { } } +#[derive(Clone, Copy)] pub struct ImmutableBet { pub(crate) obj_id: i32, pub(crate) key_id: Key32, @@ -51,6 +53,7 @@ impl ImmutableBet { } } +#[derive(Clone, Copy)] pub struct MutableBet { pub(crate) obj_id: i32, pub(crate) key_id: Key32, diff --git a/contracts/wasm/fairroulette/test/fairroulette_bg.wasm b/contracts/wasm/fairroulette/test/fairroulette_bg.wasm index ce7b3e910f..d7ee598864 100644 Binary files a/contracts/wasm/fairroulette/test/fairroulette_bg.wasm and b/contracts/wasm/fairroulette/test/fairroulette_bg.wasm differ diff --git a/contracts/wasm/fairroulette/ts/fairroulette/contract.ts b/contracts/wasm/fairroulette/ts/fairroulette/contract.ts index c612394c71..7b9b6e4bc2 100644 --- a/contracts/wasm/fairroulette/ts/fairroulette/contract.ts +++ b/contracts/wasm/fairroulette/ts/fairroulette/contract.ts @@ -13,7 +13,7 @@ export class ForcePayoutCall { } export class ForcePayoutContext { - events: sc.FairRouletteEvents = new sc.FairRouletteEvents(); + events: sc.FairRouletteEvents = new sc.FairRouletteEvents(); state: sc.MutableFairRouletteState = new sc.MutableFairRouletteState(); } @@ -22,7 +22,7 @@ export class ForceResetCall { } export class ForceResetContext { - events: sc.FairRouletteEvents = new sc.FairRouletteEvents(); + events: sc.FairRouletteEvents = new sc.FairRouletteEvents(); state: sc.MutableFairRouletteState = new sc.MutableFairRouletteState(); } @@ -31,7 +31,7 @@ export class PayWinnersCall { } export class PayWinnersContext { - events: sc.FairRouletteEvents = new sc.FairRouletteEvents(); + events: sc.FairRouletteEvents = new sc.FairRouletteEvents(); state: sc.MutableFairRouletteState = new sc.MutableFairRouletteState(); } @@ -41,7 +41,7 @@ export class PlaceBetCall { } export class PlaceBetContext { - events: sc.FairRouletteEvents = new sc.FairRouletteEvents(); + events: sc.FairRouletteEvents = new sc.FairRouletteEvents(); params: sc.ImmutablePlaceBetParams = new sc.ImmutablePlaceBetParams(); state: sc.MutableFairRouletteState = new sc.MutableFairRouletteState(); } @@ -52,7 +52,7 @@ export class PlayPeriodCall { } export class PlayPeriodContext { - events: sc.FairRouletteEvents = new sc.FairRouletteEvents(); + events: sc.FairRouletteEvents = new sc.FairRouletteEvents(); params: sc.ImmutablePlayPeriodParams = new sc.ImmutablePlayPeriodParams(); state: sc.MutableFairRouletteState = new sc.MutableFairRouletteState(); } diff --git a/contracts/wasm/fairroulette/ts/fairroulette/params.ts b/contracts/wasm/fairroulette/ts/fairroulette/params.ts index d4640d30e3..ca1af44b4a 100644 --- a/contracts/wasm/fairroulette/ts/fairroulette/params.ts +++ b/contracts/wasm/fairroulette/ts/fairroulette/params.ts @@ -10,24 +10,24 @@ import * as sc from "./index"; export class ImmutablePlaceBetParams extends wasmlib.ScMapID { number(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamNumber]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamNumber)); } } export class MutablePlaceBetParams extends wasmlib.ScMapID { number(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamNumber]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamNumber)); } } export class ImmutablePlayPeriodParams extends wasmlib.ScMapID { playPeriod(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxParamPlayPeriod]); + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamPlayPeriod)); } } export class MutablePlayPeriodParams extends wasmlib.ScMapID { playPeriod(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxParamPlayPeriod]); + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamPlayPeriod)); } } diff --git a/contracts/wasm/fairroulette/ts/fairroulette/results.ts b/contracts/wasm/fairroulette/ts/fairroulette/results.ts index 8a55504a12..719f1acc2c 100644 --- a/contracts/wasm/fairroulette/ts/fairroulette/results.ts +++ b/contracts/wasm/fairroulette/ts/fairroulette/results.ts @@ -10,48 +10,48 @@ import * as sc from "./index"; export class ImmutableLastWinningNumberResults extends wasmlib.ScMapID { lastWinningNumber(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultLastWinningNumber]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultLastWinningNumber)); } } export class MutableLastWinningNumberResults extends wasmlib.ScMapID { lastWinningNumber(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultLastWinningNumber]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultLastWinningNumber)); } } export class ImmutableRoundNumberResults extends wasmlib.ScMapID { roundNumber(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultRoundNumber]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultRoundNumber)); } } export class MutableRoundNumberResults extends wasmlib.ScMapID { roundNumber(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultRoundNumber]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultRoundNumber)); } } export class ImmutableRoundStartedAtResults extends wasmlib.ScMapID { roundStartedAt(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxResultRoundStartedAt]); + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultRoundStartedAt)); } } export class MutableRoundStartedAtResults extends wasmlib.ScMapID { roundStartedAt(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxResultRoundStartedAt]); + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultRoundStartedAt)); } } export class ImmutableRoundStatusResults extends wasmlib.ScMapID { roundStatus(): wasmlib.ScImmutableInt16 { - return new wasmlib.ScImmutableInt16(this.mapID, sc.idxMap[sc.IdxResultRoundStatus]); + return new wasmlib.ScImmutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ResultRoundStatus)); } } export class MutableRoundStatusResults extends wasmlib.ScMapID { roundStatus(): wasmlib.ScMutableInt16 { - return new wasmlib.ScMutableInt16(this.mapID, sc.idxMap[sc.IdxResultRoundStatus]); + return new wasmlib.ScMutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ResultRoundStatus)); } } diff --git a/contracts/wasm/fairroulette/ts/fairroulette/state.ts b/contracts/wasm/fairroulette/ts/fairroulette/state.ts index 08059c1fc0..f3eb652c35 100644 --- a/contracts/wasm/fairroulette/ts/fairroulette/state.ts +++ b/contracts/wasm/fairroulette/ts/fairroulette/state.ts @@ -26,28 +26,28 @@ export class ArrayOfImmutableBet { export class ImmutableFairRouletteState extends wasmlib.ScMapID { bets(): sc.ArrayOfImmutableBet { - let arrID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBets], wasmlib.TYPE_ARRAY|wasmlib.TYPE_BYTES); + let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateBets), wasmlib.TYPE_ARRAY|wasmlib.TYPE_BYTES); return new sc.ArrayOfImmutableBet(arrID); } lastWinningNumber(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateLastWinningNumber]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateLastWinningNumber)); } playPeriod(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxStatePlayPeriod]); + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.StatePlayPeriod)); } roundNumber(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateRoundNumber]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateRoundNumber)); } roundStartedAt(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxStateRoundStartedAt]); + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.StateRoundStartedAt)); } roundStatus(): wasmlib.ScImmutableInt16 { - return new wasmlib.ScImmutableInt16(this.mapID, sc.idxMap[sc.IdxStateRoundStatus]); + return new wasmlib.ScImmutableInt16(this.mapID, wasmlib.Key32.fromString(sc.StateRoundStatus)); } } @@ -72,28 +72,34 @@ export class ArrayOfMutableBet { } export class MutableFairRouletteState extends wasmlib.ScMapID { + asImmutable(): sc.ImmutableFairRouletteState { + const imm = new sc.ImmutableFairRouletteState(); + imm.mapID = this.mapID; + return imm; + } + bets(): sc.ArrayOfMutableBet { - let arrID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBets], wasmlib.TYPE_ARRAY|wasmlib.TYPE_BYTES); + let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateBets), wasmlib.TYPE_ARRAY|wasmlib.TYPE_BYTES); return new sc.ArrayOfMutableBet(arrID); } lastWinningNumber(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateLastWinningNumber]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateLastWinningNumber)); } playPeriod(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxStatePlayPeriod]); + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.StatePlayPeriod)); } roundNumber(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateRoundNumber]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateRoundNumber)); } roundStartedAt(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxStateRoundStartedAt]); + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.StateRoundStartedAt)); } roundStatus(): wasmlib.ScMutableInt16 { - return new wasmlib.ScMutableInt16(this.mapID, sc.idxMap[sc.IdxStateRoundStatus]); + return new wasmlib.ScMutableInt16(this.mapID, wasmlib.Key32.fromString(sc.StateRoundStatus)); } } diff --git a/contracts/wasm/helloworld/go/helloworld/results.go b/contracts/wasm/helloworld/go/helloworld/results.go index 4f5c596589..94e77f318a 100644 --- a/contracts/wasm/helloworld/go/helloworld/results.go +++ b/contracts/wasm/helloworld/go/helloworld/results.go @@ -14,7 +14,7 @@ type ImmutableGetHelloWorldResults struct { } func (s ImmutableGetHelloWorldResults) HelloWorld() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxResultHelloWorld]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ResultHelloWorld)) } type MutableGetHelloWorldResults struct { @@ -22,5 +22,5 @@ type MutableGetHelloWorldResults struct { } func (s MutableGetHelloWorldResults) HelloWorld() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxResultHelloWorld]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ResultHelloWorld)) } diff --git a/contracts/wasm/helloworld/go/helloworld/state.go b/contracts/wasm/helloworld/go/helloworld/state.go index 2868513d3d..0b1fb82fcb 100644 --- a/contracts/wasm/helloworld/go/helloworld/state.go +++ b/contracts/wasm/helloworld/go/helloworld/state.go @@ -14,3 +14,7 @@ type ImmutableHelloWorldState struct { type MutableHelloWorldState struct { id int32 } + +func (s MutableHelloWorldState) AsImmutable() ImmutableHelloWorldState { + return ImmutableHelloWorldState(s) +} diff --git a/contracts/wasm/helloworld/go/main.go b/contracts/wasm/helloworld/go/main.go index e91b27bf55..856ecebec4 100644 --- a/contracts/wasm/helloworld/go/main.go +++ b/contracts/wasm/helloworld/go/main.go @@ -9,7 +9,7 @@ package main -import "github.com/iotaledger/wasp/packages/vm/wasmclient" +import "github.com/iotaledger/wasp/packages/vm/wasmvmhost" import "github.com/iotaledger/wasp/contracts/wasm/helloworld/go/helloworld" @@ -18,7 +18,7 @@ func main() { //export on_load func onLoad() { - h := &wasmclient.WasmVMHost{} + h := &wasmvmhost.WasmVMHost{} h.ConnectWasmHost() helloworld.OnLoad() } diff --git a/contracts/wasm/helloworld/src/results.rs b/contracts/wasm/helloworld/src/results.rs index d17c7c68e5..49fc1b6000 100644 --- a/contracts/wasm/helloworld/src/results.rs +++ b/contracts/wasm/helloworld/src/results.rs @@ -21,7 +21,7 @@ pub struct ImmutableGetHelloWorldResults { impl ImmutableGetHelloWorldResults { pub fn hello_world(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_RESULT_HELLO_WORLD)) + ScImmutableString::new(self.id, RESULT_HELLO_WORLD.get_key_id()) } } @@ -32,6 +32,6 @@ pub struct MutableGetHelloWorldResults { impl MutableGetHelloWorldResults { pub fn hello_world(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_RESULT_HELLO_WORLD)) + ScMutableString::new(self.id, RESULT_HELLO_WORLD.get_key_id()) } } diff --git a/contracts/wasm/helloworld/test/helloworld_bg.wasm b/contracts/wasm/helloworld/test/helloworld_bg.wasm index b31d3d581c..3a50d255a5 100644 Binary files a/contracts/wasm/helloworld/test/helloworld_bg.wasm and b/contracts/wasm/helloworld/test/helloworld_bg.wasm differ diff --git a/contracts/wasm/helloworld/ts/helloworld/results.ts b/contracts/wasm/helloworld/ts/helloworld/results.ts index 8af55ab264..b9337efedf 100644 --- a/contracts/wasm/helloworld/ts/helloworld/results.ts +++ b/contracts/wasm/helloworld/ts/helloworld/results.ts @@ -10,12 +10,12 @@ import * as sc from "./index"; export class ImmutableGetHelloWorldResults extends wasmlib.ScMapID { helloWorld(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxResultHelloWorld]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultHelloWorld)); } } export class MutableGetHelloWorldResults extends wasmlib.ScMapID { helloWorld(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxResultHelloWorld]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultHelloWorld)); } } diff --git a/contracts/wasm/helloworld/ts/helloworld/state.ts b/contracts/wasm/helloworld/ts/helloworld/state.ts index d8026bdce6..b1476bca64 100644 --- a/contracts/wasm/helloworld/ts/helloworld/state.ts +++ b/contracts/wasm/helloworld/ts/helloworld/state.ts @@ -12,4 +12,9 @@ export class ImmutableHelloWorldState extends wasmlib.ScMapID { } export class MutableHelloWorldState extends wasmlib.ScMapID { + asImmutable(): sc.ImmutableHelloWorldState { + const imm = new sc.ImmutableHelloWorldState(); + imm.mapID = this.mapID; + return imm; + } } diff --git a/contracts/wasm/inccounter/go/inccounter/params.go b/contracts/wasm/inccounter/go/inccounter/params.go index e3dc8887dc..c9c340257e 100644 --- a/contracts/wasm/inccounter/go/inccounter/params.go +++ b/contracts/wasm/inccounter/go/inccounter/params.go @@ -14,7 +14,7 @@ type ImmutableIncrementWithDelayParams struct { } func (s ImmutableIncrementWithDelayParams) Delay() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, idxMap[IdxParamDelay]) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ParamDelay)) } type MutableIncrementWithDelayParams struct { @@ -22,7 +22,7 @@ type MutableIncrementWithDelayParams struct { } func (s MutableIncrementWithDelayParams) Delay() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, idxMap[IdxParamDelay]) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ParamDelay)) } type ImmutableInitParams struct { @@ -46,7 +46,7 @@ type ImmutableRepeatManyParams struct { } func (s ImmutableRepeatManyParams) NumRepeats() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxParamNumRepeats]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamNumRepeats)) } type MutableRepeatManyParams struct { @@ -54,7 +54,7 @@ type MutableRepeatManyParams struct { } func (s MutableRepeatManyParams) NumRepeats() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxParamNumRepeats]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamNumRepeats)) } type ImmutableWhenMustIncrementParams struct { @@ -62,7 +62,7 @@ type ImmutableWhenMustIncrementParams struct { } func (s ImmutableWhenMustIncrementParams) Dummy() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxParamDummy]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamDummy)) } type MutableWhenMustIncrementParams struct { @@ -70,5 +70,5 @@ type MutableWhenMustIncrementParams struct { } func (s MutableWhenMustIncrementParams) Dummy() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxParamDummy]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamDummy)) } diff --git a/contracts/wasm/inccounter/go/inccounter/results.go b/contracts/wasm/inccounter/go/inccounter/results.go index b197174349..585f59b62f 100644 --- a/contracts/wasm/inccounter/go/inccounter/results.go +++ b/contracts/wasm/inccounter/go/inccounter/results.go @@ -14,7 +14,7 @@ type ImmutableGetCounterResults struct { } func (s ImmutableGetCounterResults) Counter() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultCounter]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultCounter)) } type MutableGetCounterResults struct { @@ -22,5 +22,5 @@ type MutableGetCounterResults struct { } func (s MutableGetCounterResults) Counter() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultCounter]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultCounter)) } diff --git a/contracts/wasm/inccounter/go/inccounter/state.go b/contracts/wasm/inccounter/go/inccounter/state.go index 0795d48060..f406babfb8 100644 --- a/contracts/wasm/inccounter/go/inccounter/state.go +++ b/contracts/wasm/inccounter/go/inccounter/state.go @@ -14,21 +14,25 @@ type ImmutableIncCounterState struct { } func (s ImmutableIncCounterState) Counter() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxStateCounter]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(StateCounter)) } func (s ImmutableIncCounterState) NumRepeats() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxStateNumRepeats]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(StateNumRepeats)) } type MutableIncCounterState struct { id int32 } +func (s MutableIncCounterState) AsImmutable() ImmutableIncCounterState { + return ImmutableIncCounterState(s) +} + func (s MutableIncCounterState) Counter() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxStateCounter]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(StateCounter)) } func (s MutableIncCounterState) NumRepeats() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxStateNumRepeats]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(StateNumRepeats)) } diff --git a/contracts/wasm/inccounter/go/main.go b/contracts/wasm/inccounter/go/main.go index 7a5a3f98bd..47c9e2a29f 100644 --- a/contracts/wasm/inccounter/go/main.go +++ b/contracts/wasm/inccounter/go/main.go @@ -9,7 +9,7 @@ package main -import "github.com/iotaledger/wasp/packages/vm/wasmclient" +import "github.com/iotaledger/wasp/packages/vm/wasmvmhost" import "github.com/iotaledger/wasp/contracts/wasm/inccounter/go/inccounter" @@ -18,7 +18,7 @@ func main() { //export on_load func onLoad() { - h := &wasmclient.WasmVMHost{} + h := &wasmvmhost.WasmVMHost{} h.ConnectWasmHost() inccounter.OnLoad() } diff --git a/contracts/wasm/inccounter/src/params.rs b/contracts/wasm/inccounter/src/params.rs index edcb169d0a..27d5a8ff01 100644 --- a/contracts/wasm/inccounter/src/params.rs +++ b/contracts/wasm/inccounter/src/params.rs @@ -21,7 +21,7 @@ pub struct ImmutableIncrementWithDelayParams { impl ImmutableIncrementWithDelayParams { pub fn delay(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_PARAM_DELAY)) + ScImmutableInt32::new(self.id, PARAM_DELAY.get_key_id()) } } @@ -32,7 +32,7 @@ pub struct MutableIncrementWithDelayParams { impl MutableIncrementWithDelayParams { pub fn delay(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_PARAM_DELAY)) + ScMutableInt32::new(self.id, PARAM_DELAY.get_key_id()) } } @@ -65,7 +65,7 @@ pub struct ImmutableRepeatManyParams { impl ImmutableRepeatManyParams { pub fn num_repeats(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_NUM_REPEATS)) + ScImmutableInt64::new(self.id, PARAM_NUM_REPEATS.get_key_id()) } } @@ -76,7 +76,7 @@ pub struct MutableRepeatManyParams { impl MutableRepeatManyParams { pub fn num_repeats(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_NUM_REPEATS)) + ScMutableInt64::new(self.id, PARAM_NUM_REPEATS.get_key_id()) } } @@ -87,7 +87,7 @@ pub struct ImmutableWhenMustIncrementParams { impl ImmutableWhenMustIncrementParams { pub fn dummy(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_DUMMY)) + ScImmutableInt64::new(self.id, PARAM_DUMMY.get_key_id()) } } @@ -98,6 +98,6 @@ pub struct MutableWhenMustIncrementParams { impl MutableWhenMustIncrementParams { pub fn dummy(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_DUMMY)) + ScMutableInt64::new(self.id, PARAM_DUMMY.get_key_id()) } } diff --git a/contracts/wasm/inccounter/src/results.rs b/contracts/wasm/inccounter/src/results.rs index 74b1aa5bdd..4106744dcb 100644 --- a/contracts/wasm/inccounter/src/results.rs +++ b/contracts/wasm/inccounter/src/results.rs @@ -21,7 +21,7 @@ pub struct ImmutableGetCounterResults { impl ImmutableGetCounterResults { pub fn counter(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_COUNTER)) + ScImmutableInt64::new(self.id, RESULT_COUNTER.get_key_id()) } } @@ -32,6 +32,6 @@ pub struct MutableGetCounterResults { impl MutableGetCounterResults { pub fn counter(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_COUNTER)) + ScMutableInt64::new(self.id, RESULT_COUNTER.get_key_id()) } } diff --git a/contracts/wasm/inccounter/src/state.rs b/contracts/wasm/inccounter/src/state.rs index 36d65f563f..908f5c9aeb 100644 --- a/contracts/wasm/inccounter/src/state.rs +++ b/contracts/wasm/inccounter/src/state.rs @@ -21,11 +21,11 @@ pub struct ImmutableIncCounterState { impl ImmutableIncCounterState { pub fn counter(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_STATE_COUNTER)) + ScImmutableInt64::new(self.id, STATE_COUNTER.get_key_id()) } pub fn num_repeats(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_STATE_NUM_REPEATS)) + ScImmutableInt64::new(self.id, STATE_NUM_REPEATS.get_key_id()) } } @@ -35,11 +35,15 @@ pub struct MutableIncCounterState { } impl MutableIncCounterState { + pub fn as_immutable(&self) -> ImmutableIncCounterState { + ImmutableIncCounterState { id: self.id } + } + pub fn counter(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_STATE_COUNTER)) + ScMutableInt64::new(self.id, STATE_COUNTER.get_key_id()) } pub fn num_repeats(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_STATE_NUM_REPEATS)) + ScMutableInt64::new(self.id, STATE_NUM_REPEATS.get_key_id()) } } diff --git a/contracts/wasm/inccounter/test/inccounter_bg.wasm b/contracts/wasm/inccounter/test/inccounter_bg.wasm index c577e6e18f..8f2f783f82 100644 Binary files a/contracts/wasm/inccounter/test/inccounter_bg.wasm and b/contracts/wasm/inccounter/test/inccounter_bg.wasm differ diff --git a/contracts/wasm/inccounter/ts/inccounter/params.ts b/contracts/wasm/inccounter/ts/inccounter/params.ts index 7d4de79561..b12f5f1fa0 100644 --- a/contracts/wasm/inccounter/ts/inccounter/params.ts +++ b/contracts/wasm/inccounter/ts/inccounter/params.ts @@ -10,13 +10,13 @@ import * as sc from "./index"; export class ImmutableIncrementWithDelayParams extends wasmlib.ScMapID { delay(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxParamDelay]); + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamDelay)); } } export class MutableIncrementWithDelayParams extends wasmlib.ScMapID { delay(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxParamDelay]); + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamDelay)); } } @@ -34,24 +34,24 @@ export class MutableInitParams extends wasmlib.ScMapID { export class ImmutableRepeatManyParams extends wasmlib.ScMapID { numRepeats(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamNumRepeats]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamNumRepeats)); } } export class MutableRepeatManyParams extends wasmlib.ScMapID { numRepeats(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamNumRepeats]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamNumRepeats)); } } export class ImmutableWhenMustIncrementParams extends wasmlib.ScMapID { dummy(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamDummy]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamDummy)); } } export class MutableWhenMustIncrementParams extends wasmlib.ScMapID { dummy(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamDummy]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamDummy)); } } diff --git a/contracts/wasm/inccounter/ts/inccounter/results.ts b/contracts/wasm/inccounter/ts/inccounter/results.ts index db9dc68924..dbb6323dcd 100644 --- a/contracts/wasm/inccounter/ts/inccounter/results.ts +++ b/contracts/wasm/inccounter/ts/inccounter/results.ts @@ -10,12 +10,12 @@ import * as sc from "./index"; export class ImmutableGetCounterResults extends wasmlib.ScMapID { counter(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultCounter]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultCounter)); } } export class MutableGetCounterResults extends wasmlib.ScMapID { counter(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultCounter]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultCounter)); } } diff --git a/contracts/wasm/inccounter/ts/inccounter/state.ts b/contracts/wasm/inccounter/ts/inccounter/state.ts index d292899376..e121f2c893 100644 --- a/contracts/wasm/inccounter/ts/inccounter/state.ts +++ b/contracts/wasm/inccounter/ts/inccounter/state.ts @@ -10,20 +10,26 @@ import * as sc from "./index"; export class ImmutableIncCounterState extends wasmlib.ScMapID { counter(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateCounter]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateCounter)); } numRepeats(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateNumRepeats]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateNumRepeats)); } } export class MutableIncCounterState extends wasmlib.ScMapID { + asImmutable(): sc.ImmutableIncCounterState { + const imm = new sc.ImmutableIncCounterState(); + imm.mapID = this.mapID; + return imm; + } + counter(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateCounter]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateCounter)); } numRepeats(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateNumRepeats]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateNumRepeats)); } } diff --git a/contracts/wasm/testcore/go/main.go b/contracts/wasm/testcore/go/main.go index 44c2dc0972..9d0d44a9eb 100644 --- a/contracts/wasm/testcore/go/main.go +++ b/contracts/wasm/testcore/go/main.go @@ -9,7 +9,7 @@ package main -import "github.com/iotaledger/wasp/packages/vm/wasmclient" +import "github.com/iotaledger/wasp/packages/vm/wasmvmhost" import "github.com/iotaledger/wasp/contracts/wasm/testcore/go/testcore" @@ -18,7 +18,7 @@ func main() { //export on_load func onLoad() { - h := &wasmclient.WasmVMHost{} + h := &wasmvmhost.WasmVMHost{} h.ConnectWasmHost() testcore.OnLoad() } diff --git a/contracts/wasm/testcore/go/testcore/params.go b/contracts/wasm/testcore/go/testcore/params.go index 184b9a295d..d72858d871 100644 --- a/contracts/wasm/testcore/go/testcore/params.go +++ b/contracts/wasm/testcore/go/testcore/params.go @@ -14,15 +14,15 @@ type ImmutableCallOnChainParams struct { } func (s ImmutableCallOnChainParams) HnameContract() wasmlib.ScImmutableHname { - return wasmlib.NewScImmutableHname(s.id, idxMap[IdxParamHnameContract]) + return wasmlib.NewScImmutableHname(s.id, wasmlib.KeyID(ParamHnameContract)) } func (s ImmutableCallOnChainParams) HnameEP() wasmlib.ScImmutableHname { - return wasmlib.NewScImmutableHname(s.id, idxMap[IdxParamHnameEP]) + return wasmlib.NewScImmutableHname(s.id, wasmlib.KeyID(ParamHnameEP)) } func (s ImmutableCallOnChainParams) IntValue() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxParamIntValue]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamIntValue)) } type MutableCallOnChainParams struct { @@ -30,15 +30,15 @@ type MutableCallOnChainParams struct { } func (s MutableCallOnChainParams) HnameContract() wasmlib.ScMutableHname { - return wasmlib.NewScMutableHname(s.id, idxMap[IdxParamHnameContract]) + return wasmlib.NewScMutableHname(s.id, wasmlib.KeyID(ParamHnameContract)) } func (s MutableCallOnChainParams) HnameEP() wasmlib.ScMutableHname { - return wasmlib.NewScMutableHname(s.id, idxMap[IdxParamHnameEP]) + return wasmlib.NewScMutableHname(s.id, wasmlib.KeyID(ParamHnameEP)) } func (s MutableCallOnChainParams) IntValue() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxParamIntValue]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamIntValue)) } type ImmutableCheckContextFromFullEPParams struct { @@ -46,23 +46,23 @@ type ImmutableCheckContextFromFullEPParams struct { } func (s ImmutableCheckContextFromFullEPParams) AgentID() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamAgentID]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamAgentID)) } func (s ImmutableCheckContextFromFullEPParams) Caller() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamCaller]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamCaller)) } func (s ImmutableCheckContextFromFullEPParams) ChainID() wasmlib.ScImmutableChainID { - return wasmlib.NewScImmutableChainID(s.id, idxMap[IdxParamChainID]) + return wasmlib.NewScImmutableChainID(s.id, wasmlib.KeyID(ParamChainID)) } func (s ImmutableCheckContextFromFullEPParams) ChainOwnerID() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamChainOwnerID]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamChainOwnerID)) } func (s ImmutableCheckContextFromFullEPParams) ContractCreator() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamContractCreator]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamContractCreator)) } type MutableCheckContextFromFullEPParams struct { @@ -70,23 +70,23 @@ type MutableCheckContextFromFullEPParams struct { } func (s MutableCheckContextFromFullEPParams) AgentID() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamAgentID]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamAgentID)) } func (s MutableCheckContextFromFullEPParams) Caller() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamCaller]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamCaller)) } func (s MutableCheckContextFromFullEPParams) ChainID() wasmlib.ScMutableChainID { - return wasmlib.NewScMutableChainID(s.id, idxMap[IdxParamChainID]) + return wasmlib.NewScMutableChainID(s.id, wasmlib.KeyID(ParamChainID)) } func (s MutableCheckContextFromFullEPParams) ChainOwnerID() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamChainOwnerID]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamChainOwnerID)) } func (s MutableCheckContextFromFullEPParams) ContractCreator() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamContractCreator]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamContractCreator)) } type ImmutableInitParams struct { @@ -110,47 +110,47 @@ type ImmutablePassTypesFullParams struct { } func (s ImmutablePassTypesFullParams) Address() wasmlib.ScImmutableAddress { - return wasmlib.NewScImmutableAddress(s.id, idxMap[IdxParamAddress]) + return wasmlib.NewScImmutableAddress(s.id, wasmlib.KeyID(ParamAddress)) } func (s ImmutablePassTypesFullParams) AgentID() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamAgentID]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamAgentID)) } func (s ImmutablePassTypesFullParams) ChainID() wasmlib.ScImmutableChainID { - return wasmlib.NewScImmutableChainID(s.id, idxMap[IdxParamChainID]) + return wasmlib.NewScImmutableChainID(s.id, wasmlib.KeyID(ParamChainID)) } func (s ImmutablePassTypesFullParams) ContractID() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamContractID]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamContractID)) } func (s ImmutablePassTypesFullParams) Hash() wasmlib.ScImmutableHash { - return wasmlib.NewScImmutableHash(s.id, idxMap[IdxParamHash]) + return wasmlib.NewScImmutableHash(s.id, wasmlib.KeyID(ParamHash)) } func (s ImmutablePassTypesFullParams) Hname() wasmlib.ScImmutableHname { - return wasmlib.NewScImmutableHname(s.id, idxMap[IdxParamHname]) + return wasmlib.NewScImmutableHname(s.id, wasmlib.KeyID(ParamHname)) } func (s ImmutablePassTypesFullParams) HnameZero() wasmlib.ScImmutableHname { - return wasmlib.NewScImmutableHname(s.id, idxMap[IdxParamHnameZero]) + return wasmlib.NewScImmutableHname(s.id, wasmlib.KeyID(ParamHnameZero)) } func (s ImmutablePassTypesFullParams) Int64() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxParamInt64]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamInt64)) } func (s ImmutablePassTypesFullParams) Int64Zero() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxParamInt64Zero]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamInt64Zero)) } func (s ImmutablePassTypesFullParams) String() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxParamString]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamString)) } func (s ImmutablePassTypesFullParams) StringZero() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxParamStringZero]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamStringZero)) } type MutablePassTypesFullParams struct { @@ -158,47 +158,47 @@ type MutablePassTypesFullParams struct { } func (s MutablePassTypesFullParams) Address() wasmlib.ScMutableAddress { - return wasmlib.NewScMutableAddress(s.id, idxMap[IdxParamAddress]) + return wasmlib.NewScMutableAddress(s.id, wasmlib.KeyID(ParamAddress)) } func (s MutablePassTypesFullParams) AgentID() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamAgentID]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamAgentID)) } func (s MutablePassTypesFullParams) ChainID() wasmlib.ScMutableChainID { - return wasmlib.NewScMutableChainID(s.id, idxMap[IdxParamChainID]) + return wasmlib.NewScMutableChainID(s.id, wasmlib.KeyID(ParamChainID)) } func (s MutablePassTypesFullParams) ContractID() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamContractID]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamContractID)) } func (s MutablePassTypesFullParams) Hash() wasmlib.ScMutableHash { - return wasmlib.NewScMutableHash(s.id, idxMap[IdxParamHash]) + return wasmlib.NewScMutableHash(s.id, wasmlib.KeyID(ParamHash)) } func (s MutablePassTypesFullParams) Hname() wasmlib.ScMutableHname { - return wasmlib.NewScMutableHname(s.id, idxMap[IdxParamHname]) + return wasmlib.NewScMutableHname(s.id, wasmlib.KeyID(ParamHname)) } func (s MutablePassTypesFullParams) HnameZero() wasmlib.ScMutableHname { - return wasmlib.NewScMutableHname(s.id, idxMap[IdxParamHnameZero]) + return wasmlib.NewScMutableHname(s.id, wasmlib.KeyID(ParamHnameZero)) } func (s MutablePassTypesFullParams) Int64() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxParamInt64]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamInt64)) } func (s MutablePassTypesFullParams) Int64Zero() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxParamInt64Zero]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamInt64Zero)) } func (s MutablePassTypesFullParams) String() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxParamString]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamString)) } func (s MutablePassTypesFullParams) StringZero() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxParamStringZero]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamStringZero)) } type ImmutableRunRecursionParams struct { @@ -206,7 +206,7 @@ type ImmutableRunRecursionParams struct { } func (s ImmutableRunRecursionParams) IntValue() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxParamIntValue]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamIntValue)) } type MutableRunRecursionParams struct { @@ -214,7 +214,7 @@ type MutableRunRecursionParams struct { } func (s MutableRunRecursionParams) IntValue() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxParamIntValue]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamIntValue)) } type ImmutableSendToAddressParams struct { @@ -222,7 +222,7 @@ type ImmutableSendToAddressParams struct { } func (s ImmutableSendToAddressParams) Address() wasmlib.ScImmutableAddress { - return wasmlib.NewScImmutableAddress(s.id, idxMap[IdxParamAddress]) + return wasmlib.NewScImmutableAddress(s.id, wasmlib.KeyID(ParamAddress)) } type MutableSendToAddressParams struct { @@ -230,7 +230,7 @@ type MutableSendToAddressParams struct { } func (s MutableSendToAddressParams) Address() wasmlib.ScMutableAddress { - return wasmlib.NewScMutableAddress(s.id, idxMap[IdxParamAddress]) + return wasmlib.NewScMutableAddress(s.id, wasmlib.KeyID(ParamAddress)) } type ImmutableSetIntParams struct { @@ -238,11 +238,11 @@ type ImmutableSetIntParams struct { } func (s ImmutableSetIntParams) IntValue() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxParamIntValue]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamIntValue)) } func (s ImmutableSetIntParams) Name() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxParamName]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamName)) } type MutableSetIntParams struct { @@ -250,11 +250,11 @@ type MutableSetIntParams struct { } func (s MutableSetIntParams) IntValue() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxParamIntValue]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamIntValue)) } func (s MutableSetIntParams) Name() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxParamName]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamName)) } type ImmutableSpawnParams struct { @@ -262,7 +262,7 @@ type ImmutableSpawnParams struct { } func (s ImmutableSpawnParams) ProgHash() wasmlib.ScImmutableHash { - return wasmlib.NewScImmutableHash(s.id, idxMap[IdxParamProgHash]) + return wasmlib.NewScImmutableHash(s.id, wasmlib.KeyID(ParamProgHash)) } type MutableSpawnParams struct { @@ -270,7 +270,7 @@ type MutableSpawnParams struct { } func (s MutableSpawnParams) ProgHash() wasmlib.ScMutableHash { - return wasmlib.NewScMutableHash(s.id, idxMap[IdxParamProgHash]) + return wasmlib.NewScMutableHash(s.id, wasmlib.KeyID(ParamProgHash)) } type ImmutableTestEventLogGenericDataParams struct { @@ -278,7 +278,7 @@ type ImmutableTestEventLogGenericDataParams struct { } func (s ImmutableTestEventLogGenericDataParams) Counter() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxParamCounter]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamCounter)) } type MutableTestEventLogGenericDataParams struct { @@ -286,7 +286,7 @@ type MutableTestEventLogGenericDataParams struct { } func (s MutableTestEventLogGenericDataParams) Counter() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxParamCounter]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamCounter)) } type ImmutableWithdrawToChainParams struct { @@ -294,7 +294,7 @@ type ImmutableWithdrawToChainParams struct { } func (s ImmutableWithdrawToChainParams) ChainID() wasmlib.ScImmutableChainID { - return wasmlib.NewScImmutableChainID(s.id, idxMap[IdxParamChainID]) + return wasmlib.NewScImmutableChainID(s.id, wasmlib.KeyID(ParamChainID)) } type MutableWithdrawToChainParams struct { @@ -302,7 +302,7 @@ type MutableWithdrawToChainParams struct { } func (s MutableWithdrawToChainParams) ChainID() wasmlib.ScMutableChainID { - return wasmlib.NewScMutableChainID(s.id, idxMap[IdxParamChainID]) + return wasmlib.NewScMutableChainID(s.id, wasmlib.KeyID(ParamChainID)) } type ImmutableCheckContextFromViewEPParams struct { @@ -310,19 +310,19 @@ type ImmutableCheckContextFromViewEPParams struct { } func (s ImmutableCheckContextFromViewEPParams) AgentID() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamAgentID]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamAgentID)) } func (s ImmutableCheckContextFromViewEPParams) ChainID() wasmlib.ScImmutableChainID { - return wasmlib.NewScImmutableChainID(s.id, idxMap[IdxParamChainID]) + return wasmlib.NewScImmutableChainID(s.id, wasmlib.KeyID(ParamChainID)) } func (s ImmutableCheckContextFromViewEPParams) ChainOwnerID() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamChainOwnerID]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamChainOwnerID)) } func (s ImmutableCheckContextFromViewEPParams) ContractCreator() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamContractCreator]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamContractCreator)) } type MutableCheckContextFromViewEPParams struct { @@ -330,19 +330,19 @@ type MutableCheckContextFromViewEPParams struct { } func (s MutableCheckContextFromViewEPParams) AgentID() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamAgentID]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamAgentID)) } func (s MutableCheckContextFromViewEPParams) ChainID() wasmlib.ScMutableChainID { - return wasmlib.NewScMutableChainID(s.id, idxMap[IdxParamChainID]) + return wasmlib.NewScMutableChainID(s.id, wasmlib.KeyID(ParamChainID)) } func (s MutableCheckContextFromViewEPParams) ChainOwnerID() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamChainOwnerID]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamChainOwnerID)) } func (s MutableCheckContextFromViewEPParams) ContractCreator() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamContractCreator]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamContractCreator)) } type ImmutableFibonacciParams struct { @@ -350,7 +350,7 @@ type ImmutableFibonacciParams struct { } func (s ImmutableFibonacciParams) IntValue() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxParamIntValue]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamIntValue)) } type MutableFibonacciParams struct { @@ -358,7 +358,7 @@ type MutableFibonacciParams struct { } func (s MutableFibonacciParams) IntValue() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxParamIntValue]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamIntValue)) } type ImmutableGetIntParams struct { @@ -366,7 +366,7 @@ type ImmutableGetIntParams struct { } func (s ImmutableGetIntParams) Name() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxParamName]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamName)) } type MutableGetIntParams struct { @@ -374,7 +374,7 @@ type MutableGetIntParams struct { } func (s MutableGetIntParams) Name() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxParamName]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamName)) } type ImmutableGetStringValueParams struct { @@ -382,7 +382,7 @@ type ImmutableGetStringValueParams struct { } func (s ImmutableGetStringValueParams) VarName() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxParamVarName]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamVarName)) } type MutableGetStringValueParams struct { @@ -390,7 +390,7 @@ type MutableGetStringValueParams struct { } func (s MutableGetStringValueParams) VarName() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxParamVarName]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamVarName)) } type ImmutablePassTypesViewParams struct { @@ -398,47 +398,47 @@ type ImmutablePassTypesViewParams struct { } func (s ImmutablePassTypesViewParams) Address() wasmlib.ScImmutableAddress { - return wasmlib.NewScImmutableAddress(s.id, idxMap[IdxParamAddress]) + return wasmlib.NewScImmutableAddress(s.id, wasmlib.KeyID(ParamAddress)) } func (s ImmutablePassTypesViewParams) AgentID() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamAgentID]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamAgentID)) } func (s ImmutablePassTypesViewParams) ChainID() wasmlib.ScImmutableChainID { - return wasmlib.NewScImmutableChainID(s.id, idxMap[IdxParamChainID]) + return wasmlib.NewScImmutableChainID(s.id, wasmlib.KeyID(ParamChainID)) } func (s ImmutablePassTypesViewParams) ContractID() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamContractID]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamContractID)) } func (s ImmutablePassTypesViewParams) Hash() wasmlib.ScImmutableHash { - return wasmlib.NewScImmutableHash(s.id, idxMap[IdxParamHash]) + return wasmlib.NewScImmutableHash(s.id, wasmlib.KeyID(ParamHash)) } func (s ImmutablePassTypesViewParams) Hname() wasmlib.ScImmutableHname { - return wasmlib.NewScImmutableHname(s.id, idxMap[IdxParamHname]) + return wasmlib.NewScImmutableHname(s.id, wasmlib.KeyID(ParamHname)) } func (s ImmutablePassTypesViewParams) HnameZero() wasmlib.ScImmutableHname { - return wasmlib.NewScImmutableHname(s.id, idxMap[IdxParamHnameZero]) + return wasmlib.NewScImmutableHname(s.id, wasmlib.KeyID(ParamHnameZero)) } func (s ImmutablePassTypesViewParams) Int64() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxParamInt64]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamInt64)) } func (s ImmutablePassTypesViewParams) Int64Zero() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxParamInt64Zero]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamInt64Zero)) } func (s ImmutablePassTypesViewParams) String() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxParamString]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamString)) } func (s ImmutablePassTypesViewParams) StringZero() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxParamStringZero]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamStringZero)) } type MutablePassTypesViewParams struct { @@ -446,45 +446,45 @@ type MutablePassTypesViewParams struct { } func (s MutablePassTypesViewParams) Address() wasmlib.ScMutableAddress { - return wasmlib.NewScMutableAddress(s.id, idxMap[IdxParamAddress]) + return wasmlib.NewScMutableAddress(s.id, wasmlib.KeyID(ParamAddress)) } func (s MutablePassTypesViewParams) AgentID() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamAgentID]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamAgentID)) } func (s MutablePassTypesViewParams) ChainID() wasmlib.ScMutableChainID { - return wasmlib.NewScMutableChainID(s.id, idxMap[IdxParamChainID]) + return wasmlib.NewScMutableChainID(s.id, wasmlib.KeyID(ParamChainID)) } func (s MutablePassTypesViewParams) ContractID() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamContractID]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamContractID)) } func (s MutablePassTypesViewParams) Hash() wasmlib.ScMutableHash { - return wasmlib.NewScMutableHash(s.id, idxMap[IdxParamHash]) + return wasmlib.NewScMutableHash(s.id, wasmlib.KeyID(ParamHash)) } func (s MutablePassTypesViewParams) Hname() wasmlib.ScMutableHname { - return wasmlib.NewScMutableHname(s.id, idxMap[IdxParamHname]) + return wasmlib.NewScMutableHname(s.id, wasmlib.KeyID(ParamHname)) } func (s MutablePassTypesViewParams) HnameZero() wasmlib.ScMutableHname { - return wasmlib.NewScMutableHname(s.id, idxMap[IdxParamHnameZero]) + return wasmlib.NewScMutableHname(s.id, wasmlib.KeyID(ParamHnameZero)) } func (s MutablePassTypesViewParams) Int64() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxParamInt64]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamInt64)) } func (s MutablePassTypesViewParams) Int64Zero() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxParamInt64Zero]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamInt64Zero)) } func (s MutablePassTypesViewParams) String() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxParamString]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamString)) } func (s MutablePassTypesViewParams) StringZero() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxParamStringZero]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamStringZero)) } diff --git a/contracts/wasm/testcore/go/testcore/results.go b/contracts/wasm/testcore/go/testcore/results.go index 1dd993ca93..2d11e8178c 100644 --- a/contracts/wasm/testcore/go/testcore/results.go +++ b/contracts/wasm/testcore/go/testcore/results.go @@ -14,7 +14,7 @@ type ImmutableCallOnChainResults struct { } func (s ImmutableCallOnChainResults) IntValue() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultIntValue]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultIntValue)) } type MutableCallOnChainResults struct { @@ -22,7 +22,7 @@ type MutableCallOnChainResults struct { } func (s MutableCallOnChainResults) IntValue() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultIntValue]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultIntValue)) } type ImmutableGetMintedSupplyResults struct { @@ -30,11 +30,11 @@ type ImmutableGetMintedSupplyResults struct { } func (s ImmutableGetMintedSupplyResults) MintedColor() wasmlib.ScImmutableColor { - return wasmlib.NewScImmutableColor(s.id, idxMap[IdxResultMintedColor]) + return wasmlib.NewScImmutableColor(s.id, wasmlib.KeyID(ResultMintedColor)) } func (s ImmutableGetMintedSupplyResults) MintedSupply() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultMintedSupply]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultMintedSupply)) } type MutableGetMintedSupplyResults struct { @@ -42,11 +42,11 @@ type MutableGetMintedSupplyResults struct { } func (s MutableGetMintedSupplyResults) MintedColor() wasmlib.ScMutableColor { - return wasmlib.NewScMutableColor(s.id, idxMap[IdxResultMintedColor]) + return wasmlib.NewScMutableColor(s.id, wasmlib.KeyID(ResultMintedColor)) } func (s MutableGetMintedSupplyResults) MintedSupply() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultMintedSupply]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultMintedSupply)) } type ImmutableRunRecursionResults struct { @@ -54,7 +54,7 @@ type ImmutableRunRecursionResults struct { } func (s ImmutableRunRecursionResults) IntValue() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultIntValue]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultIntValue)) } type MutableRunRecursionResults struct { @@ -62,7 +62,7 @@ type MutableRunRecursionResults struct { } func (s MutableRunRecursionResults) IntValue() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultIntValue]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultIntValue)) } type ImmutableTestChainOwnerIDFullResults struct { @@ -70,7 +70,7 @@ type ImmutableTestChainOwnerIDFullResults struct { } func (s ImmutableTestChainOwnerIDFullResults) ChainOwnerID() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxResultChainOwnerID]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ResultChainOwnerID)) } type MutableTestChainOwnerIDFullResults struct { @@ -78,7 +78,7 @@ type MutableTestChainOwnerIDFullResults struct { } func (s MutableTestChainOwnerIDFullResults) ChainOwnerID() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxResultChainOwnerID]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ResultChainOwnerID)) } type ImmutableFibonacciResults struct { @@ -86,7 +86,7 @@ type ImmutableFibonacciResults struct { } func (s ImmutableFibonacciResults) IntValue() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultIntValue]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultIntValue)) } type MutableFibonacciResults struct { @@ -94,7 +94,7 @@ type MutableFibonacciResults struct { } func (s MutableFibonacciResults) IntValue() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultIntValue]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultIntValue)) } type ImmutableGetCounterResults struct { @@ -102,7 +102,7 @@ type ImmutableGetCounterResults struct { } func (s ImmutableGetCounterResults) Counter() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultCounter]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultCounter)) } type MutableGetCounterResults struct { @@ -110,7 +110,7 @@ type MutableGetCounterResults struct { } func (s MutableGetCounterResults) Counter() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultCounter]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultCounter)) } type MapStringToImmutableInt64 struct { @@ -190,7 +190,7 @@ type ImmutableTestChainOwnerIDViewResults struct { } func (s ImmutableTestChainOwnerIDViewResults) ChainOwnerID() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxResultChainOwnerID]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ResultChainOwnerID)) } type MutableTestChainOwnerIDViewResults struct { @@ -198,7 +198,7 @@ type MutableTestChainOwnerIDViewResults struct { } func (s MutableTestChainOwnerIDViewResults) ChainOwnerID() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxResultChainOwnerID]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ResultChainOwnerID)) } type ImmutableTestSandboxCallResults struct { @@ -206,7 +206,7 @@ type ImmutableTestSandboxCallResults struct { } func (s ImmutableTestSandboxCallResults) SandboxCall() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxResultSandboxCall]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ResultSandboxCall)) } type MutableTestSandboxCallResults struct { @@ -214,5 +214,5 @@ type MutableTestSandboxCallResults struct { } func (s MutableTestSandboxCallResults) SandboxCall() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxResultSandboxCall]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ResultSandboxCall)) } diff --git a/contracts/wasm/testcore/go/testcore/state.go b/contracts/wasm/testcore/go/testcore/state.go index d0ccc022f7..cb134bf3b5 100644 --- a/contracts/wasm/testcore/go/testcore/state.go +++ b/contracts/wasm/testcore/go/testcore/state.go @@ -14,47 +14,51 @@ type ImmutableTestCoreState struct { } func (s ImmutableTestCoreState) Counter() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxStateCounter]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(StateCounter)) } func (s ImmutableTestCoreState) HnameEP() wasmlib.ScImmutableHname { - return wasmlib.NewScImmutableHname(s.id, idxMap[IdxStateHnameEP]) + return wasmlib.NewScImmutableHname(s.id, wasmlib.KeyID(StateHnameEP)) } func (s ImmutableTestCoreState) Ints() MapStringToImmutableInt64 { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateInts], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateInts), wasmlib.TYPE_MAP) return MapStringToImmutableInt64{objID: mapID} } func (s ImmutableTestCoreState) MintedColor() wasmlib.ScImmutableColor { - return wasmlib.NewScImmutableColor(s.id, idxMap[IdxStateMintedColor]) + return wasmlib.NewScImmutableColor(s.id, wasmlib.KeyID(StateMintedColor)) } func (s ImmutableTestCoreState) MintedSupply() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxStateMintedSupply]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(StateMintedSupply)) } type MutableTestCoreState struct { id int32 } +func (s MutableTestCoreState) AsImmutable() ImmutableTestCoreState { + return ImmutableTestCoreState(s) +} + func (s MutableTestCoreState) Counter() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxStateCounter]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(StateCounter)) } func (s MutableTestCoreState) HnameEP() wasmlib.ScMutableHname { - return wasmlib.NewScMutableHname(s.id, idxMap[IdxStateHnameEP]) + return wasmlib.NewScMutableHname(s.id, wasmlib.KeyID(StateHnameEP)) } func (s MutableTestCoreState) Ints() MapStringToMutableInt64 { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateInts], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateInts), wasmlib.TYPE_MAP) return MapStringToMutableInt64{objID: mapID} } func (s MutableTestCoreState) MintedColor() wasmlib.ScMutableColor { - return wasmlib.NewScMutableColor(s.id, idxMap[IdxStateMintedColor]) + return wasmlib.NewScMutableColor(s.id, wasmlib.KeyID(StateMintedColor)) } func (s MutableTestCoreState) MintedSupply() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxStateMintedSupply]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(StateMintedSupply)) } diff --git a/contracts/wasm/testcore/src/params.rs b/contracts/wasm/testcore/src/params.rs index ef58895846..50c879a7fc 100644 --- a/contracts/wasm/testcore/src/params.rs +++ b/contracts/wasm/testcore/src/params.rs @@ -21,15 +21,15 @@ pub struct ImmutableCallOnChainParams { impl ImmutableCallOnChainParams { pub fn hname_contract(&self) -> ScImmutableHname { - ScImmutableHname::new(self.id, idx_map(IDX_PARAM_HNAME_CONTRACT)) + ScImmutableHname::new(self.id, PARAM_HNAME_CONTRACT.get_key_id()) } pub fn hname_ep(&self) -> ScImmutableHname { - ScImmutableHname::new(self.id, idx_map(IDX_PARAM_HNAME_EP)) + ScImmutableHname::new(self.id, PARAM_HNAME_EP.get_key_id()) } pub fn int_value(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_INT_VALUE)) + ScImmutableInt64::new(self.id, PARAM_INT_VALUE.get_key_id()) } } @@ -40,15 +40,15 @@ pub struct MutableCallOnChainParams { impl MutableCallOnChainParams { pub fn hname_contract(&self) -> ScMutableHname { - ScMutableHname::new(self.id, idx_map(IDX_PARAM_HNAME_CONTRACT)) + ScMutableHname::new(self.id, PARAM_HNAME_CONTRACT.get_key_id()) } pub fn hname_ep(&self) -> ScMutableHname { - ScMutableHname::new(self.id, idx_map(IDX_PARAM_HNAME_EP)) + ScMutableHname::new(self.id, PARAM_HNAME_EP.get_key_id()) } pub fn int_value(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_INT_VALUE)) + ScMutableInt64::new(self.id, PARAM_INT_VALUE.get_key_id()) } } @@ -59,23 +59,23 @@ pub struct ImmutableCheckContextFromFullEPParams { impl ImmutableCheckContextFromFullEPParams { pub fn agent_id(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_AGENT_ID)) + ScImmutableAgentID::new(self.id, PARAM_AGENT_ID.get_key_id()) } pub fn caller(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CALLER)) + ScImmutableAgentID::new(self.id, PARAM_CALLER.get_key_id()) } pub fn chain_id(&self) -> ScImmutableChainID { - ScImmutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) + ScImmutableChainID::new(self.id, PARAM_CHAIN_ID.get_key_id()) } pub fn chain_owner_id(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CHAIN_OWNER_ID)) + ScImmutableAgentID::new(self.id, PARAM_CHAIN_OWNER_ID.get_key_id()) } pub fn contract_creator(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_CREATOR)) + ScImmutableAgentID::new(self.id, PARAM_CONTRACT_CREATOR.get_key_id()) } } @@ -86,23 +86,23 @@ pub struct MutableCheckContextFromFullEPParams { impl MutableCheckContextFromFullEPParams { pub fn agent_id(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_AGENT_ID)) + ScMutableAgentID::new(self.id, PARAM_AGENT_ID.get_key_id()) } pub fn caller(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CALLER)) + ScMutableAgentID::new(self.id, PARAM_CALLER.get_key_id()) } pub fn chain_id(&self) -> ScMutableChainID { - ScMutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) + ScMutableChainID::new(self.id, PARAM_CHAIN_ID.get_key_id()) } pub fn chain_owner_id(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CHAIN_OWNER_ID)) + ScMutableAgentID::new(self.id, PARAM_CHAIN_OWNER_ID.get_key_id()) } pub fn contract_creator(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_CREATOR)) + ScMutableAgentID::new(self.id, PARAM_CONTRACT_CREATOR.get_key_id()) } } @@ -135,47 +135,47 @@ pub struct ImmutablePassTypesFullParams { impl ImmutablePassTypesFullParams { pub fn address(&self) -> ScImmutableAddress { - ScImmutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) + ScImmutableAddress::new(self.id, PARAM_ADDRESS.get_key_id()) } pub fn agent_id(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_AGENT_ID)) + ScImmutableAgentID::new(self.id, PARAM_AGENT_ID.get_key_id()) } pub fn chain_id(&self) -> ScImmutableChainID { - ScImmutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) + ScImmutableChainID::new(self.id, PARAM_CHAIN_ID.get_key_id()) } pub fn contract_id(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_ID)) + ScImmutableAgentID::new(self.id, PARAM_CONTRACT_ID.get_key_id()) } pub fn hash(&self) -> ScImmutableHash { - ScImmutableHash::new(self.id, idx_map(IDX_PARAM_HASH)) + ScImmutableHash::new(self.id, PARAM_HASH.get_key_id()) } pub fn hname(&self) -> ScImmutableHname { - ScImmutableHname::new(self.id, idx_map(IDX_PARAM_HNAME)) + ScImmutableHname::new(self.id, PARAM_HNAME.get_key_id()) } pub fn hname_zero(&self) -> ScImmutableHname { - ScImmutableHname::new(self.id, idx_map(IDX_PARAM_HNAME_ZERO)) + ScImmutableHname::new(self.id, PARAM_HNAME_ZERO.get_key_id()) } pub fn int64(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_INT64)) + ScImmutableInt64::new(self.id, PARAM_INT64.get_key_id()) } pub fn int64_zero(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_INT64_ZERO)) + ScImmutableInt64::new(self.id, PARAM_INT64_ZERO.get_key_id()) } pub fn string(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_STRING)) + ScImmutableString::new(self.id, PARAM_STRING.get_key_id()) } pub fn string_zero(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_STRING_ZERO)) + ScImmutableString::new(self.id, PARAM_STRING_ZERO.get_key_id()) } } @@ -186,47 +186,47 @@ pub struct MutablePassTypesFullParams { impl MutablePassTypesFullParams { pub fn address(&self) -> ScMutableAddress { - ScMutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) + ScMutableAddress::new(self.id, PARAM_ADDRESS.get_key_id()) } pub fn agent_id(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_AGENT_ID)) + ScMutableAgentID::new(self.id, PARAM_AGENT_ID.get_key_id()) } pub fn chain_id(&self) -> ScMutableChainID { - ScMutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) + ScMutableChainID::new(self.id, PARAM_CHAIN_ID.get_key_id()) } pub fn contract_id(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_ID)) + ScMutableAgentID::new(self.id, PARAM_CONTRACT_ID.get_key_id()) } pub fn hash(&self) -> ScMutableHash { - ScMutableHash::new(self.id, idx_map(IDX_PARAM_HASH)) + ScMutableHash::new(self.id, PARAM_HASH.get_key_id()) } pub fn hname(&self) -> ScMutableHname { - ScMutableHname::new(self.id, idx_map(IDX_PARAM_HNAME)) + ScMutableHname::new(self.id, PARAM_HNAME.get_key_id()) } pub fn hname_zero(&self) -> ScMutableHname { - ScMutableHname::new(self.id, idx_map(IDX_PARAM_HNAME_ZERO)) + ScMutableHname::new(self.id, PARAM_HNAME_ZERO.get_key_id()) } pub fn int64(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_INT64)) + ScMutableInt64::new(self.id, PARAM_INT64.get_key_id()) } pub fn int64_zero(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_INT64_ZERO)) + ScMutableInt64::new(self.id, PARAM_INT64_ZERO.get_key_id()) } pub fn string(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_STRING)) + ScMutableString::new(self.id, PARAM_STRING.get_key_id()) } pub fn string_zero(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_STRING_ZERO)) + ScMutableString::new(self.id, PARAM_STRING_ZERO.get_key_id()) } } @@ -237,7 +237,7 @@ pub struct ImmutableRunRecursionParams { impl ImmutableRunRecursionParams { pub fn int_value(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_INT_VALUE)) + ScImmutableInt64::new(self.id, PARAM_INT_VALUE.get_key_id()) } } @@ -248,7 +248,7 @@ pub struct MutableRunRecursionParams { impl MutableRunRecursionParams { pub fn int_value(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_INT_VALUE)) + ScMutableInt64::new(self.id, PARAM_INT_VALUE.get_key_id()) } } @@ -259,7 +259,7 @@ pub struct ImmutableSendToAddressParams { impl ImmutableSendToAddressParams { pub fn address(&self) -> ScImmutableAddress { - ScImmutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) + ScImmutableAddress::new(self.id, PARAM_ADDRESS.get_key_id()) } } @@ -270,7 +270,7 @@ pub struct MutableSendToAddressParams { impl MutableSendToAddressParams { pub fn address(&self) -> ScMutableAddress { - ScMutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) + ScMutableAddress::new(self.id, PARAM_ADDRESS.get_key_id()) } } @@ -281,11 +281,11 @@ pub struct ImmutableSetIntParams { impl ImmutableSetIntParams { pub fn int_value(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_INT_VALUE)) + ScImmutableInt64::new(self.id, PARAM_INT_VALUE.get_key_id()) } pub fn name(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + ScImmutableString::new(self.id, PARAM_NAME.get_key_id()) } } @@ -296,11 +296,11 @@ pub struct MutableSetIntParams { impl MutableSetIntParams { pub fn int_value(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_INT_VALUE)) + ScMutableInt64::new(self.id, PARAM_INT_VALUE.get_key_id()) } pub fn name(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + ScMutableString::new(self.id, PARAM_NAME.get_key_id()) } } @@ -311,7 +311,7 @@ pub struct ImmutableSpawnParams { impl ImmutableSpawnParams { pub fn prog_hash(&self) -> ScImmutableHash { - ScImmutableHash::new(self.id, idx_map(IDX_PARAM_PROG_HASH)) + ScImmutableHash::new(self.id, PARAM_PROG_HASH.get_key_id()) } } @@ -322,7 +322,7 @@ pub struct MutableSpawnParams { impl MutableSpawnParams { pub fn prog_hash(&self) -> ScMutableHash { - ScMutableHash::new(self.id, idx_map(IDX_PARAM_PROG_HASH)) + ScMutableHash::new(self.id, PARAM_PROG_HASH.get_key_id()) } } @@ -333,7 +333,7 @@ pub struct ImmutableTestEventLogGenericDataParams { impl ImmutableTestEventLogGenericDataParams { pub fn counter(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_COUNTER)) + ScImmutableInt64::new(self.id, PARAM_COUNTER.get_key_id()) } } @@ -344,7 +344,7 @@ pub struct MutableTestEventLogGenericDataParams { impl MutableTestEventLogGenericDataParams { pub fn counter(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_COUNTER)) + ScMutableInt64::new(self.id, PARAM_COUNTER.get_key_id()) } } @@ -355,7 +355,7 @@ pub struct ImmutableWithdrawToChainParams { impl ImmutableWithdrawToChainParams { pub fn chain_id(&self) -> ScImmutableChainID { - ScImmutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) + ScImmutableChainID::new(self.id, PARAM_CHAIN_ID.get_key_id()) } } @@ -366,7 +366,7 @@ pub struct MutableWithdrawToChainParams { impl MutableWithdrawToChainParams { pub fn chain_id(&self) -> ScMutableChainID { - ScMutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) + ScMutableChainID::new(self.id, PARAM_CHAIN_ID.get_key_id()) } } @@ -377,19 +377,19 @@ pub struct ImmutableCheckContextFromViewEPParams { impl ImmutableCheckContextFromViewEPParams { pub fn agent_id(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_AGENT_ID)) + ScImmutableAgentID::new(self.id, PARAM_AGENT_ID.get_key_id()) } pub fn chain_id(&self) -> ScImmutableChainID { - ScImmutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) + ScImmutableChainID::new(self.id, PARAM_CHAIN_ID.get_key_id()) } pub fn chain_owner_id(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CHAIN_OWNER_ID)) + ScImmutableAgentID::new(self.id, PARAM_CHAIN_OWNER_ID.get_key_id()) } pub fn contract_creator(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_CREATOR)) + ScImmutableAgentID::new(self.id, PARAM_CONTRACT_CREATOR.get_key_id()) } } @@ -400,19 +400,19 @@ pub struct MutableCheckContextFromViewEPParams { impl MutableCheckContextFromViewEPParams { pub fn agent_id(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_AGENT_ID)) + ScMutableAgentID::new(self.id, PARAM_AGENT_ID.get_key_id()) } pub fn chain_id(&self) -> ScMutableChainID { - ScMutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) + ScMutableChainID::new(self.id, PARAM_CHAIN_ID.get_key_id()) } pub fn chain_owner_id(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CHAIN_OWNER_ID)) + ScMutableAgentID::new(self.id, PARAM_CHAIN_OWNER_ID.get_key_id()) } pub fn contract_creator(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_CREATOR)) + ScMutableAgentID::new(self.id, PARAM_CONTRACT_CREATOR.get_key_id()) } } @@ -423,7 +423,7 @@ pub struct ImmutableFibonacciParams { impl ImmutableFibonacciParams { pub fn int_value(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_INT_VALUE)) + ScImmutableInt64::new(self.id, PARAM_INT_VALUE.get_key_id()) } } @@ -434,7 +434,7 @@ pub struct MutableFibonacciParams { impl MutableFibonacciParams { pub fn int_value(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_INT_VALUE)) + ScMutableInt64::new(self.id, PARAM_INT_VALUE.get_key_id()) } } @@ -445,7 +445,7 @@ pub struct ImmutableGetIntParams { impl ImmutableGetIntParams { pub fn name(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + ScImmutableString::new(self.id, PARAM_NAME.get_key_id()) } } @@ -456,7 +456,7 @@ pub struct MutableGetIntParams { impl MutableGetIntParams { pub fn name(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + ScMutableString::new(self.id, PARAM_NAME.get_key_id()) } } @@ -467,7 +467,7 @@ pub struct ImmutableGetStringValueParams { impl ImmutableGetStringValueParams { pub fn var_name(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_VAR_NAME)) + ScImmutableString::new(self.id, PARAM_VAR_NAME.get_key_id()) } } @@ -478,7 +478,7 @@ pub struct MutableGetStringValueParams { impl MutableGetStringValueParams { pub fn var_name(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_VAR_NAME)) + ScMutableString::new(self.id, PARAM_VAR_NAME.get_key_id()) } } @@ -489,47 +489,47 @@ pub struct ImmutablePassTypesViewParams { impl ImmutablePassTypesViewParams { pub fn address(&self) -> ScImmutableAddress { - ScImmutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) + ScImmutableAddress::new(self.id, PARAM_ADDRESS.get_key_id()) } pub fn agent_id(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_AGENT_ID)) + ScImmutableAgentID::new(self.id, PARAM_AGENT_ID.get_key_id()) } pub fn chain_id(&self) -> ScImmutableChainID { - ScImmutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) + ScImmutableChainID::new(self.id, PARAM_CHAIN_ID.get_key_id()) } pub fn contract_id(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_ID)) + ScImmutableAgentID::new(self.id, PARAM_CONTRACT_ID.get_key_id()) } pub fn hash(&self) -> ScImmutableHash { - ScImmutableHash::new(self.id, idx_map(IDX_PARAM_HASH)) + ScImmutableHash::new(self.id, PARAM_HASH.get_key_id()) } pub fn hname(&self) -> ScImmutableHname { - ScImmutableHname::new(self.id, idx_map(IDX_PARAM_HNAME)) + ScImmutableHname::new(self.id, PARAM_HNAME.get_key_id()) } pub fn hname_zero(&self) -> ScImmutableHname { - ScImmutableHname::new(self.id, idx_map(IDX_PARAM_HNAME_ZERO)) + ScImmutableHname::new(self.id, PARAM_HNAME_ZERO.get_key_id()) } pub fn int64(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_INT64)) + ScImmutableInt64::new(self.id, PARAM_INT64.get_key_id()) } pub fn int64_zero(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_INT64_ZERO)) + ScImmutableInt64::new(self.id, PARAM_INT64_ZERO.get_key_id()) } pub fn string(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_STRING)) + ScImmutableString::new(self.id, PARAM_STRING.get_key_id()) } pub fn string_zero(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_STRING_ZERO)) + ScImmutableString::new(self.id, PARAM_STRING_ZERO.get_key_id()) } } @@ -540,46 +540,46 @@ pub struct MutablePassTypesViewParams { impl MutablePassTypesViewParams { pub fn address(&self) -> ScMutableAddress { - ScMutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) + ScMutableAddress::new(self.id, PARAM_ADDRESS.get_key_id()) } pub fn agent_id(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_AGENT_ID)) + ScMutableAgentID::new(self.id, PARAM_AGENT_ID.get_key_id()) } pub fn chain_id(&self) -> ScMutableChainID { - ScMutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) + ScMutableChainID::new(self.id, PARAM_CHAIN_ID.get_key_id()) } pub fn contract_id(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_ID)) + ScMutableAgentID::new(self.id, PARAM_CONTRACT_ID.get_key_id()) } pub fn hash(&self) -> ScMutableHash { - ScMutableHash::new(self.id, idx_map(IDX_PARAM_HASH)) + ScMutableHash::new(self.id, PARAM_HASH.get_key_id()) } pub fn hname(&self) -> ScMutableHname { - ScMutableHname::new(self.id, idx_map(IDX_PARAM_HNAME)) + ScMutableHname::new(self.id, PARAM_HNAME.get_key_id()) } pub fn hname_zero(&self) -> ScMutableHname { - ScMutableHname::new(self.id, idx_map(IDX_PARAM_HNAME_ZERO)) + ScMutableHname::new(self.id, PARAM_HNAME_ZERO.get_key_id()) } pub fn int64(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_INT64)) + ScMutableInt64::new(self.id, PARAM_INT64.get_key_id()) } pub fn int64_zero(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_INT64_ZERO)) + ScMutableInt64::new(self.id, PARAM_INT64_ZERO.get_key_id()) } pub fn string(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_STRING)) + ScMutableString::new(self.id, PARAM_STRING.get_key_id()) } pub fn string_zero(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_STRING_ZERO)) + ScMutableString::new(self.id, PARAM_STRING_ZERO.get_key_id()) } } diff --git a/contracts/wasm/testcore/src/results.rs b/contracts/wasm/testcore/src/results.rs index 974409c2dc..a0380fbbfa 100644 --- a/contracts/wasm/testcore/src/results.rs +++ b/contracts/wasm/testcore/src/results.rs @@ -21,7 +21,7 @@ pub struct ImmutableCallOnChainResults { impl ImmutableCallOnChainResults { pub fn int_value(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_INT_VALUE)) + ScImmutableInt64::new(self.id, RESULT_INT_VALUE.get_key_id()) } } @@ -32,7 +32,7 @@ pub struct MutableCallOnChainResults { impl MutableCallOnChainResults { pub fn int_value(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_INT_VALUE)) + ScMutableInt64::new(self.id, RESULT_INT_VALUE.get_key_id()) } } @@ -43,11 +43,11 @@ pub struct ImmutableGetMintedSupplyResults { impl ImmutableGetMintedSupplyResults { pub fn minted_color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, idx_map(IDX_RESULT_MINTED_COLOR)) + ScImmutableColor::new(self.id, RESULT_MINTED_COLOR.get_key_id()) } pub fn minted_supply(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_MINTED_SUPPLY)) + ScImmutableInt64::new(self.id, RESULT_MINTED_SUPPLY.get_key_id()) } } @@ -58,11 +58,11 @@ pub struct MutableGetMintedSupplyResults { impl MutableGetMintedSupplyResults { pub fn minted_color(&self) -> ScMutableColor { - ScMutableColor::new(self.id, idx_map(IDX_RESULT_MINTED_COLOR)) + ScMutableColor::new(self.id, RESULT_MINTED_COLOR.get_key_id()) } pub fn minted_supply(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_MINTED_SUPPLY)) + ScMutableInt64::new(self.id, RESULT_MINTED_SUPPLY.get_key_id()) } } @@ -73,7 +73,7 @@ pub struct ImmutableRunRecursionResults { impl ImmutableRunRecursionResults { pub fn int_value(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_INT_VALUE)) + ScImmutableInt64::new(self.id, RESULT_INT_VALUE.get_key_id()) } } @@ -84,7 +84,7 @@ pub struct MutableRunRecursionResults { impl MutableRunRecursionResults { pub fn int_value(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_INT_VALUE)) + ScMutableInt64::new(self.id, RESULT_INT_VALUE.get_key_id()) } } @@ -95,7 +95,7 @@ pub struct ImmutableTestChainOwnerIDFullResults { impl ImmutableTestChainOwnerIDFullResults { pub fn chain_owner_id(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_RESULT_CHAIN_OWNER_ID)) + ScImmutableAgentID::new(self.id, RESULT_CHAIN_OWNER_ID.get_key_id()) } } @@ -106,7 +106,7 @@ pub struct MutableTestChainOwnerIDFullResults { impl MutableTestChainOwnerIDFullResults { pub fn chain_owner_id(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_RESULT_CHAIN_OWNER_ID)) + ScMutableAgentID::new(self.id, RESULT_CHAIN_OWNER_ID.get_key_id()) } } @@ -117,7 +117,7 @@ pub struct ImmutableFibonacciResults { impl ImmutableFibonacciResults { pub fn int_value(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_INT_VALUE)) + ScImmutableInt64::new(self.id, RESULT_INT_VALUE.get_key_id()) } } @@ -128,7 +128,7 @@ pub struct MutableFibonacciResults { impl MutableFibonacciResults { pub fn int_value(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_INT_VALUE)) + ScMutableInt64::new(self.id, RESULT_INT_VALUE.get_key_id()) } } @@ -139,7 +139,7 @@ pub struct ImmutableGetCounterResults { impl ImmutableGetCounterResults { pub fn counter(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_COUNTER)) + ScImmutableInt64::new(self.id, RESULT_COUNTER.get_key_id()) } } @@ -150,10 +150,11 @@ pub struct MutableGetCounterResults { impl MutableGetCounterResults { pub fn counter(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_COUNTER)) + ScMutableInt64::new(self.id, RESULT_COUNTER.get_key_id()) } } +#[derive(Clone, Copy)] pub struct MapStringToImmutableInt64 { pub(crate) obj_id: i32, } @@ -175,6 +176,7 @@ impl ImmutableGetIntResults { } } +#[derive(Clone, Copy)] pub struct MapStringToMutableInt64 { pub(crate) obj_id: i32, } @@ -200,6 +202,7 @@ impl MutableGetIntResults { } } +#[derive(Clone, Copy)] pub struct MapStringToImmutableString { pub(crate) obj_id: i32, } @@ -221,6 +224,7 @@ impl ImmutableGetStringValueResults { } } +#[derive(Clone, Copy)] pub struct MapStringToMutableString { pub(crate) obj_id: i32, } @@ -253,7 +257,7 @@ pub struct ImmutableTestChainOwnerIDViewResults { impl ImmutableTestChainOwnerIDViewResults { pub fn chain_owner_id(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_RESULT_CHAIN_OWNER_ID)) + ScImmutableAgentID::new(self.id, RESULT_CHAIN_OWNER_ID.get_key_id()) } } @@ -264,7 +268,7 @@ pub struct MutableTestChainOwnerIDViewResults { impl MutableTestChainOwnerIDViewResults { pub fn chain_owner_id(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_RESULT_CHAIN_OWNER_ID)) + ScMutableAgentID::new(self.id, RESULT_CHAIN_OWNER_ID.get_key_id()) } } @@ -275,7 +279,7 @@ pub struct ImmutableTestSandboxCallResults { impl ImmutableTestSandboxCallResults { pub fn sandbox_call(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_RESULT_SANDBOX_CALL)) + ScImmutableString::new(self.id, RESULT_SANDBOX_CALL.get_key_id()) } } @@ -286,6 +290,6 @@ pub struct MutableTestSandboxCallResults { impl MutableTestSandboxCallResults { pub fn sandbox_call(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_RESULT_SANDBOX_CALL)) + ScMutableString::new(self.id, RESULT_SANDBOX_CALL.get_key_id()) } } diff --git a/contracts/wasm/testcore/src/state.rs b/contracts/wasm/testcore/src/state.rs index 1f62a862ac..464c4e0aa9 100644 --- a/contracts/wasm/testcore/src/state.rs +++ b/contracts/wasm/testcore/src/state.rs @@ -21,24 +21,24 @@ pub struct ImmutableTestCoreState { impl ImmutableTestCoreState { pub fn counter(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_STATE_COUNTER)) + ScImmutableInt64::new(self.id, STATE_COUNTER.get_key_id()) } pub fn hname_ep(&self) -> ScImmutableHname { - ScImmutableHname::new(self.id, idx_map(IDX_STATE_HNAME_EP)) + ScImmutableHname::new(self.id, STATE_HNAME_EP.get_key_id()) } pub fn ints(&self) -> MapStringToImmutableInt64 { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_INTS), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_INTS.get_key_id(), TYPE_MAP); MapStringToImmutableInt64 { obj_id: map_id } } pub fn minted_color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, idx_map(IDX_STATE_MINTED_COLOR)) + ScImmutableColor::new(self.id, STATE_MINTED_COLOR.get_key_id()) } pub fn minted_supply(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_STATE_MINTED_SUPPLY)) + ScImmutableInt64::new(self.id, STATE_MINTED_SUPPLY.get_key_id()) } } @@ -48,24 +48,28 @@ pub struct MutableTestCoreState { } impl MutableTestCoreState { + pub fn as_immutable(&self) -> ImmutableTestCoreState { + ImmutableTestCoreState { id: self.id } + } + pub fn counter(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_STATE_COUNTER)) + ScMutableInt64::new(self.id, STATE_COUNTER.get_key_id()) } pub fn hname_ep(&self) -> ScMutableHname { - ScMutableHname::new(self.id, idx_map(IDX_STATE_HNAME_EP)) + ScMutableHname::new(self.id, STATE_HNAME_EP.get_key_id()) } pub fn ints(&self) -> MapStringToMutableInt64 { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_INTS), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_INTS.get_key_id(), TYPE_MAP); MapStringToMutableInt64 { obj_id: map_id } } pub fn minted_color(&self) -> ScMutableColor { - ScMutableColor::new(self.id, idx_map(IDX_STATE_MINTED_COLOR)) + ScMutableColor::new(self.id, STATE_MINTED_COLOR.get_key_id()) } pub fn minted_supply(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_STATE_MINTED_SUPPLY)) + ScMutableInt64::new(self.id, STATE_MINTED_SUPPLY.get_key_id()) } } diff --git a/contracts/wasm/testcore/test/testcore_bg.wasm b/contracts/wasm/testcore/test/testcore_bg.wasm index e3b2cafe6e..4c5b2af584 100644 Binary files a/contracts/wasm/testcore/test/testcore_bg.wasm and b/contracts/wasm/testcore/test/testcore_bg.wasm differ diff --git a/contracts/wasm/testcore/test/testcore_test.go b/contracts/wasm/testcore/test/testcore_test.go index 19cbe1e0fe..9ca6847fbd 100644 --- a/contracts/wasm/testcore/test/testcore_test.go +++ b/contracts/wasm/testcore/test/testcore_test.go @@ -9,9 +9,9 @@ import ( "github.com/iotaledger/wasp/packages/util" "github.com/iotaledger/wasp/packages/vm/core/testcore/sbtests/sbtestsc" "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" - coreaccounts2 "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib/coreaccounts" - coregovernance2 "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib/coregovernance" - coreroot2 "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib/coreroot" + "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib/coreaccounts" + "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib/coregovernance" + "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib/coreroot" "github.com/iotaledger/wasp/packages/vm/wasmsolo" "github.com/stretchr/testify/require" ) @@ -131,8 +131,8 @@ func originatorBalanceReducedBy(ctx *wasmsolo.SoloContext, w bool, minus uint64) } func deposit(t *testing.T, ctx *wasmsolo.SoloContext, user, target *wasmsolo.SoloAgent, amount int64) { - ctxAcc := ctx.SoloContextForCore(t, coreaccounts2.ScName, coreaccounts2.OnLoad) - f := coreaccounts2.ScFuncs.Deposit(ctxAcc.Sign(user)) + ctxAcc := ctx.SoloContextForCore(t, coreaccounts.ScName, coreaccounts.OnLoad) + f := coreaccounts.ScFuncs.Deposit(ctxAcc.Sign(user)) if target != nil { f.Params.AgentID().SetValue(target.ScAgentID()) } @@ -141,16 +141,16 @@ func deposit(t *testing.T, ctx *wasmsolo.SoloContext, user, target *wasmsolo.Sol } func setDeployer(t *testing.T, ctx *wasmsolo.SoloContext, deployer *wasmsolo.SoloAgent) { - ctxRoot := ctx.SoloContextForCore(t, coreroot2.ScName, coreroot2.OnLoad) - f := coreroot2.ScFuncs.GrantDeployPermission(ctxRoot) + ctxRoot := ctx.SoloContextForCore(t, coreroot.ScName, coreroot.OnLoad) + f := coreroot.ScFuncs.GrantDeployPermission(ctxRoot) f.Params.Deployer().SetValue(deployer.ScAgentID()) f.Func.TransferIotas(1).Post() require.NoError(t, ctxRoot.Err) } func setOwnerFee(t *testing.T, ctx *wasmsolo.SoloContext, amount int64) { - ctxGov := ctx.SoloContextForCore(t, coregovernance2.ScName, coregovernance2.OnLoad) - f := coregovernance2.ScFuncs.SetContractFee(ctxGov) + ctxGov := ctx.SoloContextForCore(t, coregovernance.ScName, coregovernance.OnLoad) + f := coregovernance.ScFuncs.SetContractFee(ctxGov) f.Params.Hname().SetValue(testcore.HScName) f.Params.OwnerFee().SetValue(amount) f.Func.TransferIotas(1).Post() @@ -158,8 +158,8 @@ func setOwnerFee(t *testing.T, ctx *wasmsolo.SoloContext, amount int64) { } func withdraw(t *testing.T, ctx *wasmsolo.SoloContext, user *wasmsolo.SoloAgent) { - ctxAcc := ctx.SoloContextForCore(t, coreaccounts2.ScName, coreaccounts2.OnLoad) - f := coreaccounts2.ScFuncs.Withdraw(ctxAcc.Sign(user)) + ctxAcc := ctx.SoloContextForCore(t, coreaccounts.ScName, coreaccounts.OnLoad) + f := coreaccounts.ScFuncs.Withdraw(ctxAcc.Sign(user)) f.Func.TransferIotas(1).Post() require.NoError(t, ctxAcc.Err) } diff --git a/contracts/wasm/testcore/ts/testcore/params.ts b/contracts/wasm/testcore/ts/testcore/params.ts index 8e90695611..6736de4bd6 100644 --- a/contracts/wasm/testcore/ts/testcore/params.ts +++ b/contracts/wasm/testcore/ts/testcore/params.ts @@ -10,73 +10,73 @@ import * as sc from "./index"; export class ImmutableCallOnChainParams extends wasmlib.ScMapID { hnameContract(): wasmlib.ScImmutableHname { - return new wasmlib.ScImmutableHname(this.mapID, sc.idxMap[sc.IdxParamHnameContract]); + return new wasmlib.ScImmutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHnameContract)); } hnameEP(): wasmlib.ScImmutableHname { - return new wasmlib.ScImmutableHname(this.mapID, sc.idxMap[sc.IdxParamHnameEP]); + return new wasmlib.ScImmutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHnameEP)); } intValue(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamIntValue]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamIntValue)); } } export class MutableCallOnChainParams extends wasmlib.ScMapID { hnameContract(): wasmlib.ScMutableHname { - return new wasmlib.ScMutableHname(this.mapID, sc.idxMap[sc.IdxParamHnameContract]); + return new wasmlib.ScMutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHnameContract)); } hnameEP(): wasmlib.ScMutableHname { - return new wasmlib.ScMutableHname(this.mapID, sc.idxMap[sc.IdxParamHnameEP]); + return new wasmlib.ScMutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHnameEP)); } intValue(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamIntValue]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamIntValue)); } } export class ImmutableCheckContextFromFullEPParams extends wasmlib.ScMapID { agentID(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAgentID]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAgentID)); } caller(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamCaller]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamCaller)); } chainID(): wasmlib.ScImmutableChainID { - return new wasmlib.ScImmutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); + return new wasmlib.ScImmutableChainID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainID)); } chainOwnerID(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamChainOwnerID]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainOwnerID)); } contractCreator(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractCreator]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamContractCreator)); } } export class MutableCheckContextFromFullEPParams extends wasmlib.ScMapID { agentID(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAgentID]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAgentID)); } caller(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamCaller]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamCaller)); } chainID(): wasmlib.ScMutableChainID { - return new wasmlib.ScMutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); + return new wasmlib.ScMutableChainID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainID)); } chainOwnerID(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamChainOwnerID]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainOwnerID)); } contractCreator(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractCreator]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamContractCreator)); } } @@ -94,336 +94,336 @@ export class MutableInitParams extends wasmlib.ScMapID { export class ImmutablePassTypesFullParams extends wasmlib.ScMapID { address(): wasmlib.ScImmutableAddress { - return new wasmlib.ScImmutableAddress(this.mapID, sc.idxMap[sc.IdxParamAddress]); + return new wasmlib.ScImmutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamAddress)); } agentID(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAgentID]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAgentID)); } chainID(): wasmlib.ScImmutableChainID { - return new wasmlib.ScImmutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); + return new wasmlib.ScImmutableChainID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainID)); } contractID(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractID]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamContractID)); } hash(): wasmlib.ScImmutableHash { - return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamHash]); + return new wasmlib.ScImmutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamHash)); } hname(): wasmlib.ScImmutableHname { - return new wasmlib.ScImmutableHname(this.mapID, sc.idxMap[sc.IdxParamHname]); + return new wasmlib.ScImmutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHname)); } hnameZero(): wasmlib.ScImmutableHname { - return new wasmlib.ScImmutableHname(this.mapID, sc.idxMap[sc.IdxParamHnameZero]); + return new wasmlib.ScImmutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHnameZero)); } int64(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamInt64)); } int64Zero(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64Zero]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamInt64Zero)); } string(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamString]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamString)); } stringZero(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamStringZero]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamStringZero)); } } export class MutablePassTypesFullParams extends wasmlib.ScMapID { address(): wasmlib.ScMutableAddress { - return new wasmlib.ScMutableAddress(this.mapID, sc.idxMap[sc.IdxParamAddress]); + return new wasmlib.ScMutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamAddress)); } agentID(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAgentID]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAgentID)); } chainID(): wasmlib.ScMutableChainID { - return new wasmlib.ScMutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); + return new wasmlib.ScMutableChainID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainID)); } contractID(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractID]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamContractID)); } hash(): wasmlib.ScMutableHash { - return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamHash]); + return new wasmlib.ScMutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamHash)); } hname(): wasmlib.ScMutableHname { - return new wasmlib.ScMutableHname(this.mapID, sc.idxMap[sc.IdxParamHname]); + return new wasmlib.ScMutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHname)); } hnameZero(): wasmlib.ScMutableHname { - return new wasmlib.ScMutableHname(this.mapID, sc.idxMap[sc.IdxParamHnameZero]); + return new wasmlib.ScMutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHnameZero)); } int64(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamInt64)); } int64Zero(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64Zero]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamInt64Zero)); } string(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamString]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamString)); } stringZero(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamStringZero]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamStringZero)); } } export class ImmutableRunRecursionParams extends wasmlib.ScMapID { intValue(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamIntValue]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamIntValue)); } } export class MutableRunRecursionParams extends wasmlib.ScMapID { intValue(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamIntValue]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamIntValue)); } } export class ImmutableSendToAddressParams extends wasmlib.ScMapID { address(): wasmlib.ScImmutableAddress { - return new wasmlib.ScImmutableAddress(this.mapID, sc.idxMap[sc.IdxParamAddress]); + return new wasmlib.ScImmutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamAddress)); } } export class MutableSendToAddressParams extends wasmlib.ScMapID { address(): wasmlib.ScMutableAddress { - return new wasmlib.ScMutableAddress(this.mapID, sc.idxMap[sc.IdxParamAddress]); + return new wasmlib.ScMutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamAddress)); } } export class ImmutableSetIntParams extends wasmlib.ScMapID { intValue(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamIntValue]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamIntValue)); } name(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamName]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); } } export class MutableSetIntParams extends wasmlib.ScMapID { intValue(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamIntValue]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamIntValue)); } name(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamName]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); } } export class ImmutableSpawnParams extends wasmlib.ScMapID { progHash(): wasmlib.ScImmutableHash { - return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamProgHash]); + return new wasmlib.ScImmutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamProgHash)); } } export class MutableSpawnParams extends wasmlib.ScMapID { progHash(): wasmlib.ScMutableHash { - return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamProgHash]); + return new wasmlib.ScMutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamProgHash)); } } export class ImmutableTestEventLogGenericDataParams extends wasmlib.ScMapID { counter(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamCounter]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamCounter)); } } export class MutableTestEventLogGenericDataParams extends wasmlib.ScMapID { counter(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamCounter]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamCounter)); } } export class ImmutableWithdrawToChainParams extends wasmlib.ScMapID { chainID(): wasmlib.ScImmutableChainID { - return new wasmlib.ScImmutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); + return new wasmlib.ScImmutableChainID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainID)); } } export class MutableWithdrawToChainParams extends wasmlib.ScMapID { chainID(): wasmlib.ScMutableChainID { - return new wasmlib.ScMutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); + return new wasmlib.ScMutableChainID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainID)); } } export class ImmutableCheckContextFromViewEPParams extends wasmlib.ScMapID { agentID(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAgentID]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAgentID)); } chainID(): wasmlib.ScImmutableChainID { - return new wasmlib.ScImmutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); + return new wasmlib.ScImmutableChainID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainID)); } chainOwnerID(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamChainOwnerID]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainOwnerID)); } contractCreator(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractCreator]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamContractCreator)); } } export class MutableCheckContextFromViewEPParams extends wasmlib.ScMapID { agentID(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAgentID]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAgentID)); } chainID(): wasmlib.ScMutableChainID { - return new wasmlib.ScMutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); + return new wasmlib.ScMutableChainID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainID)); } chainOwnerID(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamChainOwnerID]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainOwnerID)); } contractCreator(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractCreator]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamContractCreator)); } } export class ImmutableFibonacciParams extends wasmlib.ScMapID { intValue(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamIntValue]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamIntValue)); } } export class MutableFibonacciParams extends wasmlib.ScMapID { intValue(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamIntValue]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamIntValue)); } } export class ImmutableGetIntParams extends wasmlib.ScMapID { name(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamName]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); } } export class MutableGetIntParams extends wasmlib.ScMapID { name(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamName]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); } } export class ImmutableGetStringValueParams extends wasmlib.ScMapID { varName(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamVarName]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamVarName)); } } export class MutableGetStringValueParams extends wasmlib.ScMapID { varName(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamVarName]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamVarName)); } } export class ImmutablePassTypesViewParams extends wasmlib.ScMapID { address(): wasmlib.ScImmutableAddress { - return new wasmlib.ScImmutableAddress(this.mapID, sc.idxMap[sc.IdxParamAddress]); + return new wasmlib.ScImmutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamAddress)); } agentID(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAgentID]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAgentID)); } chainID(): wasmlib.ScImmutableChainID { - return new wasmlib.ScImmutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); + return new wasmlib.ScImmutableChainID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainID)); } contractID(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractID]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamContractID)); } hash(): wasmlib.ScImmutableHash { - return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamHash]); + return new wasmlib.ScImmutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamHash)); } hname(): wasmlib.ScImmutableHname { - return new wasmlib.ScImmutableHname(this.mapID, sc.idxMap[sc.IdxParamHname]); + return new wasmlib.ScImmutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHname)); } hnameZero(): wasmlib.ScImmutableHname { - return new wasmlib.ScImmutableHname(this.mapID, sc.idxMap[sc.IdxParamHnameZero]); + return new wasmlib.ScImmutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHnameZero)); } int64(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamInt64)); } int64Zero(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64Zero]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamInt64Zero)); } string(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamString]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamString)); } stringZero(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamStringZero]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamStringZero)); } } export class MutablePassTypesViewParams extends wasmlib.ScMapID { address(): wasmlib.ScMutableAddress { - return new wasmlib.ScMutableAddress(this.mapID, sc.idxMap[sc.IdxParamAddress]); + return new wasmlib.ScMutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamAddress)); } agentID(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAgentID]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAgentID)); } chainID(): wasmlib.ScMutableChainID { - return new wasmlib.ScMutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); + return new wasmlib.ScMutableChainID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainID)); } contractID(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractID]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamContractID)); } hash(): wasmlib.ScMutableHash { - return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamHash]); + return new wasmlib.ScMutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamHash)); } hname(): wasmlib.ScMutableHname { - return new wasmlib.ScMutableHname(this.mapID, sc.idxMap[sc.IdxParamHname]); + return new wasmlib.ScMutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHname)); } hnameZero(): wasmlib.ScMutableHname { - return new wasmlib.ScMutableHname(this.mapID, sc.idxMap[sc.IdxParamHnameZero]); + return new wasmlib.ScMutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHnameZero)); } int64(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamInt64)); } int64Zero(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64Zero]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamInt64Zero)); } string(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamString]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamString)); } stringZero(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamStringZero]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamStringZero)); } } diff --git a/contracts/wasm/testcore/ts/testcore/results.ts b/contracts/wasm/testcore/ts/testcore/results.ts index f25dbe28d6..1a4abc5abf 100644 --- a/contracts/wasm/testcore/ts/testcore/results.ts +++ b/contracts/wasm/testcore/ts/testcore/results.ts @@ -10,81 +10,81 @@ import * as sc from "./index"; export class ImmutableCallOnChainResults extends wasmlib.ScMapID { intValue(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultIntValue]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultIntValue)); } } export class MutableCallOnChainResults extends wasmlib.ScMapID { intValue(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultIntValue]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultIntValue)); } } export class ImmutableGetMintedSupplyResults extends wasmlib.ScMapID { mintedColor(): wasmlib.ScImmutableColor { - return new wasmlib.ScImmutableColor(this.mapID, sc.idxMap[sc.IdxResultMintedColor]); + return new wasmlib.ScImmutableColor(this.mapID, wasmlib.Key32.fromString(sc.ResultMintedColor)); } mintedSupply(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultMintedSupply]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultMintedSupply)); } } export class MutableGetMintedSupplyResults extends wasmlib.ScMapID { mintedColor(): wasmlib.ScMutableColor { - return new wasmlib.ScMutableColor(this.mapID, sc.idxMap[sc.IdxResultMintedColor]); + return new wasmlib.ScMutableColor(this.mapID, wasmlib.Key32.fromString(sc.ResultMintedColor)); } mintedSupply(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultMintedSupply]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultMintedSupply)); } } export class ImmutableRunRecursionResults extends wasmlib.ScMapID { intValue(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultIntValue]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultIntValue)); } } export class MutableRunRecursionResults extends wasmlib.ScMapID { intValue(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultIntValue]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultIntValue)); } } export class ImmutableTestChainOwnerIDFullResults extends wasmlib.ScMapID { chainOwnerID(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxResultChainOwnerID]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ResultChainOwnerID)); } } export class MutableTestChainOwnerIDFullResults extends wasmlib.ScMapID { chainOwnerID(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxResultChainOwnerID]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ResultChainOwnerID)); } } export class ImmutableFibonacciResults extends wasmlib.ScMapID { intValue(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultIntValue]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultIntValue)); } } export class MutableFibonacciResults extends wasmlib.ScMapID { intValue(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultIntValue]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultIntValue)); } } export class ImmutableGetCounterResults extends wasmlib.ScMapID { counter(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultCounter]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultCounter)); } } export class MutableGetCounterResults extends wasmlib.ScMapID { counter(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultCounter]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultCounter)); } } @@ -170,24 +170,24 @@ export class MutableGetStringValueResults extends wasmlib.ScMapID { export class ImmutableTestChainOwnerIDViewResults extends wasmlib.ScMapID { chainOwnerID(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxResultChainOwnerID]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ResultChainOwnerID)); } } export class MutableTestChainOwnerIDViewResults extends wasmlib.ScMapID { chainOwnerID(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxResultChainOwnerID]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ResultChainOwnerID)); } } export class ImmutableTestSandboxCallResults extends wasmlib.ScMapID { sandboxCall(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxResultSandboxCall]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultSandboxCall)); } } export class MutableTestSandboxCallResults extends wasmlib.ScMapID { sandboxCall(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxResultSandboxCall]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultSandboxCall)); } } diff --git a/contracts/wasm/testcore/ts/testcore/state.ts b/contracts/wasm/testcore/ts/testcore/state.ts index 3a20e3d512..549c82f010 100644 --- a/contracts/wasm/testcore/ts/testcore/state.ts +++ b/contracts/wasm/testcore/ts/testcore/state.ts @@ -10,46 +10,52 @@ import * as sc from "./index"; export class ImmutableTestCoreState extends wasmlib.ScMapID { counter(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateCounter]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateCounter)); } hnameEP(): wasmlib.ScImmutableHname { - return new wasmlib.ScImmutableHname(this.mapID, sc.idxMap[sc.IdxStateHnameEP]); + return new wasmlib.ScImmutableHname(this.mapID, wasmlib.Key32.fromString(sc.StateHnameEP)); } ints(): sc.MapStringToImmutableInt64 { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateInts], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateInts), wasmlib.TYPE_MAP); return new sc.MapStringToImmutableInt64(mapID); } mintedColor(): wasmlib.ScImmutableColor { - return new wasmlib.ScImmutableColor(this.mapID, sc.idxMap[sc.IdxStateMintedColor]); + return new wasmlib.ScImmutableColor(this.mapID, wasmlib.Key32.fromString(sc.StateMintedColor)); } mintedSupply(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateMintedSupply]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateMintedSupply)); } } export class MutableTestCoreState extends wasmlib.ScMapID { + asImmutable(): sc.ImmutableTestCoreState { + const imm = new sc.ImmutableTestCoreState(); + imm.mapID = this.mapID; + return imm; + } + counter(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateCounter]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateCounter)); } hnameEP(): wasmlib.ScMutableHname { - return new wasmlib.ScMutableHname(this.mapID, sc.idxMap[sc.IdxStateHnameEP]); + return new wasmlib.ScMutableHname(this.mapID, wasmlib.Key32.fromString(sc.StateHnameEP)); } ints(): sc.MapStringToMutableInt64 { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateInts], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateInts), wasmlib.TYPE_MAP); return new sc.MapStringToMutableInt64(mapID); } mintedColor(): wasmlib.ScMutableColor { - return new wasmlib.ScMutableColor(this.mapID, sc.idxMap[sc.IdxStateMintedColor]); + return new wasmlib.ScMutableColor(this.mapID, wasmlib.Key32.fromString(sc.StateMintedColor)); } mintedSupply(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateMintedSupply]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateMintedSupply)); } } diff --git a/contracts/wasm/testwasmlib/go/main.go b/contracts/wasm/testwasmlib/go/main.go index c213bd8591..5138f55c33 100644 --- a/contracts/wasm/testwasmlib/go/main.go +++ b/contracts/wasm/testwasmlib/go/main.go @@ -9,7 +9,7 @@ package main -import "github.com/iotaledger/wasp/packages/vm/wasmclient" +import "github.com/iotaledger/wasp/packages/vm/wasmvmhost" import "github.com/iotaledger/wasp/contracts/wasm/testwasmlib/go/testwasmlib" @@ -18,7 +18,7 @@ func main() { //export on_load func onLoad() { - h := &wasmclient.WasmVMHost{} + h := &wasmvmhost.WasmVMHost{} h.ConnectWasmHost() testwasmlib.OnLoad() } diff --git a/contracts/wasm/testwasmlib/go/testwasmlib/consts.go b/contracts/wasm/testwasmlib/go/testwasmlib/consts.go index b28384f1f9..7b8cefa6f3 100644 --- a/contracts/wasm/testwasmlib/go/testwasmlib/consts.go +++ b/contracts/wasm/testwasmlib/go/testwasmlib/consts.go @@ -11,7 +11,7 @@ import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" const ( ScName = "testwasmlib" - ScDescription = "Exercise all aspects of WasmLib" + ScDescription = "Exercise several aspects of WasmLib" HScName = wasmlib.ScHname(0x89703a45) ) @@ -30,6 +30,7 @@ const ( ParamInt32 = "int32" ParamInt64 = "int64" ParamInt8 = "int8" + ParamKey = "key" ParamName = "name" ParamParam = "this" ParamRecordIndex = "recordIndex" @@ -53,6 +54,7 @@ const ( const ( StateArrays = "arrays" + StateMaps = "maps" StateRandom = "random" ) @@ -60,26 +62,36 @@ const ( FuncArrayClear = "arrayClear" FuncArrayCreate = "arrayCreate" FuncArraySet = "arraySet" + FuncMapClear = "mapClear" + FuncMapCreate = "mapCreate" + FuncMapSet = "mapSet" FuncParamTypes = "paramTypes" FuncRandom = "random" + FuncTriggerEvent = "triggerEvent" ViewArrayLength = "arrayLength" ViewArrayValue = "arrayValue" ViewBlockRecord = "blockRecord" ViewBlockRecords = "blockRecords" ViewGetRandom = "getRandom" ViewIotaBalance = "iotaBalance" + ViewMapValue = "mapValue" ) const ( HFuncArrayClear = wasmlib.ScHname(0x88021821) HFuncArrayCreate = wasmlib.ScHname(0x1ed5b23b) HFuncArraySet = wasmlib.ScHname(0x2c4150b3) + HFuncMapClear = wasmlib.ScHname(0x027f215a) + HFuncMapCreate = wasmlib.ScHname(0x6295d599) + HFuncMapSet = wasmlib.ScHname(0xf2260404) HFuncParamTypes = wasmlib.ScHname(0x6921c4cd) HFuncRandom = wasmlib.ScHname(0xe86c97ca) + HFuncTriggerEvent = wasmlib.ScHname(0xd5438ac6) HViewArrayLength = wasmlib.ScHname(0x3a831021) HViewArrayValue = wasmlib.ScHname(0x662dbd81) HViewBlockRecord = wasmlib.ScHname(0xad13b2f8) HViewBlockRecords = wasmlib.ScHname(0x16e249ea) HViewGetRandom = wasmlib.ScHname(0x46263045) HViewIotaBalance = wasmlib.ScHname(0x9d3920bd) + HViewMapValue = wasmlib.ScHname(0x23149bef) ) diff --git a/contracts/wasm/testwasmlib/go/testwasmlib/contract.go b/contracts/wasm/testwasmlib/go/testwasmlib/contract.go index 816dc14035..87309712b0 100644 --- a/contracts/wasm/testwasmlib/go/testwasmlib/contract.go +++ b/contracts/wasm/testwasmlib/go/testwasmlib/contract.go @@ -24,6 +24,21 @@ type ArraySetCall struct { Params MutableArraySetParams } +type MapClearCall struct { + Func *wasmlib.ScFunc + Params MutableMapClearParams +} + +type MapCreateCall struct { + Func *wasmlib.ScFunc + Params MutableMapCreateParams +} + +type MapSetCall struct { + Func *wasmlib.ScFunc + Params MutableMapSetParams +} + type ParamTypesCall struct { Func *wasmlib.ScFunc Params MutableParamTypesParams @@ -33,6 +48,11 @@ type RandomCall struct { Func *wasmlib.ScFunc } +type TriggerEventCall struct { + Func *wasmlib.ScFunc + Params MutableTriggerEventParams +} + type ArrayLengthCall struct { Func *wasmlib.ScView Params MutableArrayLengthParams @@ -67,6 +87,12 @@ type IotaBalanceCall struct { Results ImmutableIotaBalanceResults } +type MapValueCall struct { + Func *wasmlib.ScView + Params MutableMapValueParams + Results ImmutableMapValueResults +} + type Funcs struct{} var ScFuncs Funcs @@ -89,6 +115,24 @@ func (sc Funcs) ArraySet(ctx wasmlib.ScFuncCallContext) *ArraySetCall { return f } +func (sc Funcs) MapClear(ctx wasmlib.ScFuncCallContext) *MapClearCall { + f := &MapClearCall{Func: wasmlib.NewScFunc(ctx, HScName, HFuncMapClear)} + f.Func.SetPtrs(&f.Params.id, nil) + return f +} + +func (sc Funcs) MapCreate(ctx wasmlib.ScFuncCallContext) *MapCreateCall { + f := &MapCreateCall{Func: wasmlib.NewScFunc(ctx, HScName, HFuncMapCreate)} + f.Func.SetPtrs(&f.Params.id, nil) + return f +} + +func (sc Funcs) MapSet(ctx wasmlib.ScFuncCallContext) *MapSetCall { + f := &MapSetCall{Func: wasmlib.NewScFunc(ctx, HScName, HFuncMapSet)} + f.Func.SetPtrs(&f.Params.id, nil) + return f +} + func (sc Funcs) ParamTypes(ctx wasmlib.ScFuncCallContext) *ParamTypesCall { f := &ParamTypesCall{Func: wasmlib.NewScFunc(ctx, HScName, HFuncParamTypes)} f.Func.SetPtrs(&f.Params.id, nil) @@ -99,6 +143,12 @@ func (sc Funcs) Random(ctx wasmlib.ScFuncCallContext) *RandomCall { return &RandomCall{Func: wasmlib.NewScFunc(ctx, HScName, HFuncRandom)} } +func (sc Funcs) TriggerEvent(ctx wasmlib.ScFuncCallContext) *TriggerEventCall { + f := &TriggerEventCall{Func: wasmlib.NewScFunc(ctx, HScName, HFuncTriggerEvent)} + f.Func.SetPtrs(&f.Params.id, nil) + return f +} + func (sc Funcs) ArrayLength(ctx wasmlib.ScViewCallContext) *ArrayLengthCall { f := &ArrayLengthCall{Func: wasmlib.NewScView(ctx, HScName, HViewArrayLength)} f.Func.SetPtrs(&f.Params.id, &f.Results.id) @@ -134,3 +184,9 @@ func (sc Funcs) IotaBalance(ctx wasmlib.ScViewCallContext) *IotaBalanceCall { f.Func.SetPtrs(nil, &f.Results.id) return f } + +func (sc Funcs) MapValue(ctx wasmlib.ScViewCallContext) *MapValueCall { + f := &MapValueCall{Func: wasmlib.NewScView(ctx, HScName, HViewMapValue)} + f.Func.SetPtrs(&f.Params.id, &f.Results.id) + return f +} diff --git a/contracts/wasm/testwasmlib/go/testwasmlib/events.go b/contracts/wasm/testwasmlib/go/testwasmlib/events.go new file mode 100644 index 0000000000..eb9574346e --- /dev/null +++ b/contracts/wasm/testwasmlib/go/testwasmlib/events.go @@ -0,0 +1,19 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// (Re-)generated by schema tool +// >>>> DO NOT CHANGE THIS FILE! <<<< +// Change the json schema instead + +package testwasmlib + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + +type TestWasmLibEvents struct{} + +func (e TestWasmLibEvents) Test(address wasmlib.ScAddress, name string) { + wasmlib.NewEventEncoder("testwasmlib.test"). + Address(address). + String(name). + Emit() +} diff --git a/contracts/wasm/testwasmlib/go/testwasmlib/keys.go b/contracts/wasm/testwasmlib/go/testwasmlib/keys.go index e5d6841858..9b5e7ac61f 100644 --- a/contracts/wasm/testwasmlib/go/testwasmlib/keys.go +++ b/contracts/wasm/testwasmlib/go/testwasmlib/keys.go @@ -24,29 +24,31 @@ const ( IdxParamInt32 = 11 IdxParamInt64 = 12 IdxParamInt8 = 13 - IdxParamName = 14 - IdxParamParam = 15 - IdxParamRecordIndex = 16 - IdxParamRequestID = 17 - IdxParamString = 18 - IdxParamUint16 = 19 - IdxParamUint32 = 20 - IdxParamUint64 = 21 - IdxParamUint8 = 22 - IdxParamValue = 23 + IdxParamKey = 14 + IdxParamName = 15 + IdxParamParam = 16 + IdxParamRecordIndex = 17 + IdxParamRequestID = 18 + IdxParamString = 19 + IdxParamUint16 = 20 + IdxParamUint32 = 21 + IdxParamUint64 = 22 + IdxParamUint8 = 23 + IdxParamValue = 24 - IdxResultCount = 24 - IdxResultIotas = 25 - IdxResultLength = 26 - IdxResultRandom = 27 - IdxResultRecord = 28 - IdxResultValue = 29 + IdxResultCount = 25 + IdxResultIotas = 26 + IdxResultLength = 27 + IdxResultRandom = 28 + IdxResultRecord = 29 + IdxResultValue = 30 - IdxStateArrays = 30 - IdxStateRandom = 31 + IdxStateArrays = 31 + IdxStateMaps = 32 + IdxStateRandom = 33 ) -const keyMapLen = 32 +const keyMapLen = 34 var keyMap = [keyMapLen]wasmlib.Key{ ParamAddress, @@ -63,6 +65,7 @@ var keyMap = [keyMapLen]wasmlib.Key{ ParamInt32, ParamInt64, ParamInt8, + ParamKey, ParamName, ParamParam, ParamRecordIndex, @@ -80,6 +83,7 @@ var keyMap = [keyMapLen]wasmlib.Key{ ResultRecord, ResultValue, StateArrays, + StateMaps, StateRandom, } diff --git a/contracts/wasm/testwasmlib/go/testwasmlib/lib.go b/contracts/wasm/testwasmlib/go/testwasmlib/lib.go index 19543d3317..1356e5135a 100644 --- a/contracts/wasm/testwasmlib/go/testwasmlib/lib.go +++ b/contracts/wasm/testwasmlib/go/testwasmlib/lib.go @@ -14,14 +14,19 @@ func OnLoad() { exports.AddFunc(FuncArrayClear, funcArrayClearThunk) exports.AddFunc(FuncArrayCreate, funcArrayCreateThunk) exports.AddFunc(FuncArraySet, funcArraySetThunk) + exports.AddFunc(FuncMapClear, funcMapClearThunk) + exports.AddFunc(FuncMapCreate, funcMapCreateThunk) + exports.AddFunc(FuncMapSet, funcMapSetThunk) exports.AddFunc(FuncParamTypes, funcParamTypesThunk) exports.AddFunc(FuncRandom, funcRandomThunk) + exports.AddFunc(FuncTriggerEvent, funcTriggerEventThunk) exports.AddView(ViewArrayLength, viewArrayLengthThunk) exports.AddView(ViewArrayValue, viewArrayValueThunk) exports.AddView(ViewBlockRecord, viewBlockRecordThunk) exports.AddView(ViewBlockRecords, viewBlockRecordsThunk) exports.AddView(ViewGetRandom, viewGetRandomThunk) exports.AddView(ViewIotaBalance, viewIotaBalanceThunk) + exports.AddView(ViewMapValue, viewMapValueThunk) for i, key := range keyMap { idxMap[i] = key.KeyID() @@ -29,6 +34,7 @@ func OnLoad() { } type ArrayClearContext struct { + Events TestWasmLibEvents Params ImmutableArrayClearParams State MutableTestWasmLibState } @@ -49,6 +55,7 @@ func funcArrayClearThunk(ctx wasmlib.ScFuncContext) { } type ArrayCreateContext struct { + Events TestWasmLibEvents Params ImmutableArrayCreateParams State MutableTestWasmLibState } @@ -69,6 +76,7 @@ func funcArrayCreateThunk(ctx wasmlib.ScFuncContext) { } type ArraySetContext struct { + Events TestWasmLibEvents Params ImmutableArraySetParams State MutableTestWasmLibState } @@ -90,7 +98,73 @@ func funcArraySetThunk(ctx wasmlib.ScFuncContext) { ctx.Log("testwasmlib.funcArraySet ok") } +type MapClearContext struct { + Events TestWasmLibEvents + Params ImmutableMapClearParams + State MutableTestWasmLibState +} + +func funcMapClearThunk(ctx wasmlib.ScFuncContext) { + ctx.Log("testwasmlib.funcMapClear") + f := &MapClearContext{ + Params: ImmutableMapClearParams{ + id: wasmlib.OBJ_ID_PARAMS, + }, + State: MutableTestWasmLibState{ + id: wasmlib.OBJ_ID_STATE, + }, + } + ctx.Require(f.Params.Name().Exists(), "missing mandatory name") + funcMapClear(ctx, f) + ctx.Log("testwasmlib.funcMapClear ok") +} + +type MapCreateContext struct { + Events TestWasmLibEvents + Params ImmutableMapCreateParams + State MutableTestWasmLibState +} + +func funcMapCreateThunk(ctx wasmlib.ScFuncContext) { + ctx.Log("testwasmlib.funcMapCreate") + f := &MapCreateContext{ + Params: ImmutableMapCreateParams{ + id: wasmlib.OBJ_ID_PARAMS, + }, + State: MutableTestWasmLibState{ + id: wasmlib.OBJ_ID_STATE, + }, + } + ctx.Require(f.Params.Name().Exists(), "missing mandatory name") + funcMapCreate(ctx, f) + ctx.Log("testwasmlib.funcMapCreate ok") +} + +type MapSetContext struct { + Events TestWasmLibEvents + Params ImmutableMapSetParams + State MutableTestWasmLibState +} + +func funcMapSetThunk(ctx wasmlib.ScFuncContext) { + ctx.Log("testwasmlib.funcMapSet") + f := &MapSetContext{ + Params: ImmutableMapSetParams{ + id: wasmlib.OBJ_ID_PARAMS, + }, + State: MutableTestWasmLibState{ + id: wasmlib.OBJ_ID_STATE, + }, + } + ctx.Require(f.Params.Key().Exists(), "missing mandatory key") + ctx.Require(f.Params.Name().Exists(), "missing mandatory name") + ctx.Require(f.Params.Value().Exists(), "missing mandatory value") + funcMapSet(ctx, f) + ctx.Log("testwasmlib.funcMapSet ok") +} + type ParamTypesContext struct { + Events TestWasmLibEvents Params ImmutableParamTypesParams State MutableTestWasmLibState } @@ -110,7 +184,8 @@ func funcParamTypesThunk(ctx wasmlib.ScFuncContext) { } type RandomContext struct { - State MutableTestWasmLibState + Events TestWasmLibEvents + State MutableTestWasmLibState } func funcRandomThunk(ctx wasmlib.ScFuncContext) { @@ -124,6 +199,28 @@ func funcRandomThunk(ctx wasmlib.ScFuncContext) { ctx.Log("testwasmlib.funcRandom ok") } +type TriggerEventContext struct { + Events TestWasmLibEvents + Params ImmutableTriggerEventParams + State MutableTestWasmLibState +} + +func funcTriggerEventThunk(ctx wasmlib.ScFuncContext) { + ctx.Log("testwasmlib.funcTriggerEvent") + f := &TriggerEventContext{ + Params: ImmutableTriggerEventParams{ + id: wasmlib.OBJ_ID_PARAMS, + }, + State: MutableTestWasmLibState{ + id: wasmlib.OBJ_ID_STATE, + }, + } + ctx.Require(f.Params.Address().Exists(), "missing mandatory address") + ctx.Require(f.Params.Name().Exists(), "missing mandatory name") + funcTriggerEvent(ctx, f) + ctx.Log("testwasmlib.funcTriggerEvent ok") +} + type ArrayLengthContext struct { Params ImmutableArrayLengthParams Results MutableArrayLengthResults @@ -259,3 +356,28 @@ func viewIotaBalanceThunk(ctx wasmlib.ScViewContext) { viewIotaBalance(ctx, f) ctx.Log("testwasmlib.viewIotaBalance ok") } + +type MapValueContext struct { + Params ImmutableMapValueParams + Results MutableMapValueResults + State ImmutableTestWasmLibState +} + +func viewMapValueThunk(ctx wasmlib.ScViewContext) { + ctx.Log("testwasmlib.viewMapValue") + f := &MapValueContext{ + Params: ImmutableMapValueParams{ + id: wasmlib.OBJ_ID_PARAMS, + }, + Results: MutableMapValueResults{ + id: wasmlib.OBJ_ID_RESULTS, + }, + State: ImmutableTestWasmLibState{ + id: wasmlib.OBJ_ID_STATE, + }, + } + ctx.Require(f.Params.Key().Exists(), "missing mandatory key") + ctx.Require(f.Params.Name().Exists(), "missing mandatory name") + viewMapValue(ctx, f) + ctx.Log("testwasmlib.viewMapValue ok") +} diff --git a/contracts/wasm/testwasmlib/go/testwasmlib/params.go b/contracts/wasm/testwasmlib/go/testwasmlib/params.go index c31fca95d0..dd89b42103 100644 --- a/contracts/wasm/testwasmlib/go/testwasmlib/params.go +++ b/contracts/wasm/testwasmlib/go/testwasmlib/params.go @@ -14,7 +14,7 @@ type ImmutableArrayClearParams struct { } func (s ImmutableArrayClearParams) Name() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxParamName]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamName)) } type MutableArrayClearParams struct { @@ -22,7 +22,7 @@ type MutableArrayClearParams struct { } func (s MutableArrayClearParams) Name() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxParamName]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamName)) } type ImmutableArrayCreateParams struct { @@ -30,7 +30,7 @@ type ImmutableArrayCreateParams struct { } func (s ImmutableArrayCreateParams) Name() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxParamName]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamName)) } type MutableArrayCreateParams struct { @@ -38,7 +38,7 @@ type MutableArrayCreateParams struct { } func (s MutableArrayCreateParams) Name() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxParamName]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamName)) } type ImmutableArraySetParams struct { @@ -46,15 +46,15 @@ type ImmutableArraySetParams struct { } func (s ImmutableArraySetParams) Index() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, idxMap[IdxParamIndex]) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ParamIndex)) } func (s ImmutableArraySetParams) Name() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxParamName]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamName)) } func (s ImmutableArraySetParams) Value() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxParamValue]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamValue)) } type MutableArraySetParams struct { @@ -62,15 +62,79 @@ type MutableArraySetParams struct { } func (s MutableArraySetParams) Index() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, idxMap[IdxParamIndex]) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ParamIndex)) } func (s MutableArraySetParams) Name() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxParamName]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamName)) } func (s MutableArraySetParams) Value() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxParamValue]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamValue)) +} + +type ImmutableMapClearParams struct { + id int32 +} + +func (s ImmutableMapClearParams) Name() wasmlib.ScImmutableString { + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamName)) +} + +type MutableMapClearParams struct { + id int32 +} + +func (s MutableMapClearParams) Name() wasmlib.ScMutableString { + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamName)) +} + +type ImmutableMapCreateParams struct { + id int32 +} + +func (s ImmutableMapCreateParams) Name() wasmlib.ScImmutableString { + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamName)) +} + +type MutableMapCreateParams struct { + id int32 +} + +func (s MutableMapCreateParams) Name() wasmlib.ScMutableString { + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamName)) +} + +type ImmutableMapSetParams struct { + id int32 +} + +func (s ImmutableMapSetParams) Key() wasmlib.ScImmutableString { + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamKey)) +} + +func (s ImmutableMapSetParams) Name() wasmlib.ScImmutableString { + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamName)) +} + +func (s ImmutableMapSetParams) Value() wasmlib.ScImmutableString { + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamValue)) +} + +type MutableMapSetParams struct { + id int32 +} + +func (s MutableMapSetParams) Key() wasmlib.ScMutableString { + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamKey)) +} + +func (s MutableMapSetParams) Name() wasmlib.ScMutableString { + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamName)) +} + +func (s MutableMapSetParams) Value() wasmlib.ScMutableString { + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamValue)) } type MapStringToImmutableBytes struct { @@ -86,51 +150,51 @@ type ImmutableParamTypesParams struct { } func (s ImmutableParamTypesParams) Address() wasmlib.ScImmutableAddress { - return wasmlib.NewScImmutableAddress(s.id, idxMap[IdxParamAddress]) + return wasmlib.NewScImmutableAddress(s.id, wasmlib.KeyID(ParamAddress)) } func (s ImmutableParamTypesParams) AgentID() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamAgentID]) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamAgentID)) } func (s ImmutableParamTypesParams) Bool() wasmlib.ScImmutableBool { - return wasmlib.NewScImmutableBool(s.id, idxMap[IdxParamBool]) + return wasmlib.NewScImmutableBool(s.id, wasmlib.KeyID(ParamBool)) } func (s ImmutableParamTypesParams) Bytes() wasmlib.ScImmutableBytes { - return wasmlib.NewScImmutableBytes(s.id, idxMap[IdxParamBytes]) + return wasmlib.NewScImmutableBytes(s.id, wasmlib.KeyID(ParamBytes)) } func (s ImmutableParamTypesParams) ChainID() wasmlib.ScImmutableChainID { - return wasmlib.NewScImmutableChainID(s.id, idxMap[IdxParamChainID]) + return wasmlib.NewScImmutableChainID(s.id, wasmlib.KeyID(ParamChainID)) } func (s ImmutableParamTypesParams) Color() wasmlib.ScImmutableColor { - return wasmlib.NewScImmutableColor(s.id, idxMap[IdxParamColor]) + return wasmlib.NewScImmutableColor(s.id, wasmlib.KeyID(ParamColor)) } func (s ImmutableParamTypesParams) Hash() wasmlib.ScImmutableHash { - return wasmlib.NewScImmutableHash(s.id, idxMap[IdxParamHash]) + return wasmlib.NewScImmutableHash(s.id, wasmlib.KeyID(ParamHash)) } func (s ImmutableParamTypesParams) Hname() wasmlib.ScImmutableHname { - return wasmlib.NewScImmutableHname(s.id, idxMap[IdxParamHname]) + return wasmlib.NewScImmutableHname(s.id, wasmlib.KeyID(ParamHname)) } func (s ImmutableParamTypesParams) Int16() wasmlib.ScImmutableInt16 { - return wasmlib.NewScImmutableInt16(s.id, idxMap[IdxParamInt16]) + return wasmlib.NewScImmutableInt16(s.id, wasmlib.KeyID(ParamInt16)) } func (s ImmutableParamTypesParams) Int32() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, idxMap[IdxParamInt32]) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ParamInt32)) } func (s ImmutableParamTypesParams) Int64() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxParamInt64]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamInt64)) } func (s ImmutableParamTypesParams) Int8() wasmlib.ScImmutableInt8 { - return wasmlib.NewScImmutableInt8(s.id, idxMap[IdxParamInt8]) + return wasmlib.NewScImmutableInt8(s.id, wasmlib.KeyID(ParamInt8)) } func (s ImmutableParamTypesParams) Param() MapStringToImmutableBytes { @@ -138,27 +202,27 @@ func (s ImmutableParamTypesParams) Param() MapStringToImmutableBytes { } func (s ImmutableParamTypesParams) RequestID() wasmlib.ScImmutableRequestID { - return wasmlib.NewScImmutableRequestID(s.id, idxMap[IdxParamRequestID]) + return wasmlib.NewScImmutableRequestID(s.id, wasmlib.KeyID(ParamRequestID)) } func (s ImmutableParamTypesParams) String() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxParamString]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamString)) } func (s ImmutableParamTypesParams) Uint16() wasmlib.ScImmutableUint16 { - return wasmlib.NewScImmutableUint16(s.id, idxMap[IdxParamUint16]) + return wasmlib.NewScImmutableUint16(s.id, wasmlib.KeyID(ParamUint16)) } func (s ImmutableParamTypesParams) Uint32() wasmlib.ScImmutableUint32 { - return wasmlib.NewScImmutableUint32(s.id, idxMap[IdxParamUint32]) + return wasmlib.NewScImmutableUint32(s.id, wasmlib.KeyID(ParamUint32)) } func (s ImmutableParamTypesParams) Uint64() wasmlib.ScImmutableUint64 { - return wasmlib.NewScImmutableUint64(s.id, idxMap[IdxParamUint64]) + return wasmlib.NewScImmutableUint64(s.id, wasmlib.KeyID(ParamUint64)) } func (s ImmutableParamTypesParams) Uint8() wasmlib.ScImmutableUint8 { - return wasmlib.NewScImmutableUint8(s.id, idxMap[IdxParamUint8]) + return wasmlib.NewScImmutableUint8(s.id, wasmlib.KeyID(ParamUint8)) } type MapStringToMutableBytes struct { @@ -178,51 +242,51 @@ type MutableParamTypesParams struct { } func (s MutableParamTypesParams) Address() wasmlib.ScMutableAddress { - return wasmlib.NewScMutableAddress(s.id, idxMap[IdxParamAddress]) + return wasmlib.NewScMutableAddress(s.id, wasmlib.KeyID(ParamAddress)) } func (s MutableParamTypesParams) AgentID() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamAgentID]) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamAgentID)) } func (s MutableParamTypesParams) Bool() wasmlib.ScMutableBool { - return wasmlib.NewScMutableBool(s.id, idxMap[IdxParamBool]) + return wasmlib.NewScMutableBool(s.id, wasmlib.KeyID(ParamBool)) } func (s MutableParamTypesParams) Bytes() wasmlib.ScMutableBytes { - return wasmlib.NewScMutableBytes(s.id, idxMap[IdxParamBytes]) + return wasmlib.NewScMutableBytes(s.id, wasmlib.KeyID(ParamBytes)) } func (s MutableParamTypesParams) ChainID() wasmlib.ScMutableChainID { - return wasmlib.NewScMutableChainID(s.id, idxMap[IdxParamChainID]) + return wasmlib.NewScMutableChainID(s.id, wasmlib.KeyID(ParamChainID)) } func (s MutableParamTypesParams) Color() wasmlib.ScMutableColor { - return wasmlib.NewScMutableColor(s.id, idxMap[IdxParamColor]) + return wasmlib.NewScMutableColor(s.id, wasmlib.KeyID(ParamColor)) } func (s MutableParamTypesParams) Hash() wasmlib.ScMutableHash { - return wasmlib.NewScMutableHash(s.id, idxMap[IdxParamHash]) + return wasmlib.NewScMutableHash(s.id, wasmlib.KeyID(ParamHash)) } func (s MutableParamTypesParams) Hname() wasmlib.ScMutableHname { - return wasmlib.NewScMutableHname(s.id, idxMap[IdxParamHname]) + return wasmlib.NewScMutableHname(s.id, wasmlib.KeyID(ParamHname)) } func (s MutableParamTypesParams) Int16() wasmlib.ScMutableInt16 { - return wasmlib.NewScMutableInt16(s.id, idxMap[IdxParamInt16]) + return wasmlib.NewScMutableInt16(s.id, wasmlib.KeyID(ParamInt16)) } func (s MutableParamTypesParams) Int32() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, idxMap[IdxParamInt32]) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ParamInt32)) } func (s MutableParamTypesParams) Int64() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxParamInt64]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamInt64)) } func (s MutableParamTypesParams) Int8() wasmlib.ScMutableInt8 { - return wasmlib.NewScMutableInt8(s.id, idxMap[IdxParamInt8]) + return wasmlib.NewScMutableInt8(s.id, wasmlib.KeyID(ParamInt8)) } func (s MutableParamTypesParams) Param() MapStringToMutableBytes { @@ -230,27 +294,51 @@ func (s MutableParamTypesParams) Param() MapStringToMutableBytes { } func (s MutableParamTypesParams) RequestID() wasmlib.ScMutableRequestID { - return wasmlib.NewScMutableRequestID(s.id, idxMap[IdxParamRequestID]) + return wasmlib.NewScMutableRequestID(s.id, wasmlib.KeyID(ParamRequestID)) } func (s MutableParamTypesParams) String() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxParamString]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamString)) } func (s MutableParamTypesParams) Uint16() wasmlib.ScMutableUint16 { - return wasmlib.NewScMutableUint16(s.id, idxMap[IdxParamUint16]) + return wasmlib.NewScMutableUint16(s.id, wasmlib.KeyID(ParamUint16)) } func (s MutableParamTypesParams) Uint32() wasmlib.ScMutableUint32 { - return wasmlib.NewScMutableUint32(s.id, idxMap[IdxParamUint32]) + return wasmlib.NewScMutableUint32(s.id, wasmlib.KeyID(ParamUint32)) } func (s MutableParamTypesParams) Uint64() wasmlib.ScMutableUint64 { - return wasmlib.NewScMutableUint64(s.id, idxMap[IdxParamUint64]) + return wasmlib.NewScMutableUint64(s.id, wasmlib.KeyID(ParamUint64)) } func (s MutableParamTypesParams) Uint8() wasmlib.ScMutableUint8 { - return wasmlib.NewScMutableUint8(s.id, idxMap[IdxParamUint8]) + return wasmlib.NewScMutableUint8(s.id, wasmlib.KeyID(ParamUint8)) +} + +type ImmutableTriggerEventParams struct { + id int32 +} + +func (s ImmutableTriggerEventParams) Address() wasmlib.ScImmutableAddress { + return wasmlib.NewScImmutableAddress(s.id, wasmlib.KeyID(ParamAddress)) +} + +func (s ImmutableTriggerEventParams) Name() wasmlib.ScImmutableString { + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamName)) +} + +type MutableTriggerEventParams struct { + id int32 +} + +func (s MutableTriggerEventParams) Address() wasmlib.ScMutableAddress { + return wasmlib.NewScMutableAddress(s.id, wasmlib.KeyID(ParamAddress)) +} + +func (s MutableTriggerEventParams) Name() wasmlib.ScMutableString { + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamName)) } type ImmutableArrayLengthParams struct { @@ -258,7 +346,7 @@ type ImmutableArrayLengthParams struct { } func (s ImmutableArrayLengthParams) Name() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxParamName]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamName)) } type MutableArrayLengthParams struct { @@ -266,7 +354,7 @@ type MutableArrayLengthParams struct { } func (s MutableArrayLengthParams) Name() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxParamName]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamName)) } type ImmutableArrayValueParams struct { @@ -274,11 +362,11 @@ type ImmutableArrayValueParams struct { } func (s ImmutableArrayValueParams) Index() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, idxMap[IdxParamIndex]) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ParamIndex)) } func (s ImmutableArrayValueParams) Name() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxParamName]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamName)) } type MutableArrayValueParams struct { @@ -286,11 +374,11 @@ type MutableArrayValueParams struct { } func (s MutableArrayValueParams) Index() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, idxMap[IdxParamIndex]) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ParamIndex)) } func (s MutableArrayValueParams) Name() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxParamName]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamName)) } type ImmutableBlockRecordParams struct { @@ -298,11 +386,11 @@ type ImmutableBlockRecordParams struct { } func (s ImmutableBlockRecordParams) BlockIndex() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, idxMap[IdxParamBlockIndex]) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ParamBlockIndex)) } func (s ImmutableBlockRecordParams) RecordIndex() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, idxMap[IdxParamRecordIndex]) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ParamRecordIndex)) } type MutableBlockRecordParams struct { @@ -310,11 +398,11 @@ type MutableBlockRecordParams struct { } func (s MutableBlockRecordParams) BlockIndex() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, idxMap[IdxParamBlockIndex]) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ParamBlockIndex)) } func (s MutableBlockRecordParams) RecordIndex() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, idxMap[IdxParamRecordIndex]) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ParamRecordIndex)) } type ImmutableBlockRecordsParams struct { @@ -322,7 +410,7 @@ type ImmutableBlockRecordsParams struct { } func (s ImmutableBlockRecordsParams) BlockIndex() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, idxMap[IdxParamBlockIndex]) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ParamBlockIndex)) } type MutableBlockRecordsParams struct { @@ -330,5 +418,29 @@ type MutableBlockRecordsParams struct { } func (s MutableBlockRecordsParams) BlockIndex() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, idxMap[IdxParamBlockIndex]) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ParamBlockIndex)) +} + +type ImmutableMapValueParams struct { + id int32 +} + +func (s ImmutableMapValueParams) Key() wasmlib.ScImmutableString { + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamKey)) +} + +func (s ImmutableMapValueParams) Name() wasmlib.ScImmutableString { + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamName)) +} + +type MutableMapValueParams struct { + id int32 +} + +func (s MutableMapValueParams) Key() wasmlib.ScMutableString { + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamKey)) +} + +func (s MutableMapValueParams) Name() wasmlib.ScMutableString { + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamName)) } diff --git a/contracts/wasm/testwasmlib/go/testwasmlib/results.go b/contracts/wasm/testwasmlib/go/testwasmlib/results.go index 9cb62e01e0..4426bd9cea 100644 --- a/contracts/wasm/testwasmlib/go/testwasmlib/results.go +++ b/contracts/wasm/testwasmlib/go/testwasmlib/results.go @@ -14,7 +14,7 @@ type ImmutableArrayLengthResults struct { } func (s ImmutableArrayLengthResults) Length() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, idxMap[IdxResultLength]) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ResultLength)) } type MutableArrayLengthResults struct { @@ -22,7 +22,7 @@ type MutableArrayLengthResults struct { } func (s MutableArrayLengthResults) Length() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, idxMap[IdxResultLength]) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ResultLength)) } type ImmutableArrayValueResults struct { @@ -30,7 +30,7 @@ type ImmutableArrayValueResults struct { } func (s ImmutableArrayValueResults) Value() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxResultValue]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ResultValue)) } type MutableArrayValueResults struct { @@ -38,7 +38,7 @@ type MutableArrayValueResults struct { } func (s MutableArrayValueResults) Value() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxResultValue]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ResultValue)) } type ImmutableBlockRecordResults struct { @@ -46,7 +46,7 @@ type ImmutableBlockRecordResults struct { } func (s ImmutableBlockRecordResults) Record() wasmlib.ScImmutableBytes { - return wasmlib.NewScImmutableBytes(s.id, idxMap[IdxResultRecord]) + return wasmlib.NewScImmutableBytes(s.id, wasmlib.KeyID(ResultRecord)) } type MutableBlockRecordResults struct { @@ -54,7 +54,7 @@ type MutableBlockRecordResults struct { } func (s MutableBlockRecordResults) Record() wasmlib.ScMutableBytes { - return wasmlib.NewScMutableBytes(s.id, idxMap[IdxResultRecord]) + return wasmlib.NewScMutableBytes(s.id, wasmlib.KeyID(ResultRecord)) } type ImmutableBlockRecordsResults struct { @@ -62,7 +62,7 @@ type ImmutableBlockRecordsResults struct { } func (s ImmutableBlockRecordsResults) Count() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, idxMap[IdxResultCount]) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ResultCount)) } type MutableBlockRecordsResults struct { @@ -70,7 +70,7 @@ type MutableBlockRecordsResults struct { } func (s MutableBlockRecordsResults) Count() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, idxMap[IdxResultCount]) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ResultCount)) } type ImmutableGetRandomResults struct { @@ -78,7 +78,7 @@ type ImmutableGetRandomResults struct { } func (s ImmutableGetRandomResults) Random() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultRandom]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultRandom)) } type MutableGetRandomResults struct { @@ -86,7 +86,7 @@ type MutableGetRandomResults struct { } func (s MutableGetRandomResults) Random() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultRandom]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultRandom)) } type ImmutableIotaBalanceResults struct { @@ -94,7 +94,7 @@ type ImmutableIotaBalanceResults struct { } func (s ImmutableIotaBalanceResults) Iotas() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultIotas]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultIotas)) } type MutableIotaBalanceResults struct { @@ -102,5 +102,21 @@ type MutableIotaBalanceResults struct { } func (s MutableIotaBalanceResults) Iotas() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultIotas]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultIotas)) +} + +type ImmutableMapValueResults struct { + id int32 +} + +func (s ImmutableMapValueResults) Value() wasmlib.ScImmutableString { + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ResultValue)) +} + +type MutableMapValueResults struct { + id int32 +} + +func (s MutableMapValueResults) Value() wasmlib.ScMutableString { + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ResultValue)) } diff --git a/contracts/wasm/testwasmlib/go/testwasmlib/state.go b/contracts/wasm/testwasmlib/go/testwasmlib/state.go index 7d08d8f873..47bd6093a9 100644 --- a/contracts/wasm/testwasmlib/go/testwasmlib/state.go +++ b/contracts/wasm/testwasmlib/go/testwasmlib/state.go @@ -18,17 +18,31 @@ func (m MapStringToImmutableStringArray) GetStringArray(key string) ImmutableStr return ImmutableStringArray{objID: subID} } +type MapStringToImmutableStringMap struct { + objID int32 +} + +func (m MapStringToImmutableStringMap) GetStringMap(key string) ImmutableStringMap { + subID := wasmlib.GetObjectID(m.objID, wasmlib.Key(key).KeyID(), wasmlib.TYPE_MAP) + return ImmutableStringMap{objID: subID} +} + type ImmutableTestWasmLibState struct { id int32 } func (s ImmutableTestWasmLibState) Arrays() MapStringToImmutableStringArray { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateArrays], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateArrays), wasmlib.TYPE_MAP) return MapStringToImmutableStringArray{objID: mapID} } +func (s ImmutableTestWasmLibState) Maps() MapStringToImmutableStringMap { + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateMaps), wasmlib.TYPE_MAP) + return MapStringToImmutableStringMap{objID: mapID} +} + func (s ImmutableTestWasmLibState) Random() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxStateRandom]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(StateRandom)) } type MapStringToMutableStringArray struct { @@ -44,15 +58,37 @@ func (m MapStringToMutableStringArray) GetStringArray(key string) MutableStringA return MutableStringArray{objID: subID} } +type MapStringToMutableStringMap struct { + objID int32 +} + +func (m MapStringToMutableStringMap) Clear() { + wasmlib.Clear(m.objID) +} + +func (m MapStringToMutableStringMap) GetStringMap(key string) MutableStringMap { + subID := wasmlib.GetObjectID(m.objID, wasmlib.Key(key).KeyID(), wasmlib.TYPE_MAP) + return MutableStringMap{objID: subID} +} + type MutableTestWasmLibState struct { id int32 } +func (s MutableTestWasmLibState) AsImmutable() ImmutableTestWasmLibState { + return ImmutableTestWasmLibState(s) +} + func (s MutableTestWasmLibState) Arrays() MapStringToMutableStringArray { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateArrays], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateArrays), wasmlib.TYPE_MAP) return MapStringToMutableStringArray{objID: mapID} } +func (s MutableTestWasmLibState) Maps() MapStringToMutableStringMap { + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateMaps), wasmlib.TYPE_MAP) + return MapStringToMutableStringMap{objID: mapID} +} + func (s MutableTestWasmLibState) Random() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxStateRandom]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(StateRandom)) } diff --git a/contracts/wasm/testwasmlib/go/testwasmlib/structs.go b/contracts/wasm/testwasmlib/go/testwasmlib/structs.go new file mode 100644 index 0000000000..f57de29a9d --- /dev/null +++ b/contracts/wasm/testwasmlib/go/testwasmlib/structs.go @@ -0,0 +1,65 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// (Re-)generated by schema tool +// >>>> DO NOT CHANGE THIS FILE! <<<< +// Change the json schema instead + +package testwasmlib + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + +type Location struct { + X int32 + Y int32 +} + +func NewLocationFromBytes(bytes []byte) *Location { + decode := wasmlib.NewBytesDecoder(bytes) + data := &Location{} + data.X = decode.Int32() + data.Y = decode.Int32() + decode.Close() + return data +} + +func (o *Location) Bytes() []byte { + return wasmlib.NewBytesEncoder(). + Int32(o.X). + Int32(o.Y). + Data() +} + +type ImmutableLocation struct { + objID int32 + keyID wasmlib.Key32 +} + +func (o ImmutableLocation) Exists() bool { + return wasmlib.Exists(o.objID, o.keyID, wasmlib.TYPE_BYTES) +} + +func (o ImmutableLocation) Value() *Location { + return NewLocationFromBytes(wasmlib.GetBytes(o.objID, o.keyID, wasmlib.TYPE_BYTES)) +} + +type MutableLocation struct { + objID int32 + keyID wasmlib.Key32 +} + +func (o MutableLocation) Delete() { + wasmlib.DelKey(o.objID, o.keyID, wasmlib.TYPE_BYTES) +} + +func (o MutableLocation) Exists() bool { + return wasmlib.Exists(o.objID, o.keyID, wasmlib.TYPE_BYTES) +} + +func (o MutableLocation) SetValue(value *Location) { + wasmlib.SetBytes(o.objID, o.keyID, wasmlib.TYPE_BYTES, value.Bytes()) +} + +func (o MutableLocation) Value() *Location { + return NewLocationFromBytes(wasmlib.GetBytes(o.objID, o.keyID, wasmlib.TYPE_BYTES)) +} diff --git a/contracts/wasm/testwasmlib/go/testwasmlib/testwasmlib.go b/contracts/wasm/testwasmlib/go/testwasmlib/testwasmlib.go index dba9a43d1f..8efb37d99e 100644 --- a/contracts/wasm/testwasmlib/go/testwasmlib/testwasmlib.go +++ b/contracts/wasm/testwasmlib/go/testwasmlib/testwasmlib.go @@ -133,3 +133,34 @@ func funcRandom(ctx wasmlib.ScFuncContext, f *RandomContext) { func viewGetRandom(ctx wasmlib.ScViewContext, f *GetRandomContext) { f.Results.Random().SetValue(f.State.Random().Value()) } + +func funcTriggerEvent(ctx wasmlib.ScFuncContext, f *TriggerEventContext) { + f.Events.Test(f.Params.Address().Value(), f.Params.Name().Value()) +} + +func funcMapClear(ctx wasmlib.ScFuncContext, f *MapClearContext) { + name := f.Params.Name().Value() + myMap := f.State.Maps().GetStringMap(name) + myMap.Clear() +} + +func funcMapCreate(ctx wasmlib.ScFuncContext, f *MapCreateContext) { + name := f.Params.Name().Value() + myMap := f.State.Maps().GetStringMap(name) + myMap.Clear() +} + +func funcMapSet(ctx wasmlib.ScFuncContext, f *MapSetContext) { + name := f.Params.Name().Value() + myMap := f.State.Maps().GetStringMap(name) + key := f.Params.Key().Value() + value := f.Params.Value().Value() + myMap.GetString(key).SetValue(value) +} + +func viewMapValue(ctx wasmlib.ScViewContext, f *MapValueContext) { + name := f.Params.Name().Value() + myMap := f.State.Maps().GetStringMap(name) + key := f.Params.Key().Value() + f.Results.Value().SetValue(myMap.GetString(key).Value()) +} diff --git a/contracts/wasm/testwasmlib/go/testwasmlib/typedefs.go b/contracts/wasm/testwasmlib/go/testwasmlib/typedefs.go index 28df5b3ef7..97090d3d58 100644 --- a/contracts/wasm/testwasmlib/go/testwasmlib/typedefs.go +++ b/contracts/wasm/testwasmlib/go/testwasmlib/typedefs.go @@ -40,3 +40,27 @@ func (a ArrayOfMutableString) GetString(index int32) wasmlib.ScMutableString { } type MutableStringArray = ArrayOfMutableString + +type MapStringToImmutableString struct { + objID int32 +} + +func (m MapStringToImmutableString) GetString(key string) wasmlib.ScImmutableString { + return wasmlib.NewScImmutableString(m.objID, wasmlib.Key(key).KeyID()) +} + +type ImmutableStringMap = MapStringToImmutableString + +type MapStringToMutableString struct { + objID int32 +} + +func (m MapStringToMutableString) Clear() { + wasmlib.Clear(m.objID) +} + +func (m MapStringToMutableString) GetString(key string) wasmlib.ScMutableString { + return wasmlib.NewScMutableString(m.objID, wasmlib.Key(key).KeyID()) +} + +type MutableStringMap = MapStringToMutableString diff --git a/contracts/wasm/testwasmlib/go/testwasmlibclient/events.go b/contracts/wasm/testwasmlib/go/testwasmlibclient/events.go new file mode 100644 index 0000000000..e0c3faf93c --- /dev/null +++ b/contracts/wasm/testwasmlib/go/testwasmlibclient/events.go @@ -0,0 +1,28 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// (Re-)generated by schema tool +// >>>> DO NOT CHANGE THIS FILE! <<<< +// Change the json schema instead + +package testwasmlibclient + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmclient" + +var EventHandlers = map[string]func([]string){ + "testwasmlib.test": onTestWasmLibTestThunk, +} + +type EventTest struct { + wasmclient.Event + Address wasmclient.Address + Name string +} + +func onTestWasmLibTestThunk(message []string) { + e := &EventTest{} + e.Init(message) + e.Address = e.NextAddress() + e.Name = e.NextString() + OnTestWasmLibTest(e) +} diff --git a/contracts/wasm/testwasmlib/go/testwasmlibclient/service.go b/contracts/wasm/testwasmlib/go/testwasmlibclient/service.go new file mode 100644 index 0000000000..60b4dbd9fb --- /dev/null +++ b/contracts/wasm/testwasmlib/go/testwasmlibclient/service.go @@ -0,0 +1,533 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// (Re-)generated by schema tool +// >>>> DO NOT CHANGE THIS FILE! <<<< +// Change the json schema instead + +package testwasmlibclient + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmclient" + +const ( + ArgAddress = "address" + ArgAgentID = "agentID" + ArgBlockIndex = "blockIndex" + ArgBool = "bool" + ArgBytes = "bytes" + ArgChainID = "chainID" + ArgColor = "color" + ArgHash = "hash" + ArgHname = "hname" + ArgIndex = "index" + ArgInt16 = "int16" + ArgInt32 = "int32" + ArgInt64 = "int64" + ArgInt8 = "int8" + ArgKey = "key" + ArgName = "name" + ArgParam = "this" + ArgRecordIndex = "recordIndex" + ArgRequestID = "requestID" + ArgString = "string" + ArgUint16 = "uint16" + ArgUint32 = "uint32" + ArgUint64 = "uint64" + ArgUint8 = "uint8" + ArgValue = "value" + + ResCount = "count" + ResIotas = "iotas" + ResLength = "length" + ResRandom = "random" + ResRecord = "record" + ResValue = "value" +) + +///////////////////////////// arrayClear ///////////////////////////// + +type ArrayClearFunc struct { + wasmclient.ClientFunc + args wasmclient.Arguments +} + +func (f *ArrayClearFunc) Name(v string) { + f.args.Set(ArgName, f.args.FromString(v)) +} + +func (f *ArrayClearFunc) Post() wasmclient.Request { + f.args.Mandatory(ArgName) + return f.ClientFunc.Post(0x88021821, &f.args) +} + +///////////////////////////// arrayCreate ///////////////////////////// + +type ArrayCreateFunc struct { + wasmclient.ClientFunc + args wasmclient.Arguments +} + +func (f *ArrayCreateFunc) Name(v string) { + f.args.Set(ArgName, f.args.FromString(v)) +} + +func (f *ArrayCreateFunc) Post() wasmclient.Request { + f.args.Mandatory(ArgName) + return f.ClientFunc.Post(0x1ed5b23b, &f.args) +} + +///////////////////////////// arraySet ///////////////////////////// + +type ArraySetFunc struct { + wasmclient.ClientFunc + args wasmclient.Arguments +} + +func (f *ArraySetFunc) Index(v int32) { + f.args.Set(ArgIndex, f.args.FromInt32(v)) +} + +func (f *ArraySetFunc) Name(v string) { + f.args.Set(ArgName, f.args.FromString(v)) +} + +func (f *ArraySetFunc) Value(v string) { + f.args.Set(ArgValue, f.args.FromString(v)) +} + +func (f *ArraySetFunc) Post() wasmclient.Request { + f.args.Mandatory(ArgIndex) + f.args.Mandatory(ArgName) + f.args.Mandatory(ArgValue) + return f.ClientFunc.Post(0x2c4150b3, &f.args) +} + +///////////////////////////// mapClear ///////////////////////////// + +type MapClearFunc struct { + wasmclient.ClientFunc + args wasmclient.Arguments +} + +func (f *MapClearFunc) Name(v string) { + f.args.Set(ArgName, f.args.FromString(v)) +} + +func (f *MapClearFunc) Post() wasmclient.Request { + f.args.Mandatory(ArgName) + return f.ClientFunc.Post(0x027f215a, &f.args) +} + +///////////////////////////// mapCreate ///////////////////////////// + +type MapCreateFunc struct { + wasmclient.ClientFunc + args wasmclient.Arguments +} + +func (f *MapCreateFunc) Name(v string) { + f.args.Set(ArgName, f.args.FromString(v)) +} + +func (f *MapCreateFunc) Post() wasmclient.Request { + f.args.Mandatory(ArgName) + return f.ClientFunc.Post(0x6295d599, &f.args) +} + +///////////////////////////// mapSet ///////////////////////////// + +type MapSetFunc struct { + wasmclient.ClientFunc + args wasmclient.Arguments +} + +func (f *MapSetFunc) Key(v string) { + f.args.Set(ArgKey, f.args.FromString(v)) +} + +func (f *MapSetFunc) Name(v string) { + f.args.Set(ArgName, f.args.FromString(v)) +} + +func (f *MapSetFunc) Value(v string) { + f.args.Set(ArgValue, f.args.FromString(v)) +} + +func (f *MapSetFunc) Post() wasmclient.Request { + f.args.Mandatory(ArgKey) + f.args.Mandatory(ArgName) + f.args.Mandatory(ArgValue) + return f.ClientFunc.Post(0xf2260404, &f.args) +} + +///////////////////////////// paramTypes ///////////////////////////// + +type ParamTypesFunc struct { + wasmclient.ClientFunc + args wasmclient.Arguments +} + +func (f *ParamTypesFunc) Address(v wasmclient.Address) { + f.args.Set(ArgAddress, f.args.FromAddress(v)) +} + +func (f *ParamTypesFunc) AgentID(v wasmclient.AgentID) { + f.args.Set(ArgAgentID, f.args.FromAgentID(v)) +} + +func (f *ParamTypesFunc) Bool(v bool) { + f.args.Set(ArgBool, f.args.FromBool(v)) +} + +func (f *ParamTypesFunc) Bytes(v []byte) { + f.args.Set(ArgBytes, f.args.FromBytes(v)) +} + +func (f *ParamTypesFunc) ChainID(v wasmclient.ChainID) { + f.args.Set(ArgChainID, f.args.FromChainID(v)) +} + +func (f *ParamTypesFunc) Color(v wasmclient.Color) { + f.args.Set(ArgColor, f.args.FromColor(v)) +} + +func (f *ParamTypesFunc) Hash(v wasmclient.Hash) { + f.args.Set(ArgHash, f.args.FromHash(v)) +} + +func (f *ParamTypesFunc) Hname(v wasmclient.Hname) { + f.args.Set(ArgHname, f.args.FromHname(v)) +} + +func (f *ParamTypesFunc) Int16(v int16) { + f.args.Set(ArgInt16, f.args.FromInt16(v)) +} + +func (f *ParamTypesFunc) Int32(v int32) { + f.args.Set(ArgInt32, f.args.FromInt32(v)) +} + +func (f *ParamTypesFunc) Int64(v int64) { + f.args.Set(ArgInt64, f.args.FromInt64(v)) +} + +func (f *ParamTypesFunc) Int8(v int8) { + f.args.Set(ArgInt8, f.args.FromInt8(v)) +} + +func (f *ParamTypesFunc) Param(v []byte) { + f.args.Set(ArgParam, f.args.FromBytes(v)) +} + +func (f *ParamTypesFunc) RequestID(v wasmclient.RequestID) { + f.args.Set(ArgRequestID, f.args.FromRequestID(v)) +} + +func (f *ParamTypesFunc) String(v string) { + f.args.Set(ArgString, f.args.FromString(v)) +} + +func (f *ParamTypesFunc) Uint16(v uint16) { + f.args.Set(ArgUint16, f.args.FromUint16(v)) +} + +func (f *ParamTypesFunc) Uint32(v uint32) { + f.args.Set(ArgUint32, f.args.FromUint32(v)) +} + +func (f *ParamTypesFunc) Uint64(v uint64) { + f.args.Set(ArgUint64, f.args.FromUint64(v)) +} + +func (f *ParamTypesFunc) Uint8(v uint8) { + f.args.Set(ArgUint8, f.args.FromUint8(v)) +} + +func (f *ParamTypesFunc) Post() wasmclient.Request { + return f.ClientFunc.Post(0x6921c4cd, &f.args) +} + +///////////////////////////// random ///////////////////////////// + +type RandomFunc struct { + wasmclient.ClientFunc +} + +func (f *RandomFunc) Post() wasmclient.Request { + return f.ClientFunc.Post(0xe86c97ca, nil) +} + +///////////////////////////// triggerEvent ///////////////////////////// + +type TriggerEventFunc struct { + wasmclient.ClientFunc + args wasmclient.Arguments +} + +func (f *TriggerEventFunc) Address(v wasmclient.Address) { + f.args.Set(ArgAddress, f.args.FromAddress(v)) +} + +func (f *TriggerEventFunc) Name(v string) { + f.args.Set(ArgName, f.args.FromString(v)) +} + +func (f *TriggerEventFunc) Post() wasmclient.Request { + f.args.Mandatory(ArgAddress) + f.args.Mandatory(ArgName) + return f.ClientFunc.Post(0xd5438ac6, &f.args) +} + +///////////////////////////// arrayLength ///////////////////////////// + +type ArrayLengthView struct { + wasmclient.ClientView + args wasmclient.Arguments +} + +func (f *ArrayLengthView) Name(v string) { + f.args.Set(ArgName, f.args.FromString(v)) +} + +func (f *ArrayLengthView) Call() ArrayLengthResults { + f.args.Mandatory(ArgName) + f.ClientView.Call("arrayLength", &f.args) + return ArrayLengthResults{res: f.Results()} +} + +type ArrayLengthResults struct { + res wasmclient.Results +} + +func (r *ArrayLengthResults) Length() int32 { + return r.res.ToInt32(r.res.Get(ResLength)) +} + +///////////////////////////// arrayValue ///////////////////////////// + +type ArrayValueView struct { + wasmclient.ClientView + args wasmclient.Arguments +} + +func (f *ArrayValueView) Index(v int32) { + f.args.Set(ArgIndex, f.args.FromInt32(v)) +} + +func (f *ArrayValueView) Name(v string) { + f.args.Set(ArgName, f.args.FromString(v)) +} + +func (f *ArrayValueView) Call() ArrayValueResults { + f.args.Mandatory(ArgIndex) + f.args.Mandatory(ArgName) + f.ClientView.Call("arrayValue", &f.args) + return ArrayValueResults{res: f.Results()} +} + +type ArrayValueResults struct { + res wasmclient.Results +} + +func (r *ArrayValueResults) Value() string { + return r.res.ToString(r.res.Get(ResValue)) +} + +///////////////////////////// blockRecord ///////////////////////////// + +type BlockRecordView struct { + wasmclient.ClientView + args wasmclient.Arguments +} + +func (f *BlockRecordView) BlockIndex(v int32) { + f.args.Set(ArgBlockIndex, f.args.FromInt32(v)) +} + +func (f *BlockRecordView) RecordIndex(v int32) { + f.args.Set(ArgRecordIndex, f.args.FromInt32(v)) +} + +func (f *BlockRecordView) Call() BlockRecordResults { + f.args.Mandatory(ArgBlockIndex) + f.args.Mandatory(ArgRecordIndex) + f.ClientView.Call("blockRecord", &f.args) + return BlockRecordResults{res: f.Results()} +} + +type BlockRecordResults struct { + res wasmclient.Results +} + +func (r *BlockRecordResults) Record() []byte { + return r.res.ToBytes(r.res.Get(ResRecord)) +} + +///////////////////////////// blockRecords ///////////////////////////// + +type BlockRecordsView struct { + wasmclient.ClientView + args wasmclient.Arguments +} + +func (f *BlockRecordsView) BlockIndex(v int32) { + f.args.Set(ArgBlockIndex, f.args.FromInt32(v)) +} + +func (f *BlockRecordsView) Call() BlockRecordsResults { + f.args.Mandatory(ArgBlockIndex) + f.ClientView.Call("blockRecords", &f.args) + return BlockRecordsResults{res: f.Results()} +} + +type BlockRecordsResults struct { + res wasmclient.Results +} + +func (r *BlockRecordsResults) Count() int32 { + return r.res.ToInt32(r.res.Get(ResCount)) +} + +///////////////////////////// getRandom ///////////////////////////// + +type GetRandomView struct { + wasmclient.ClientView +} + +func (f *GetRandomView) Call() GetRandomResults { + f.ClientView.Call("getRandom", nil) + return GetRandomResults{res: f.Results()} +} + +type GetRandomResults struct { + res wasmclient.Results +} + +func (r *GetRandomResults) Random() int64 { + return r.res.ToInt64(r.res.Get(ResRandom)) +} + +///////////////////////////// iotaBalance ///////////////////////////// + +type IotaBalanceView struct { + wasmclient.ClientView +} + +func (f *IotaBalanceView) Call() IotaBalanceResults { + f.ClientView.Call("iotaBalance", nil) + return IotaBalanceResults{res: f.Results()} +} + +type IotaBalanceResults struct { + res wasmclient.Results +} + +func (r *IotaBalanceResults) Iotas() int64 { + return r.res.ToInt64(r.res.Get(ResIotas)) +} + +///////////////////////////// mapValue ///////////////////////////// + +type MapValueView struct { + wasmclient.ClientView + args wasmclient.Arguments +} + +func (f *MapValueView) Key(v string) { + f.args.Set(ArgKey, f.args.FromString(v)) +} + +func (f *MapValueView) Name(v string) { + f.args.Set(ArgName, f.args.FromString(v)) +} + +func (f *MapValueView) Call() MapValueResults { + f.args.Mandatory(ArgKey) + f.args.Mandatory(ArgName) + f.ClientView.Call("mapValue", &f.args) + return MapValueResults{res: f.Results()} +} + +type MapValueResults struct { + res wasmclient.Results +} + +func (r *MapValueResults) Value() string { + return r.res.ToString(r.res.Get(ResValue)) +} + +///////////////////////////// TestWasmLibService ///////////////////////////// + +type TestWasmLibService struct { + wasmclient.Service +} + +func NewTestWasmLibService(cl *wasmclient.ServiceClient, chainID string) (*TestWasmLibService, error) { + s := &TestWasmLibService{} + err := s.Service.Init(cl, chainID, 0x89703a45, EventHandlers) + return s, err +} + +func (s *TestWasmLibService) ArrayClear() ArrayClearFunc { + return ArrayClearFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *TestWasmLibService) ArrayCreate() ArrayCreateFunc { + return ArrayCreateFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *TestWasmLibService) ArraySet() ArraySetFunc { + return ArraySetFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *TestWasmLibService) MapClear() MapClearFunc { + return MapClearFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *TestWasmLibService) MapCreate() MapCreateFunc { + return MapCreateFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *TestWasmLibService) MapSet() MapSetFunc { + return MapSetFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *TestWasmLibService) ParamTypes() ParamTypesFunc { + return ParamTypesFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *TestWasmLibService) Random() RandomFunc { + return RandomFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *TestWasmLibService) TriggerEvent() TriggerEventFunc { + return TriggerEventFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *TestWasmLibService) ArrayLength() ArrayLengthView { + return ArrayLengthView{ClientView: s.AsClientView()} +} + +func (s *TestWasmLibService) ArrayValue() ArrayValueView { + return ArrayValueView{ClientView: s.AsClientView()} +} + +func (s *TestWasmLibService) BlockRecord() BlockRecordView { + return BlockRecordView{ClientView: s.AsClientView()} +} + +func (s *TestWasmLibService) BlockRecords() BlockRecordsView { + return BlockRecordsView{ClientView: s.AsClientView()} +} + +func (s *TestWasmLibService) GetRandom() GetRandomView { + return GetRandomView{ClientView: s.AsClientView()} +} + +func (s *TestWasmLibService) IotaBalance() IotaBalanceView { + return IotaBalanceView{ClientView: s.AsClientView()} +} + +func (s *TestWasmLibService) MapValue() MapValueView { + return MapValueView{ClientView: s.AsClientView()} +} diff --git a/contracts/wasm/testwasmlib/go/testwasmlibclient/testwasmlib.go b/contracts/wasm/testwasmlib/go/testwasmlibclient/testwasmlib.go new file mode 100644 index 0000000000..205f7ffd4d --- /dev/null +++ b/contracts/wasm/testwasmlib/go/testwasmlibclient/testwasmlib.go @@ -0,0 +1,7 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package testwasmlibclient + +func OnTestWasmLibTest(event *EventTest) { +} diff --git a/contracts/wasm/testwasmlib/schema.yaml b/contracts/wasm/testwasmlib/schema.yaml index 05b9d67cb9..7b1358e733 100644 --- a/contracts/wasm/testwasmlib/schema.yaml +++ b/contracts/wasm/testwasmlib/schema.yaml @@ -1,23 +1,66 @@ name: TestWasmLib -description: Exercise all aspects of WasmLib -structs: {} +description: Exercise several aspects of WasmLib + +# ################################## +events: +# ################################## + test: + name: String + address: Address + +# ################################## +structs: +# ################################## +# Location: +# x: Int32 +# y: Int32 + +# ################################## typedefs: +# ################################## StringArray: String[] + StringMap: map[String]String +# Longitude: map[Int32]Location + +# ################################## state: +# ################################## arrays: map[String]StringArray + maps: map[String]StringMap random: Int64 +# latLong: map[Int32]Longitude + +# ################################## funcs: +# ################################## arrayClear: params: name: String + arrayCreate: params: name: String + arraySet: params: index: Int32 name: String value: String + + mapClear: + params: + name: String + + mapCreate: + params: + name: String + + mapSet: + params: + name: String + key: String + value: String + paramTypes: params: address: Address? @@ -39,33 +82,54 @@ funcs: uint16: Uint16? uint32: Uint32? uint64: Uint64? + random: + + triggerEvent: + params: + name: String + address: Address + +# ################################## views: +# ################################## arrayLength: params: name: String results: length: Int32 + arrayValue: params: index: Int32 name: String results: value: String + blockRecord: params: blockIndex: Int32 recordIndex: Int32 results: record: Bytes + blockRecords: params: blockIndex: Int32 results: count: Int32 + iotaBalance: results: iotas: Int64 + + mapValue: + params: + name: String + key: String + results: + value: String + getRandom: results: random: Int64 diff --git a/contracts/wasm/testwasmlib/src/consts.rs b/contracts/wasm/testwasmlib/src/consts.rs index 8af1763e67..8842bfad04 100644 --- a/contracts/wasm/testwasmlib/src/consts.rs +++ b/contracts/wasm/testwasmlib/src/consts.rs @@ -10,7 +10,7 @@ use wasmlib::*; pub const SC_NAME : &str = "testwasmlib"; -pub const SC_DESCRIPTION : &str = "Exercise all aspects of WasmLib"; +pub const SC_DESCRIPTION : &str = "Exercise several aspects of WasmLib"; pub const HSC_NAME : ScHname = ScHname(0x89703a45); pub const PARAM_ADDRESS : &str = "address"; @@ -27,6 +27,7 @@ pub const PARAM_INT16 : &str = "int16"; pub const PARAM_INT32 : &str = "int32"; pub const PARAM_INT64 : &str = "int64"; pub const PARAM_INT8 : &str = "int8"; +pub const PARAM_KEY : &str = "key"; pub const PARAM_NAME : &str = "name"; pub const PARAM_PARAM : &str = "this"; pub const PARAM_RECORD_INDEX : &str = "recordIndex"; @@ -46,28 +47,39 @@ pub const RESULT_RECORD : &str = "record"; pub const RESULT_VALUE : &str = "value"; pub const STATE_ARRAYS : &str = "arrays"; +pub const STATE_MAPS : &str = "maps"; pub const STATE_RANDOM : &str = "random"; pub const FUNC_ARRAY_CLEAR : &str = "arrayClear"; pub const FUNC_ARRAY_CREATE : &str = "arrayCreate"; pub const FUNC_ARRAY_SET : &str = "arraySet"; +pub const FUNC_MAP_CLEAR : &str = "mapClear"; +pub const FUNC_MAP_CREATE : &str = "mapCreate"; +pub const FUNC_MAP_SET : &str = "mapSet"; pub const FUNC_PARAM_TYPES : &str = "paramTypes"; pub const FUNC_RANDOM : &str = "random"; +pub const FUNC_TRIGGER_EVENT : &str = "triggerEvent"; pub const VIEW_ARRAY_LENGTH : &str = "arrayLength"; pub const VIEW_ARRAY_VALUE : &str = "arrayValue"; pub const VIEW_BLOCK_RECORD : &str = "blockRecord"; pub const VIEW_BLOCK_RECORDS : &str = "blockRecords"; pub const VIEW_GET_RANDOM : &str = "getRandom"; pub const VIEW_IOTA_BALANCE : &str = "iotaBalance"; +pub const VIEW_MAP_VALUE : &str = "mapValue"; pub const HFUNC_ARRAY_CLEAR : ScHname = ScHname(0x88021821); pub const HFUNC_ARRAY_CREATE : ScHname = ScHname(0x1ed5b23b); pub const HFUNC_ARRAY_SET : ScHname = ScHname(0x2c4150b3); +pub const HFUNC_MAP_CLEAR : ScHname = ScHname(0x027f215a); +pub const HFUNC_MAP_CREATE : ScHname = ScHname(0x6295d599); +pub const HFUNC_MAP_SET : ScHname = ScHname(0xf2260404); pub const HFUNC_PARAM_TYPES : ScHname = ScHname(0x6921c4cd); pub const HFUNC_RANDOM : ScHname = ScHname(0xe86c97ca); +pub const HFUNC_TRIGGER_EVENT : ScHname = ScHname(0xd5438ac6); pub const HVIEW_ARRAY_LENGTH : ScHname = ScHname(0x3a831021); pub const HVIEW_ARRAY_VALUE : ScHname = ScHname(0x662dbd81); pub const HVIEW_BLOCK_RECORD : ScHname = ScHname(0xad13b2f8); pub const HVIEW_BLOCK_RECORDS : ScHname = ScHname(0x16e249ea); pub const HVIEW_GET_RANDOM : ScHname = ScHname(0x46263045); pub const HVIEW_IOTA_BALANCE : ScHname = ScHname(0x9d3920bd); +pub const HVIEW_MAP_VALUE : ScHname = ScHname(0x23149bef); diff --git a/contracts/wasm/testwasmlib/src/contract.rs b/contracts/wasm/testwasmlib/src/contract.rs index 5df0ede6ee..8de723d684 100644 --- a/contracts/wasm/testwasmlib/src/contract.rs +++ b/contracts/wasm/testwasmlib/src/contract.rs @@ -30,6 +30,21 @@ pub struct ArraySetCall { pub params: MutableArraySetParams, } +pub struct MapClearCall { + pub func: ScFunc, + pub params: MutableMapClearParams, +} + +pub struct MapCreateCall { + pub func: ScFunc, + pub params: MutableMapCreateParams, +} + +pub struct MapSetCall { + pub func: ScFunc, + pub params: MutableMapSetParams, +} + pub struct ParamTypesCall { pub func: ScFunc, pub params: MutableParamTypesParams, @@ -39,6 +54,11 @@ pub struct RandomCall { pub func: ScFunc, } +pub struct TriggerEventCall { + pub func: ScFunc, + pub params: MutableTriggerEventParams, +} + pub struct ArrayLengthCall { pub func: ScView, pub params: MutableArrayLengthParams, @@ -73,6 +93,12 @@ pub struct IotaBalanceCall { pub results: ImmutableIotaBalanceResults, } +pub struct MapValueCall { + pub func: ScView, + pub params: MutableMapValueParams, + pub results: ImmutableMapValueResults, +} + pub struct ScFuncs { } @@ -104,6 +130,33 @@ impl ScFuncs { f } + pub fn map_clear(_ctx: & dyn ScFuncCallContext) -> MapClearCall { + let mut f = MapClearCall { + func: ScFunc::new(HSC_NAME, HFUNC_MAP_CLEAR), + params: MutableMapClearParams { id: 0 }, + }; + f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); + f + } + + pub fn map_create(_ctx: & dyn ScFuncCallContext) -> MapCreateCall { + let mut f = MapCreateCall { + func: ScFunc::new(HSC_NAME, HFUNC_MAP_CREATE), + params: MutableMapCreateParams { id: 0 }, + }; + f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); + f + } + + pub fn map_set(_ctx: & dyn ScFuncCallContext) -> MapSetCall { + let mut f = MapSetCall { + func: ScFunc::new(HSC_NAME, HFUNC_MAP_SET), + params: MutableMapSetParams { id: 0 }, + }; + f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); + f + } + pub fn param_types(_ctx: & dyn ScFuncCallContext) -> ParamTypesCall { let mut f = ParamTypesCall { func: ScFunc::new(HSC_NAME, HFUNC_PARAM_TYPES), @@ -119,6 +172,15 @@ impl ScFuncs { } } + pub fn trigger_event(_ctx: & dyn ScFuncCallContext) -> TriggerEventCall { + let mut f = TriggerEventCall { + func: ScFunc::new(HSC_NAME, HFUNC_TRIGGER_EVENT), + params: MutableTriggerEventParams { id: 0 }, + }; + f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); + f + } + pub fn array_length(_ctx: & dyn ScViewCallContext) -> ArrayLengthCall { let mut f = ArrayLengthCall { func: ScView::new(HSC_NAME, HVIEW_ARRAY_LENGTH), @@ -176,4 +238,14 @@ impl ScFuncs { f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } + + pub fn map_value(_ctx: & dyn ScViewCallContext) -> MapValueCall { + let mut f = MapValueCall { + func: ScView::new(HSC_NAME, HVIEW_MAP_VALUE), + params: MutableMapValueParams { id: 0 }, + results: ImmutableMapValueResults { id: 0 }, + }; + f.func.set_ptrs(&mut f.params.id, &mut f.results.id); + f + } } diff --git a/contracts/wasm/testwasmlib/src/events.rs b/contracts/wasm/testwasmlib/src/events.rs new file mode 100644 index 0000000000..c190ba68d1 --- /dev/null +++ b/contracts/wasm/testwasmlib/src/events.rs @@ -0,0 +1,23 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// (Re-)generated by schema tool +// >>>> DO NOT CHANGE THIS FILE! <<<< +// Change the json schema instead + +#![allow(dead_code)] + +use wasmlib::*; + +pub struct TestWasmLibEvents { +} + +impl TestWasmLibEvents { + + pub fn test(&self, address: &ScAddress, name: &str) { + let mut encoder = EventEncoder::new("testwasmlib.test"); + encoder.address(&address); + encoder.string(&name); + encoder.emit(); + } +} diff --git a/contracts/wasm/testwasmlib/src/keys.rs b/contracts/wasm/testwasmlib/src/keys.rs index f20b5ce4ed..7aeff86e99 100644 --- a/contracts/wasm/testwasmlib/src/keys.rs +++ b/contracts/wasm/testwasmlib/src/keys.rs @@ -25,28 +25,30 @@ pub(crate) const IDX_PARAM_INT16 : usize = 10; pub(crate) const IDX_PARAM_INT32 : usize = 11; pub(crate) const IDX_PARAM_INT64 : usize = 12; pub(crate) const IDX_PARAM_INT8 : usize = 13; -pub(crate) const IDX_PARAM_NAME : usize = 14; -pub(crate) const IDX_PARAM_PARAM : usize = 15; -pub(crate) const IDX_PARAM_RECORD_INDEX : usize = 16; -pub(crate) const IDX_PARAM_REQUEST_ID : usize = 17; -pub(crate) const IDX_PARAM_STRING : usize = 18; -pub(crate) const IDX_PARAM_UINT16 : usize = 19; -pub(crate) const IDX_PARAM_UINT32 : usize = 20; -pub(crate) const IDX_PARAM_UINT64 : usize = 21; -pub(crate) const IDX_PARAM_UINT8 : usize = 22; -pub(crate) const IDX_PARAM_VALUE : usize = 23; +pub(crate) const IDX_PARAM_KEY : usize = 14; +pub(crate) const IDX_PARAM_NAME : usize = 15; +pub(crate) const IDX_PARAM_PARAM : usize = 16; +pub(crate) const IDX_PARAM_RECORD_INDEX : usize = 17; +pub(crate) const IDX_PARAM_REQUEST_ID : usize = 18; +pub(crate) const IDX_PARAM_STRING : usize = 19; +pub(crate) const IDX_PARAM_UINT16 : usize = 20; +pub(crate) const IDX_PARAM_UINT32 : usize = 21; +pub(crate) const IDX_PARAM_UINT64 : usize = 22; +pub(crate) const IDX_PARAM_UINT8 : usize = 23; +pub(crate) const IDX_PARAM_VALUE : usize = 24; -pub(crate) const IDX_RESULT_COUNT : usize = 24; -pub(crate) const IDX_RESULT_IOTAS : usize = 25; -pub(crate) const IDX_RESULT_LENGTH : usize = 26; -pub(crate) const IDX_RESULT_RANDOM : usize = 27; -pub(crate) const IDX_RESULT_RECORD : usize = 28; -pub(crate) const IDX_RESULT_VALUE : usize = 29; +pub(crate) const IDX_RESULT_COUNT : usize = 25; +pub(crate) const IDX_RESULT_IOTAS : usize = 26; +pub(crate) const IDX_RESULT_LENGTH : usize = 27; +pub(crate) const IDX_RESULT_RANDOM : usize = 28; +pub(crate) const IDX_RESULT_RECORD : usize = 29; +pub(crate) const IDX_RESULT_VALUE : usize = 30; -pub(crate) const IDX_STATE_ARRAYS : usize = 30; -pub(crate) const IDX_STATE_RANDOM : usize = 31; +pub(crate) const IDX_STATE_ARRAYS : usize = 31; +pub(crate) const IDX_STATE_MAPS : usize = 32; +pub(crate) const IDX_STATE_RANDOM : usize = 33; -pub const KEY_MAP_LEN: usize = 32; +pub const KEY_MAP_LEN: usize = 34; pub const KEY_MAP: [&str; KEY_MAP_LEN] = [ PARAM_ADDRESS, @@ -63,6 +65,7 @@ pub const KEY_MAP: [&str; KEY_MAP_LEN] = [ PARAM_INT32, PARAM_INT64, PARAM_INT8, + PARAM_KEY, PARAM_NAME, PARAM_PARAM, PARAM_RECORD_INDEX, @@ -80,6 +83,7 @@ pub const KEY_MAP: [&str; KEY_MAP_LEN] = [ RESULT_RECORD, RESULT_VALUE, STATE_ARRAYS, + STATE_MAPS, STATE_RANDOM, ]; diff --git a/contracts/wasm/testwasmlib/src/lib.rs b/contracts/wasm/testwasmlib/src/lib.rs index f064f1deb6..b5f7cade6a 100644 --- a/contracts/wasm/testwasmlib/src/lib.rs +++ b/contracts/wasm/testwasmlib/src/lib.rs @@ -13,6 +13,7 @@ use wasmlib::*; use wasmlib::host::*; use crate::consts::*; +use crate::events::*; use crate::keys::*; use crate::params::*; use crate::results::*; @@ -20,6 +21,7 @@ use crate::state::*; mod consts; mod contract; +mod events; mod keys; mod params; mod results; @@ -33,14 +35,19 @@ fn on_load() { exports.add_func(FUNC_ARRAY_CLEAR, func_array_clear_thunk); exports.add_func(FUNC_ARRAY_CREATE, func_array_create_thunk); exports.add_func(FUNC_ARRAY_SET, func_array_set_thunk); + exports.add_func(FUNC_MAP_CLEAR, func_map_clear_thunk); + exports.add_func(FUNC_MAP_CREATE, func_map_create_thunk); + exports.add_func(FUNC_MAP_SET, func_map_set_thunk); exports.add_func(FUNC_PARAM_TYPES, func_param_types_thunk); exports.add_func(FUNC_RANDOM, func_random_thunk); + exports.add_func(FUNC_TRIGGER_EVENT, func_trigger_event_thunk); exports.add_view(VIEW_ARRAY_LENGTH, view_array_length_thunk); exports.add_view(VIEW_ARRAY_VALUE, view_array_value_thunk); exports.add_view(VIEW_BLOCK_RECORD, view_block_record_thunk); exports.add_view(VIEW_BLOCK_RECORDS, view_block_records_thunk); exports.add_view(VIEW_GET_RANDOM, view_get_random_thunk); exports.add_view(VIEW_IOTA_BALANCE, view_iota_balance_thunk); + exports.add_view(VIEW_MAP_VALUE, view_map_value_thunk); unsafe { for i in 0..KEY_MAP_LEN { @@ -50,6 +57,7 @@ fn on_load() { } pub struct ArrayClearContext { + events: TestWasmLibEvents, params: ImmutableArrayClearParams, state: MutableTestWasmLibState, } @@ -57,6 +65,7 @@ pub struct ArrayClearContext { fn func_array_clear_thunk(ctx: &ScFuncContext) { ctx.log("testwasmlib.funcArrayClear"); let f = ArrayClearContext { + events: TestWasmLibEvents {}, params: ImmutableArrayClearParams { id: OBJ_ID_PARAMS, }, @@ -70,6 +79,7 @@ fn func_array_clear_thunk(ctx: &ScFuncContext) { } pub struct ArrayCreateContext { + events: TestWasmLibEvents, params: ImmutableArrayCreateParams, state: MutableTestWasmLibState, } @@ -77,6 +87,7 @@ pub struct ArrayCreateContext { fn func_array_create_thunk(ctx: &ScFuncContext) { ctx.log("testwasmlib.funcArrayCreate"); let f = ArrayCreateContext { + events: TestWasmLibEvents {}, params: ImmutableArrayCreateParams { id: OBJ_ID_PARAMS, }, @@ -90,6 +101,7 @@ fn func_array_create_thunk(ctx: &ScFuncContext) { } pub struct ArraySetContext { + events: TestWasmLibEvents, params: ImmutableArraySetParams, state: MutableTestWasmLibState, } @@ -97,6 +109,7 @@ pub struct ArraySetContext { fn func_array_set_thunk(ctx: &ScFuncContext) { ctx.log("testwasmlib.funcArraySet"); let f = ArraySetContext { + events: TestWasmLibEvents {}, params: ImmutableArraySetParams { id: OBJ_ID_PARAMS, }, @@ -111,7 +124,76 @@ fn func_array_set_thunk(ctx: &ScFuncContext) { ctx.log("testwasmlib.funcArraySet ok"); } +pub struct MapClearContext { + events: TestWasmLibEvents, + params: ImmutableMapClearParams, + state: MutableTestWasmLibState, +} + +fn func_map_clear_thunk(ctx: &ScFuncContext) { + ctx.log("testwasmlib.funcMapClear"); + let f = MapClearContext { + events: TestWasmLibEvents {}, + params: ImmutableMapClearParams { + id: OBJ_ID_PARAMS, + }, + state: MutableTestWasmLibState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.name().exists(), "missing mandatory name"); + func_map_clear(ctx, &f); + ctx.log("testwasmlib.funcMapClear ok"); +} + +pub struct MapCreateContext { + events: TestWasmLibEvents, + params: ImmutableMapCreateParams, + state: MutableTestWasmLibState, +} + +fn func_map_create_thunk(ctx: &ScFuncContext) { + ctx.log("testwasmlib.funcMapCreate"); + let f = MapCreateContext { + events: TestWasmLibEvents {}, + params: ImmutableMapCreateParams { + id: OBJ_ID_PARAMS, + }, + state: MutableTestWasmLibState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.name().exists(), "missing mandatory name"); + func_map_create(ctx, &f); + ctx.log("testwasmlib.funcMapCreate ok"); +} + +pub struct MapSetContext { + events: TestWasmLibEvents, + params: ImmutableMapSetParams, + state: MutableTestWasmLibState, +} + +fn func_map_set_thunk(ctx: &ScFuncContext) { + ctx.log("testwasmlib.funcMapSet"); + let f = MapSetContext { + events: TestWasmLibEvents {}, + params: ImmutableMapSetParams { + id: OBJ_ID_PARAMS, + }, + state: MutableTestWasmLibState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.key().exists(), "missing mandatory key"); + ctx.require(f.params.name().exists(), "missing mandatory name"); + ctx.require(f.params.value().exists(), "missing mandatory value"); + func_map_set(ctx, &f); + ctx.log("testwasmlib.funcMapSet ok"); +} + pub struct ParamTypesContext { + events: TestWasmLibEvents, params: ImmutableParamTypesParams, state: MutableTestWasmLibState, } @@ -119,6 +201,7 @@ pub struct ParamTypesContext { fn func_param_types_thunk(ctx: &ScFuncContext) { ctx.log("testwasmlib.funcParamTypes"); let f = ParamTypesContext { + events: TestWasmLibEvents {}, params: ImmutableParamTypesParams { id: OBJ_ID_PARAMS, }, @@ -131,12 +214,14 @@ fn func_param_types_thunk(ctx: &ScFuncContext) { } pub struct RandomContext { + events: TestWasmLibEvents, state: MutableTestWasmLibState, } fn func_random_thunk(ctx: &ScFuncContext) { ctx.log("testwasmlib.funcRandom"); let f = RandomContext { + events: TestWasmLibEvents {}, state: MutableTestWasmLibState { id: OBJ_ID_STATE, }, @@ -145,6 +230,29 @@ fn func_random_thunk(ctx: &ScFuncContext) { ctx.log("testwasmlib.funcRandom ok"); } +pub struct TriggerEventContext { + events: TestWasmLibEvents, + params: ImmutableTriggerEventParams, + state: MutableTestWasmLibState, +} + +fn func_trigger_event_thunk(ctx: &ScFuncContext) { + ctx.log("testwasmlib.funcTriggerEvent"); + let f = TriggerEventContext { + events: TestWasmLibEvents {}, + params: ImmutableTriggerEventParams { + id: OBJ_ID_PARAMS, + }, + state: MutableTestWasmLibState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.address().exists(), "missing mandatory address"); + ctx.require(f.params.name().exists(), "missing mandatory name"); + func_trigger_event(ctx, &f); + ctx.log("testwasmlib.funcTriggerEvent ok"); +} + pub struct ArrayLengthContext { params: ImmutableArrayLengthParams, results: MutableArrayLengthResults, @@ -280,3 +388,28 @@ fn view_iota_balance_thunk(ctx: &ScViewContext) { view_iota_balance(ctx, &f); ctx.log("testwasmlib.viewIotaBalance ok"); } + +pub struct MapValueContext { + params: ImmutableMapValueParams, + results: MutableMapValueResults, + state: ImmutableTestWasmLibState, +} + +fn view_map_value_thunk(ctx: &ScViewContext) { + ctx.log("testwasmlib.viewMapValue"); + let f = MapValueContext { + params: ImmutableMapValueParams { + id: OBJ_ID_PARAMS, + }, + results: MutableMapValueResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableTestWasmLibState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.key().exists(), "missing mandatory key"); + ctx.require(f.params.name().exists(), "missing mandatory name"); + view_map_value(ctx, &f); + ctx.log("testwasmlib.viewMapValue ok"); +} diff --git a/contracts/wasm/testwasmlib/src/params.rs b/contracts/wasm/testwasmlib/src/params.rs index aaa1f6b8b4..1d9f4e9d87 100644 --- a/contracts/wasm/testwasmlib/src/params.rs +++ b/contracts/wasm/testwasmlib/src/params.rs @@ -22,7 +22,7 @@ pub struct ImmutableArrayClearParams { impl ImmutableArrayClearParams { pub fn name(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + ScImmutableString::new(self.id, PARAM_NAME.get_key_id()) } } @@ -33,7 +33,7 @@ pub struct MutableArrayClearParams { impl MutableArrayClearParams { pub fn name(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + ScMutableString::new(self.id, PARAM_NAME.get_key_id()) } } @@ -44,7 +44,7 @@ pub struct ImmutableArrayCreateParams { impl ImmutableArrayCreateParams { pub fn name(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + ScImmutableString::new(self.id, PARAM_NAME.get_key_id()) } } @@ -55,7 +55,7 @@ pub struct MutableArrayCreateParams { impl MutableArrayCreateParams { pub fn name(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + ScMutableString::new(self.id, PARAM_NAME.get_key_id()) } } @@ -66,15 +66,15 @@ pub struct ImmutableArraySetParams { impl ImmutableArraySetParams { pub fn index(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_PARAM_INDEX)) + ScImmutableInt32::new(self.id, PARAM_INDEX.get_key_id()) } pub fn name(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + ScImmutableString::new(self.id, PARAM_NAME.get_key_id()) } pub fn value(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_VALUE)) + ScImmutableString::new(self.id, PARAM_VALUE.get_key_id()) } } @@ -85,18 +85,101 @@ pub struct MutableArraySetParams { impl MutableArraySetParams { pub fn index(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_PARAM_INDEX)) + ScMutableInt32::new(self.id, PARAM_INDEX.get_key_id()) } pub fn name(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + ScMutableString::new(self.id, PARAM_NAME.get_key_id()) } pub fn value(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_VALUE)) + ScMutableString::new(self.id, PARAM_VALUE.get_key_id()) } } +#[derive(Clone, Copy)] +pub struct ImmutableMapClearParams { + pub(crate) id: i32, +} + +impl ImmutableMapClearParams { + pub fn name(&self) -> ScImmutableString { + ScImmutableString::new(self.id, PARAM_NAME.get_key_id()) + } +} + +#[derive(Clone, Copy)] +pub struct MutableMapClearParams { + pub(crate) id: i32, +} + +impl MutableMapClearParams { + pub fn name(&self) -> ScMutableString { + ScMutableString::new(self.id, PARAM_NAME.get_key_id()) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableMapCreateParams { + pub(crate) id: i32, +} + +impl ImmutableMapCreateParams { + pub fn name(&self) -> ScImmutableString { + ScImmutableString::new(self.id, PARAM_NAME.get_key_id()) + } +} + +#[derive(Clone, Copy)] +pub struct MutableMapCreateParams { + pub(crate) id: i32, +} + +impl MutableMapCreateParams { + pub fn name(&self) -> ScMutableString { + ScMutableString::new(self.id, PARAM_NAME.get_key_id()) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableMapSetParams { + pub(crate) id: i32, +} + +impl ImmutableMapSetParams { + pub fn key(&self) -> ScImmutableString { + ScImmutableString::new(self.id, PARAM_KEY.get_key_id()) + } + + pub fn name(&self) -> ScImmutableString { + ScImmutableString::new(self.id, PARAM_NAME.get_key_id()) + } + + pub fn value(&self) -> ScImmutableString { + ScImmutableString::new(self.id, PARAM_VALUE.get_key_id()) + } +} + +#[derive(Clone, Copy)] +pub struct MutableMapSetParams { + pub(crate) id: i32, +} + +impl MutableMapSetParams { + pub fn key(&self) -> ScMutableString { + ScMutableString::new(self.id, PARAM_KEY.get_key_id()) + } + + pub fn name(&self) -> ScMutableString { + ScMutableString::new(self.id, PARAM_NAME.get_key_id()) + } + + pub fn value(&self) -> ScMutableString { + ScMutableString::new(self.id, PARAM_VALUE.get_key_id()) + } +} + +#[derive(Clone, Copy)] pub struct MapStringToImmutableBytes { pub(crate) obj_id: i32, } @@ -114,51 +197,51 @@ pub struct ImmutableParamTypesParams { impl ImmutableParamTypesParams { pub fn address(&self) -> ScImmutableAddress { - ScImmutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) + ScImmutableAddress::new(self.id, PARAM_ADDRESS.get_key_id()) } pub fn agent_id(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_AGENT_ID)) + ScImmutableAgentID::new(self.id, PARAM_AGENT_ID.get_key_id()) } pub fn bool(&self) -> ScImmutableBool { - ScImmutableBool::new(self.id, idx_map(IDX_PARAM_BOOL)) + ScImmutableBool::new(self.id, PARAM_BOOL.get_key_id()) } pub fn bytes(&self) -> ScImmutableBytes { - ScImmutableBytes::new(self.id, idx_map(IDX_PARAM_BYTES)) + ScImmutableBytes::new(self.id, PARAM_BYTES.get_key_id()) } pub fn chain_id(&self) -> ScImmutableChainID { - ScImmutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) + ScImmutableChainID::new(self.id, PARAM_CHAIN_ID.get_key_id()) } pub fn color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + ScImmutableColor::new(self.id, PARAM_COLOR.get_key_id()) } pub fn hash(&self) -> ScImmutableHash { - ScImmutableHash::new(self.id, idx_map(IDX_PARAM_HASH)) + ScImmutableHash::new(self.id, PARAM_HASH.get_key_id()) } pub fn hname(&self) -> ScImmutableHname { - ScImmutableHname::new(self.id, idx_map(IDX_PARAM_HNAME)) + ScImmutableHname::new(self.id, PARAM_HNAME.get_key_id()) } pub fn int16(&self) -> ScImmutableInt16 { - ScImmutableInt16::new(self.id, idx_map(IDX_PARAM_INT16)) + ScImmutableInt16::new(self.id, PARAM_INT16.get_key_id()) } pub fn int32(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_PARAM_INT32)) + ScImmutableInt32::new(self.id, PARAM_INT32.get_key_id()) } pub fn int64(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_INT64)) + ScImmutableInt64::new(self.id, PARAM_INT64.get_key_id()) } pub fn int8(&self) -> ScImmutableInt8 { - ScImmutableInt8::new(self.id, idx_map(IDX_PARAM_INT8)) + ScImmutableInt8::new(self.id, PARAM_INT8.get_key_id()) } pub fn param(&self) -> MapStringToImmutableBytes { @@ -166,30 +249,31 @@ impl ImmutableParamTypesParams { } pub fn request_id(&self) -> ScImmutableRequestID { - ScImmutableRequestID::new(self.id, idx_map(IDX_PARAM_REQUEST_ID)) + ScImmutableRequestID::new(self.id, PARAM_REQUEST_ID.get_key_id()) } pub fn string(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_STRING)) + ScImmutableString::new(self.id, PARAM_STRING.get_key_id()) } pub fn uint16(&self) -> ScImmutableUint16 { - ScImmutableUint16::new(self.id, idx_map(IDX_PARAM_UINT16)) + ScImmutableUint16::new(self.id, PARAM_UINT16.get_key_id()) } pub fn uint32(&self) -> ScImmutableUint32 { - ScImmutableUint32::new(self.id, idx_map(IDX_PARAM_UINT32)) + ScImmutableUint32::new(self.id, PARAM_UINT32.get_key_id()) } pub fn uint64(&self) -> ScImmutableUint64 { - ScImmutableUint64::new(self.id, idx_map(IDX_PARAM_UINT64)) + ScImmutableUint64::new(self.id, PARAM_UINT64.get_key_id()) } pub fn uint8(&self) -> ScImmutableUint8 { - ScImmutableUint8::new(self.id, idx_map(IDX_PARAM_UINT8)) + ScImmutableUint8::new(self.id, PARAM_UINT8.get_key_id()) } } +#[derive(Clone, Copy)] pub struct MapStringToMutableBytes { pub(crate) obj_id: i32, } @@ -211,51 +295,51 @@ pub struct MutableParamTypesParams { impl MutableParamTypesParams { pub fn address(&self) -> ScMutableAddress { - ScMutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) + ScMutableAddress::new(self.id, PARAM_ADDRESS.get_key_id()) } pub fn agent_id(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_AGENT_ID)) + ScMutableAgentID::new(self.id, PARAM_AGENT_ID.get_key_id()) } pub fn bool(&self) -> ScMutableBool { - ScMutableBool::new(self.id, idx_map(IDX_PARAM_BOOL)) + ScMutableBool::new(self.id, PARAM_BOOL.get_key_id()) } pub fn bytes(&self) -> ScMutableBytes { - ScMutableBytes::new(self.id, idx_map(IDX_PARAM_BYTES)) + ScMutableBytes::new(self.id, PARAM_BYTES.get_key_id()) } pub fn chain_id(&self) -> ScMutableChainID { - ScMutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) + ScMutableChainID::new(self.id, PARAM_CHAIN_ID.get_key_id()) } pub fn color(&self) -> ScMutableColor { - ScMutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + ScMutableColor::new(self.id, PARAM_COLOR.get_key_id()) } pub fn hash(&self) -> ScMutableHash { - ScMutableHash::new(self.id, idx_map(IDX_PARAM_HASH)) + ScMutableHash::new(self.id, PARAM_HASH.get_key_id()) } pub fn hname(&self) -> ScMutableHname { - ScMutableHname::new(self.id, idx_map(IDX_PARAM_HNAME)) + ScMutableHname::new(self.id, PARAM_HNAME.get_key_id()) } pub fn int16(&self) -> ScMutableInt16 { - ScMutableInt16::new(self.id, idx_map(IDX_PARAM_INT16)) + ScMutableInt16::new(self.id, PARAM_INT16.get_key_id()) } pub fn int32(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_PARAM_INT32)) + ScMutableInt32::new(self.id, PARAM_INT32.get_key_id()) } pub fn int64(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_INT64)) + ScMutableInt64::new(self.id, PARAM_INT64.get_key_id()) } pub fn int8(&self) -> ScMutableInt8 { - ScMutableInt8::new(self.id, idx_map(IDX_PARAM_INT8)) + ScMutableInt8::new(self.id, PARAM_INT8.get_key_id()) } pub fn param(&self) -> MapStringToMutableBytes { @@ -263,27 +347,57 @@ impl MutableParamTypesParams { } pub fn request_id(&self) -> ScMutableRequestID { - ScMutableRequestID::new(self.id, idx_map(IDX_PARAM_REQUEST_ID)) + ScMutableRequestID::new(self.id, PARAM_REQUEST_ID.get_key_id()) } pub fn string(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_STRING)) + ScMutableString::new(self.id, PARAM_STRING.get_key_id()) } pub fn uint16(&self) -> ScMutableUint16 { - ScMutableUint16::new(self.id, idx_map(IDX_PARAM_UINT16)) + ScMutableUint16::new(self.id, PARAM_UINT16.get_key_id()) } pub fn uint32(&self) -> ScMutableUint32 { - ScMutableUint32::new(self.id, idx_map(IDX_PARAM_UINT32)) + ScMutableUint32::new(self.id, PARAM_UINT32.get_key_id()) } pub fn uint64(&self) -> ScMutableUint64 { - ScMutableUint64::new(self.id, idx_map(IDX_PARAM_UINT64)) + ScMutableUint64::new(self.id, PARAM_UINT64.get_key_id()) } pub fn uint8(&self) -> ScMutableUint8 { - ScMutableUint8::new(self.id, idx_map(IDX_PARAM_UINT8)) + ScMutableUint8::new(self.id, PARAM_UINT8.get_key_id()) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableTriggerEventParams { + pub(crate) id: i32, +} + +impl ImmutableTriggerEventParams { + pub fn address(&self) -> ScImmutableAddress { + ScImmutableAddress::new(self.id, PARAM_ADDRESS.get_key_id()) + } + + pub fn name(&self) -> ScImmutableString { + ScImmutableString::new(self.id, PARAM_NAME.get_key_id()) + } +} + +#[derive(Clone, Copy)] +pub struct MutableTriggerEventParams { + pub(crate) id: i32, +} + +impl MutableTriggerEventParams { + pub fn address(&self) -> ScMutableAddress { + ScMutableAddress::new(self.id, PARAM_ADDRESS.get_key_id()) + } + + pub fn name(&self) -> ScMutableString { + ScMutableString::new(self.id, PARAM_NAME.get_key_id()) } } @@ -294,7 +408,7 @@ pub struct ImmutableArrayLengthParams { impl ImmutableArrayLengthParams { pub fn name(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + ScImmutableString::new(self.id, PARAM_NAME.get_key_id()) } } @@ -305,7 +419,7 @@ pub struct MutableArrayLengthParams { impl MutableArrayLengthParams { pub fn name(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + ScMutableString::new(self.id, PARAM_NAME.get_key_id()) } } @@ -316,11 +430,11 @@ pub struct ImmutableArrayValueParams { impl ImmutableArrayValueParams { pub fn index(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_PARAM_INDEX)) + ScImmutableInt32::new(self.id, PARAM_INDEX.get_key_id()) } pub fn name(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + ScImmutableString::new(self.id, PARAM_NAME.get_key_id()) } } @@ -331,11 +445,11 @@ pub struct MutableArrayValueParams { impl MutableArrayValueParams { pub fn index(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_PARAM_INDEX)) + ScMutableInt32::new(self.id, PARAM_INDEX.get_key_id()) } pub fn name(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + ScMutableString::new(self.id, PARAM_NAME.get_key_id()) } } @@ -346,11 +460,11 @@ pub struct ImmutableBlockRecordParams { impl ImmutableBlockRecordParams { pub fn block_index(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_PARAM_BLOCK_INDEX)) + ScImmutableInt32::new(self.id, PARAM_BLOCK_INDEX.get_key_id()) } pub fn record_index(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_PARAM_RECORD_INDEX)) + ScImmutableInt32::new(self.id, PARAM_RECORD_INDEX.get_key_id()) } } @@ -361,11 +475,11 @@ pub struct MutableBlockRecordParams { impl MutableBlockRecordParams { pub fn block_index(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_PARAM_BLOCK_INDEX)) + ScMutableInt32::new(self.id, PARAM_BLOCK_INDEX.get_key_id()) } pub fn record_index(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_PARAM_RECORD_INDEX)) + ScMutableInt32::new(self.id, PARAM_RECORD_INDEX.get_key_id()) } } @@ -376,7 +490,7 @@ pub struct ImmutableBlockRecordsParams { impl ImmutableBlockRecordsParams { pub fn block_index(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_PARAM_BLOCK_INDEX)) + ScImmutableInt32::new(self.id, PARAM_BLOCK_INDEX.get_key_id()) } } @@ -387,6 +501,36 @@ pub struct MutableBlockRecordsParams { impl MutableBlockRecordsParams { pub fn block_index(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_PARAM_BLOCK_INDEX)) + ScMutableInt32::new(self.id, PARAM_BLOCK_INDEX.get_key_id()) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableMapValueParams { + pub(crate) id: i32, +} + +impl ImmutableMapValueParams { + pub fn key(&self) -> ScImmutableString { + ScImmutableString::new(self.id, PARAM_KEY.get_key_id()) + } + + pub fn name(&self) -> ScImmutableString { + ScImmutableString::new(self.id, PARAM_NAME.get_key_id()) + } +} + +#[derive(Clone, Copy)] +pub struct MutableMapValueParams { + pub(crate) id: i32, +} + +impl MutableMapValueParams { + pub fn key(&self) -> ScMutableString { + ScMutableString::new(self.id, PARAM_KEY.get_key_id()) + } + + pub fn name(&self) -> ScMutableString { + ScMutableString::new(self.id, PARAM_NAME.get_key_id()) } } diff --git a/contracts/wasm/testwasmlib/src/results.rs b/contracts/wasm/testwasmlib/src/results.rs index 528943d5aa..e46d27f60b 100644 --- a/contracts/wasm/testwasmlib/src/results.rs +++ b/contracts/wasm/testwasmlib/src/results.rs @@ -22,7 +22,7 @@ pub struct ImmutableArrayLengthResults { impl ImmutableArrayLengthResults { pub fn length(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_RESULT_LENGTH)) + ScImmutableInt32::new(self.id, RESULT_LENGTH.get_key_id()) } } @@ -33,7 +33,7 @@ pub struct MutableArrayLengthResults { impl MutableArrayLengthResults { pub fn length(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_RESULT_LENGTH)) + ScMutableInt32::new(self.id, RESULT_LENGTH.get_key_id()) } } @@ -44,7 +44,7 @@ pub struct ImmutableArrayValueResults { impl ImmutableArrayValueResults { pub fn value(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_RESULT_VALUE)) + ScImmutableString::new(self.id, RESULT_VALUE.get_key_id()) } } @@ -55,7 +55,7 @@ pub struct MutableArrayValueResults { impl MutableArrayValueResults { pub fn value(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_RESULT_VALUE)) + ScMutableString::new(self.id, RESULT_VALUE.get_key_id()) } } @@ -66,7 +66,7 @@ pub struct ImmutableBlockRecordResults { impl ImmutableBlockRecordResults { pub fn record(&self) -> ScImmutableBytes { - ScImmutableBytes::new(self.id, idx_map(IDX_RESULT_RECORD)) + ScImmutableBytes::new(self.id, RESULT_RECORD.get_key_id()) } } @@ -77,7 +77,7 @@ pub struct MutableBlockRecordResults { impl MutableBlockRecordResults { pub fn record(&self) -> ScMutableBytes { - ScMutableBytes::new(self.id, idx_map(IDX_RESULT_RECORD)) + ScMutableBytes::new(self.id, RESULT_RECORD.get_key_id()) } } @@ -88,7 +88,7 @@ pub struct ImmutableBlockRecordsResults { impl ImmutableBlockRecordsResults { pub fn count(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_RESULT_COUNT)) + ScImmutableInt32::new(self.id, RESULT_COUNT.get_key_id()) } } @@ -99,7 +99,7 @@ pub struct MutableBlockRecordsResults { impl MutableBlockRecordsResults { pub fn count(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_RESULT_COUNT)) + ScMutableInt32::new(self.id, RESULT_COUNT.get_key_id()) } } @@ -110,7 +110,7 @@ pub struct ImmutableGetRandomResults { impl ImmutableGetRandomResults { pub fn random(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_RANDOM)) + ScImmutableInt64::new(self.id, RESULT_RANDOM.get_key_id()) } } @@ -121,7 +121,7 @@ pub struct MutableGetRandomResults { impl MutableGetRandomResults { pub fn random(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_RANDOM)) + ScMutableInt64::new(self.id, RESULT_RANDOM.get_key_id()) } } @@ -132,7 +132,7 @@ pub struct ImmutableIotaBalanceResults { impl ImmutableIotaBalanceResults { pub fn iotas(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_IOTAS)) + ScImmutableInt64::new(self.id, RESULT_IOTAS.get_key_id()) } } @@ -143,6 +143,28 @@ pub struct MutableIotaBalanceResults { impl MutableIotaBalanceResults { pub fn iotas(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_IOTAS)) + ScMutableInt64::new(self.id, RESULT_IOTAS.get_key_id()) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableMapValueResults { + pub(crate) id: i32, +} + +impl ImmutableMapValueResults { + pub fn value(&self) -> ScImmutableString { + ScImmutableString::new(self.id, RESULT_VALUE.get_key_id()) + } +} + +#[derive(Clone, Copy)] +pub struct MutableMapValueResults { + pub(crate) id: i32, +} + +impl MutableMapValueResults { + pub fn value(&self) -> ScMutableString { + ScMutableString::new(self.id, RESULT_VALUE.get_key_id()) } } diff --git a/contracts/wasm/testwasmlib/src/state.rs b/contracts/wasm/testwasmlib/src/state.rs index e2dfc69350..01ceb24c3b 100644 --- a/contracts/wasm/testwasmlib/src/state.rs +++ b/contracts/wasm/testwasmlib/src/state.rs @@ -15,6 +15,7 @@ use crate::*; use crate::keys::*; use crate::typedefs::*; +#[derive(Clone, Copy)] pub struct MapStringToImmutableStringArray { pub(crate) obj_id: i32, } @@ -26,6 +27,18 @@ impl MapStringToImmutableStringArray { } } +#[derive(Clone, Copy)] +pub struct MapStringToImmutableStringMap { + pub(crate) obj_id: i32, +} + +impl MapStringToImmutableStringMap { + pub fn get_string_map(&self, key: &str) -> ImmutableStringMap { + let sub_id = get_object_id(self.obj_id, key.get_key_id(), TYPE_MAP); + ImmutableStringMap { obj_id: sub_id } + } +} + #[derive(Clone, Copy)] pub struct ImmutableTestWasmLibState { pub(crate) id: i32, @@ -33,15 +46,21 @@ pub struct ImmutableTestWasmLibState { impl ImmutableTestWasmLibState { pub fn arrays(&self) -> MapStringToImmutableStringArray { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_ARRAYS), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_ARRAYS.get_key_id(), TYPE_MAP); MapStringToImmutableStringArray { obj_id: map_id } } + pub fn maps(&self) -> MapStringToImmutableStringMap { + let map_id = get_object_id(self.id, STATE_MAPS.get_key_id(), TYPE_MAP); + MapStringToImmutableStringMap { obj_id: map_id } + } + pub fn random(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_STATE_RANDOM)) + ScImmutableInt64::new(self.id, STATE_RANDOM.get_key_id()) } } +#[derive(Clone, Copy)] pub struct MapStringToMutableStringArray { pub(crate) obj_id: i32, } @@ -57,18 +76,43 @@ impl MapStringToMutableStringArray { } } +#[derive(Clone, Copy)] +pub struct MapStringToMutableStringMap { + pub(crate) obj_id: i32, +} + +impl MapStringToMutableStringMap { + pub fn clear(&self) { + clear(self.obj_id); + } + + pub fn get_string_map(&self, key: &str) -> MutableStringMap { + let sub_id = get_object_id(self.obj_id, key.get_key_id(), TYPE_MAP); + MutableStringMap { obj_id: sub_id } + } +} + #[derive(Clone, Copy)] pub struct MutableTestWasmLibState { pub(crate) id: i32, } impl MutableTestWasmLibState { + pub fn as_immutable(&self) -> ImmutableTestWasmLibState { + ImmutableTestWasmLibState { id: self.id } + } + pub fn arrays(&self) -> MapStringToMutableStringArray { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_ARRAYS), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_ARRAYS.get_key_id(), TYPE_MAP); MapStringToMutableStringArray { obj_id: map_id } } + pub fn maps(&self) -> MapStringToMutableStringMap { + let map_id = get_object_id(self.id, STATE_MAPS.get_key_id(), TYPE_MAP); + MapStringToMutableStringMap { obj_id: map_id } + } + pub fn random(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_STATE_RANDOM)) + ScMutableInt64::new(self.id, STATE_RANDOM.get_key_id()) } } diff --git a/contracts/wasm/testwasmlib/src/structs.rs b/contracts/wasm/testwasmlib/src/structs.rs new file mode 100644 index 0000000000..9d670e8dee --- /dev/null +++ b/contracts/wasm/testwasmlib/src/structs.rs @@ -0,0 +1,73 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// (Re-)generated by schema tool +// >>>> DO NOT CHANGE THIS FILE! <<<< +// Change the json schema instead + +#![allow(dead_code)] +#![allow(unused_imports)] + +use wasmlib::*; +use wasmlib::host::*; +use crate::typedefs::*; + +pub struct Location { + pub x : i32, + pub y : i32, +} + +impl Location { + pub fn from_bytes(bytes: &[u8]) -> Location { + let mut decode = BytesDecoder::new(bytes); + Location { + x : decode.int32(), + y : decode.int32(), + } + } + + pub fn to_bytes(&self) -> Vec { + let mut encode = BytesEncoder::new(); + encode.int32(self.x); + encode.int32(self.y); + return encode.data(); + } +} + +pub struct ImmutableLocation { + pub(crate) obj_id: i32, + pub(crate) key_id: Key32, +} + +impl ImmutableLocation { + pub fn exists(&self) -> bool { + exists(self.obj_id, self.key_id, TYPE_BYTES) + } + + pub fn value(&self) -> Location { + Location::from_bytes(&get_bytes(self.obj_id, self.key_id, TYPE_BYTES)) + } +} + +pub struct MutableLocation { + pub(crate) obj_id: i32, + pub(crate) key_id: Key32, +} + +impl MutableLocation { + pub fn delete(&self) { + del_key(self.obj_id, self.key_id, TYPE_BYTES); + } + + pub fn exists(&self) -> bool { + exists(self.obj_id, self.key_id, TYPE_BYTES) + } + + pub fn set_value(&self, value: &Location) { + set_bytes(self.obj_id, self.key_id, TYPE_BYTES, &value.to_bytes()); + } + + pub fn value(&self) -> Location { + Location::from_bytes(&get_bytes(self.obj_id, self.key_id, TYPE_BYTES)) + } +} diff --git a/contracts/wasm/testwasmlib/src/testwasmlib.rs b/contracts/wasm/testwasmlib/src/testwasmlib.rs index ac32a8a541..31db1e8ab6 100644 --- a/contracts/wasm/testwasmlib/src/testwasmlib.rs +++ b/contracts/wasm/testwasmlib/src/testwasmlib.rs @@ -128,3 +128,19 @@ pub fn func_random(ctx: &ScFuncContext, f: &RandomContext) { pub fn view_get_random(_ctx: &ScViewContext, f: &GetRandomContext) { f.results.random().set_value(f.state.random().value()); } + +pub fn func_trigger_event(_ctx: &ScFuncContext, f: &TriggerEventContext) { + f.events.test(&f.params.address().value(), &f.params.name().value()); +} + +pub fn func_map_clear(_ctx: &ScFuncContext, _f: &MapClearContext) { +} + +pub fn func_map_create(_ctx: &ScFuncContext, _f: &MapCreateContext) { +} + +pub fn func_map_set(_ctx: &ScFuncContext, _f: &MapSetContext) { +} + +pub fn view_map_value(_ctx: &ScViewContext, _f: &MapValueContext) { +} diff --git a/contracts/wasm/testwasmlib/src/typedefs.rs b/contracts/wasm/testwasmlib/src/typedefs.rs index 7c8e0d9e73..7f96eb2368 100644 --- a/contracts/wasm/testwasmlib/src/typedefs.rs +++ b/contracts/wasm/testwasmlib/src/typedefs.rs @@ -10,6 +10,7 @@ use wasmlib::*; use wasmlib::host::*; +#[derive(Clone, Copy)] pub struct ArrayOfImmutableString { pub(crate) obj_id: i32, } @@ -26,6 +27,7 @@ impl ArrayOfImmutableString { pub type ImmutableStringArray = ArrayOfImmutableString; +#[derive(Clone, Copy)] pub struct ArrayOfMutableString { pub(crate) obj_id: i32, } @@ -45,3 +47,33 @@ impl ArrayOfMutableString { } pub type MutableStringArray = ArrayOfMutableString; + +#[derive(Clone, Copy)] +pub struct MapStringToImmutableString { + pub(crate) obj_id: i32, +} + +impl MapStringToImmutableString { + pub fn get_string(&self, key: &str) -> ScImmutableString { + ScImmutableString::new(self.obj_id, key.get_key_id()) + } +} + +pub type ImmutableStringMap = MapStringToImmutableString; + +#[derive(Clone, Copy)] +pub struct MapStringToMutableString { + pub(crate) obj_id: i32, +} + +impl MapStringToMutableString { + pub fn clear(&self) { + clear(self.obj_id); + } + + pub fn get_string(&self, key: &str) -> ScMutableString { + ScMutableString::new(self.obj_id, key.get_key_id()) + } +} + +pub type MutableStringMap = MapStringToMutableString; diff --git a/contracts/wasm/testwasmlib/test/testwasmlib_bg.wasm b/contracts/wasm/testwasmlib/test/testwasmlib_bg.wasm index ddfa98208d..39e10ae724 100644 Binary files a/contracts/wasm/testwasmlib/test/testwasmlib_bg.wasm and b/contracts/wasm/testwasmlib/test/testwasmlib_bg.wasm differ diff --git a/contracts/wasm/testwasmlib/test/testwasmlib_client_test.go b/contracts/wasm/testwasmlib/test/testwasmlib_client_test.go new file mode 100644 index 0000000000..f96da7f4b4 --- /dev/null +++ b/contracts/wasm/testwasmlib/test/testwasmlib_client_test.go @@ -0,0 +1,143 @@ +package test + +import ( + "fmt" + "testing" + + "github.com/iotaledger/wasp/contracts/wasm/testwasmlib/go/testwasmlibclient" + "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmclient" + coreaccountsclient "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmclient/coreaccounts" + "github.com/stretchr/testify/require" +) + +// hardcoded seed and chain ID, taken from wasp-cli.json +// note that normally the chain has already been set up and +// the contract has already been deployed in some way, so +// these values are usually available from elsewhere +const ( + myChainID = "tRA59jhoDG9QpXi7NcQ3phuQaaPqgXRBgXxK2Sy1FPGf" + mySeed = "6C6tRksZDWeDTCzX4Q7R2hbpyFV86cSGLVxdkFKSB3sv" +) + +func setupClient(t *testing.T) *testwasmlibclient.TestWasmLibService { + // for now skip client tests + t.SkipNow() + + require.True(t, wasmclient.SeedIsValid(mySeed)) + require.True(t, wasmclient.ChainIsValid(myChainID)) + + // we're testing against wasp-cluster, so defaults will do + svcClient := wasmclient.DefaultServiceClient() + + // create the service for the testwasmlib smart contract + svc, err := testwasmlibclient.NewTestWasmLibService(svcClient, myChainID) + require.NoError(t, err) + + // we'll use the first address in the seed to sign requests + svc.SignRequests(wasmclient.SeedToKeyPair(mySeed, 0)) + return svc +} + +func TestClientEvents(t *testing.T) { + svc := setupClient(t) + + // get new triggerEvent interface, pass params, and post the request + f := svc.TriggerEvent() + f.Name("Lala") + f.Address(wasmclient.SeedToAddress(mySeed, 0)) + req1 := f.Post() + require.NoError(t, req1.Error()) + + // err := svc.WaitRequest(req1) + // require.NoError(t, err) + + // get new triggerEvent interface, pass params, and post the request + f = svc.TriggerEvent() + f.Name("Trala") + f.Address(wasmclient.SeedToAddress(mySeed, 1)) + req2 := f.Post() + require.NoError(t, req2.Error()) + + err := svc.WaitRequest(req2) + require.NoError(t, err) +} + +func TestClientRandom(t *testing.T) { + svc := setupClient(t) + + // generate new random value + f := svc.Random() + req := f.Post() + require.NoError(t, req.Error()) + + err := svc.WaitRequest(req) + require.NoError(t, err) + + // get current random value + v := svc.GetRandom() + res := v.Call() + require.NoError(t, v.Error()) + require.GreaterOrEqual(t, res.Random(), int64(0)) + fmt.Println("Random: ", res.Random()) +} + +func TestClientArray(t *testing.T) { + svc := setupClient(t) + + v := svc.ArrayLength() + v.Name("Bands") + res := v.Call() + require.NoError(t, v.Error()) + require.EqualValues(t, 0, res.Length()) + + f := svc.ArraySet() + f.Name("Bands") + f.Index(0) + f.Value("Dire Straits") + req := f.Post() + require.NoError(t, req.Error()) + err := svc.WaitRequest(req) + require.NoError(t, err) + + v = svc.ArrayLength() + v.Name("Bands") + res = v.Call() + require.NoError(t, v.Error()) + require.EqualValues(t, 1, res.Length()) + + c := svc.ArrayClear() + c.Name("Bands") + req = c.Post() + require.NoError(t, req.Error()) + err = svc.WaitRequest(req) + require.NoError(t, err) + + v = svc.ArrayLength() + v.Name("Bands") + res = v.Call() + require.NoError(t, v.Error()) + require.EqualValues(t, 0, res.Length()) +} + +func TestAccountBalance(t *testing.T) { + // for now skip client tests + t.SkipNow() + + // we're testing against wasp-cluster, so defaults will do + svcClient := wasmclient.DefaultServiceClient() + + // create the service for the testwasmlib smart contract + svc, err := coreaccountsclient.NewCoreAccountsService(svcClient, myChainID) + require.NoError(t, err) + + // we'll use the first address in the seed to sign requests + svc.SignRequests(wasmclient.SeedToKeyPair(mySeed, 0)) + + bal := svc.Balance() + agendID := wasmclient.SeedToAgentID(mySeed, 0) + bal.AgentID(agendID) + res := bal.Call() + require.NoError(t, bal.Error()) + balances := res.Balances() + fmt.Printf("Balances: %v\n", balances) +} diff --git a/contracts/wasm/testwasmlib/test/testwasmlib_test.go b/contracts/wasm/testwasmlib/test/testwasmlib_test.go index 3cc625fccc..1fb5acb218 100644 --- a/contracts/wasm/testwasmlib/test/testwasmlib_test.go +++ b/contracts/wasm/testwasmlib/test/testwasmlib_test.go @@ -245,6 +245,56 @@ func TestClearArray(t *testing.T) { require.Error(t, ctx.Err) } +func TestClearMap(t *testing.T) { + // test reproduces a problem that needs fixing + t.SkipNow() + + *wasmsolo.GoDebug = true + ctx := setupTest(t) + + as := testwasmlib.ScFuncs.MapSet(ctx) + as.Params.Name().SetValue("albums") + as.Params.Key().SetValue("Simple Minds") + as.Params.Value().SetValue("New Gold Dream") + as.Func.TransferIotas(1).Post() + require.NoError(t, ctx.Err) + + as = testwasmlib.ScFuncs.MapSet(ctx) + as.Params.Name().SetValue("bands") + as.Params.Key().SetValue("Dire Straits") + as.Params.Value().SetValue("Calling Elvis") + as.Func.TransferIotas(1).Post() + require.NoError(t, ctx.Err) + + as = testwasmlib.ScFuncs.MapSet(ctx) + as.Params.Name().SetValue("bands") + as.Params.Key().SetValue("ELO") + as.Params.Value().SetValue("Mr. Blue Sky") + as.Func.TransferIotas(1).Post() + require.NoError(t, ctx.Err) + + av := testwasmlib.ScFuncs.MapValue(ctx) + av.Params.Name().SetValue("bands") + av.Params.Key().SetValue("Dire Straits") + av.Func.Call() + require.NoError(t, ctx.Err) + value := av.Results.Value() + require.True(t, value.Exists()) + require.EqualValues(t, "Calling Elvis", value.Value()) + + ac := testwasmlib.ScFuncs.ArrayClear(ctx) + ac.Params.Name().SetValue("bands") + ac.Func.TransferIotas(1).Post() + require.NoError(t, ctx.Err) + + av = testwasmlib.ScFuncs.MapValue(ctx) + av.Params.Name().SetValue("bands") + av.Params.Key().SetValue("Dire Straits") + av.Func.Call() + require.NoError(t, ctx.Err) + require.EqualValues(t, "", value.Value()) +} + func TestViewBalance(t *testing.T) { ctx := setupTest(t) diff --git a/contracts/wasm/testwasmlib/ts/testwasmlib/consts.ts b/contracts/wasm/testwasmlib/ts/testwasmlib/consts.ts index a6a3b0d49c..fbce884289 100644 --- a/contracts/wasm/testwasmlib/ts/testwasmlib/consts.ts +++ b/contracts/wasm/testwasmlib/ts/testwasmlib/consts.ts @@ -8,7 +8,7 @@ import * as wasmlib from "wasmlib"; export const ScName = "testwasmlib"; -export const ScDescription = "Exercise all aspects of WasmLib"; +export const ScDescription = "Exercise several aspects of WasmLib"; export const HScName = new wasmlib.ScHname(0x89703a45); export const ParamAddress = "address"; @@ -25,6 +25,7 @@ export const ParamInt16 = "int16"; export const ParamInt32 = "int32"; export const ParamInt64 = "int64"; export const ParamInt8 = "int8"; +export const ParamKey = "key"; export const ParamName = "name"; export const ParamParam = "this"; export const ParamRecordIndex = "recordIndex"; @@ -44,28 +45,39 @@ export const ResultRecord = "record"; export const ResultValue = "value"; export const StateArrays = "arrays"; +export const StateMaps = "maps"; export const StateRandom = "random"; export const FuncArrayClear = "arrayClear"; export const FuncArrayCreate = "arrayCreate"; export const FuncArraySet = "arraySet"; +export const FuncMapClear = "mapClear"; +export const FuncMapCreate = "mapCreate"; +export const FuncMapSet = "mapSet"; export const FuncParamTypes = "paramTypes"; export const FuncRandom = "random"; +export const FuncTriggerEvent = "triggerEvent"; export const ViewArrayLength = "arrayLength"; export const ViewArrayValue = "arrayValue"; export const ViewBlockRecord = "blockRecord"; export const ViewBlockRecords = "blockRecords"; export const ViewGetRandom = "getRandom"; export const ViewIotaBalance = "iotaBalance"; +export const ViewMapValue = "mapValue"; export const HFuncArrayClear = new wasmlib.ScHname(0x88021821); export const HFuncArrayCreate = new wasmlib.ScHname(0x1ed5b23b); export const HFuncArraySet = new wasmlib.ScHname(0x2c4150b3); +export const HFuncMapClear = new wasmlib.ScHname(0x027f215a); +export const HFuncMapCreate = new wasmlib.ScHname(0x6295d599); +export const HFuncMapSet = new wasmlib.ScHname(0xf2260404); export const HFuncParamTypes = new wasmlib.ScHname(0x6921c4cd); export const HFuncRandom = new wasmlib.ScHname(0xe86c97ca); +export const HFuncTriggerEvent = new wasmlib.ScHname(0xd5438ac6); export const HViewArrayLength = new wasmlib.ScHname(0x3a831021); export const HViewArrayValue = new wasmlib.ScHname(0x662dbd81); export const HViewBlockRecord = new wasmlib.ScHname(0xad13b2f8); export const HViewBlockRecords = new wasmlib.ScHname(0x16e249ea); export const HViewGetRandom = new wasmlib.ScHname(0x46263045); export const HViewIotaBalance = new wasmlib.ScHname(0x9d3920bd); +export const HViewMapValue = new wasmlib.ScHname(0x23149bef); diff --git a/contracts/wasm/testwasmlib/ts/testwasmlib/contract.ts b/contracts/wasm/testwasmlib/ts/testwasmlib/contract.ts index 7e24c61f0f..0b3ecd8c70 100644 --- a/contracts/wasm/testwasmlib/ts/testwasmlib/contract.ts +++ b/contracts/wasm/testwasmlib/ts/testwasmlib/contract.ts @@ -14,6 +14,7 @@ export class ArrayClearCall { } export class ArrayClearContext { + events: sc.TestWasmLibEvents = new sc.TestWasmLibEvents(); params: sc.ImmutableArrayClearParams = new sc.ImmutableArrayClearParams(); state: sc.MutableTestWasmLibState = new sc.MutableTestWasmLibState(); } @@ -24,6 +25,7 @@ export class ArrayCreateCall { } export class ArrayCreateContext { + events: sc.TestWasmLibEvents = new sc.TestWasmLibEvents(); params: sc.ImmutableArrayCreateParams = new sc.ImmutableArrayCreateParams(); state: sc.MutableTestWasmLibState = new sc.MutableTestWasmLibState(); } @@ -34,16 +36,51 @@ export class ArraySetCall { } export class ArraySetContext { + events: sc.TestWasmLibEvents = new sc.TestWasmLibEvents(); params: sc.ImmutableArraySetParams = new sc.ImmutableArraySetParams(); state: sc.MutableTestWasmLibState = new sc.MutableTestWasmLibState(); } +export class MapClearCall { + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncMapClear); + params: sc.MutableMapClearParams = new sc.MutableMapClearParams(); +} + +export class MapClearContext { + events: sc.TestWasmLibEvents = new sc.TestWasmLibEvents(); + params: sc.ImmutableMapClearParams = new sc.ImmutableMapClearParams(); + state: sc.MutableTestWasmLibState = new sc.MutableTestWasmLibState(); +} + +export class MapCreateCall { + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncMapCreate); + params: sc.MutableMapCreateParams = new sc.MutableMapCreateParams(); +} + +export class MapCreateContext { + events: sc.TestWasmLibEvents = new sc.TestWasmLibEvents(); + params: sc.ImmutableMapCreateParams = new sc.ImmutableMapCreateParams(); + state: sc.MutableTestWasmLibState = new sc.MutableTestWasmLibState(); +} + +export class MapSetCall { + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncMapSet); + params: sc.MutableMapSetParams = new sc.MutableMapSetParams(); +} + +export class MapSetContext { + events: sc.TestWasmLibEvents = new sc.TestWasmLibEvents(); + params: sc.ImmutableMapSetParams = new sc.ImmutableMapSetParams(); + state: sc.MutableTestWasmLibState = new sc.MutableTestWasmLibState(); +} + export class ParamTypesCall { func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncParamTypes); params: sc.MutableParamTypesParams = new sc.MutableParamTypesParams(); } export class ParamTypesContext { + events: sc.TestWasmLibEvents = new sc.TestWasmLibEvents(); params: sc.ImmutableParamTypesParams = new sc.ImmutableParamTypesParams(); state: sc.MutableTestWasmLibState = new sc.MutableTestWasmLibState(); } @@ -53,6 +90,18 @@ export class RandomCall { } export class RandomContext { + events: sc.TestWasmLibEvents = new sc.TestWasmLibEvents(); + state: sc.MutableTestWasmLibState = new sc.MutableTestWasmLibState(); +} + +export class TriggerEventCall { + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTriggerEvent); + params: sc.MutableTriggerEventParams = new sc.MutableTriggerEventParams(); +} + +export class TriggerEventContext { + events: sc.TestWasmLibEvents = new sc.TestWasmLibEvents(); + params: sc.ImmutableTriggerEventParams = new sc.ImmutableTriggerEventParams(); state: sc.MutableTestWasmLibState = new sc.MutableTestWasmLibState(); } @@ -124,6 +173,18 @@ export class IotaBalanceContext { state: sc.ImmutableTestWasmLibState = new sc.ImmutableTestWasmLibState(); } +export class MapValueCall { + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewMapValue); + params: sc.MutableMapValueParams = new sc.MutableMapValueParams(); + results: sc.ImmutableMapValueResults = new sc.ImmutableMapValueResults(); +} + +export class MapValueContext { + params: sc.ImmutableMapValueParams = new sc.ImmutableMapValueParams(); + results: sc.MutableMapValueResults = new sc.MutableMapValueResults(); + state: sc.ImmutableTestWasmLibState = new sc.ImmutableTestWasmLibState(); +} + export class ScFuncs { static arrayClear(ctx: wasmlib.ScFuncCallContext): ArrayClearCall { let f = new ArrayClearCall(); @@ -143,6 +204,24 @@ export class ScFuncs { return f; } + static mapClear(ctx: wasmlib.ScFuncCallContext): MapClearCall { + let f = new MapClearCall(); + f.func.setPtrs(f.params, null); + return f; + } + + static mapCreate(ctx: wasmlib.ScFuncCallContext): MapCreateCall { + let f = new MapCreateCall(); + f.func.setPtrs(f.params, null); + return f; + } + + static mapSet(ctx: wasmlib.ScFuncCallContext): MapSetCall { + let f = new MapSetCall(); + f.func.setPtrs(f.params, null); + return f; + } + static paramTypes(ctx: wasmlib.ScFuncCallContext): ParamTypesCall { let f = new ParamTypesCall(); f.func.setPtrs(f.params, null); @@ -153,6 +232,12 @@ export class ScFuncs { return new RandomCall(); } + static triggerEvent(ctx: wasmlib.ScFuncCallContext): TriggerEventCall { + let f = new TriggerEventCall(); + f.func.setPtrs(f.params, null); + return f; + } + static arrayLength(ctx: wasmlib.ScViewCallContext): ArrayLengthCall { let f = new ArrayLengthCall(); f.func.setPtrs(f.params, f.results); @@ -188,4 +273,10 @@ export class ScFuncs { f.func.setPtrs(null, f.results); return f; } + + static mapValue(ctx: wasmlib.ScViewCallContext): MapValueCall { + let f = new MapValueCall(); + f.func.setPtrs(f.params, f.results); + return f; + } } diff --git a/contracts/wasm/testwasmlib/ts/testwasmlib/events.ts b/contracts/wasm/testwasmlib/ts/testwasmlib/events.ts new file mode 100644 index 0000000000..8fd0c6416b --- /dev/null +++ b/contracts/wasm/testwasmlib/ts/testwasmlib/events.ts @@ -0,0 +1,18 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// (Re-)generated by schema tool +// >>>> DO NOT CHANGE THIS FILE! <<<< +// Change the json schema instead + +import * as wasmlib from "wasmlib"; + +export class TestWasmLibEvents { + + test(address: wasmlib.ScAddress, name: string): void { + new wasmlib.EventEncoder("testwasmlib.test"). + address(address). + string(name). + emit(); + } +} diff --git a/contracts/wasm/testwasmlib/ts/testwasmlib/index.ts b/contracts/wasm/testwasmlib/ts/testwasmlib/index.ts index 528a39b4da..502314c2d3 100644 --- a/contracts/wasm/testwasmlib/ts/testwasmlib/index.ts +++ b/contracts/wasm/testwasmlib/ts/testwasmlib/index.ts @@ -9,6 +9,7 @@ export * from "./testwasmlib"; export * from "./consts"; export * from "./contract"; +export * from "./events"; export * from "./keys"; export * from "./lib"; export * from "./params"; diff --git a/contracts/wasm/testwasmlib/ts/testwasmlib/keys.ts b/contracts/wasm/testwasmlib/ts/testwasmlib/keys.ts index a67473b453..92517c4880 100644 --- a/contracts/wasm/testwasmlib/ts/testwasmlib/keys.ts +++ b/contracts/wasm/testwasmlib/ts/testwasmlib/keys.ts @@ -22,26 +22,28 @@ export const IdxParamInt16 = 10; export const IdxParamInt32 = 11; export const IdxParamInt64 = 12; export const IdxParamInt8 = 13; -export const IdxParamName = 14; -export const IdxParamParam = 15; -export const IdxParamRecordIndex = 16; -export const IdxParamRequestID = 17; -export const IdxParamString = 18; -export const IdxParamUint16 = 19; -export const IdxParamUint32 = 20; -export const IdxParamUint64 = 21; -export const IdxParamUint8 = 22; -export const IdxParamValue = 23; +export const IdxParamKey = 14; +export const IdxParamName = 15; +export const IdxParamParam = 16; +export const IdxParamRecordIndex = 17; +export const IdxParamRequestID = 18; +export const IdxParamString = 19; +export const IdxParamUint16 = 20; +export const IdxParamUint32 = 21; +export const IdxParamUint64 = 22; +export const IdxParamUint8 = 23; +export const IdxParamValue = 24; -export const IdxResultCount = 24; -export const IdxResultIotas = 25; -export const IdxResultLength = 26; -export const IdxResultRandom = 27; -export const IdxResultRecord = 28; -export const IdxResultValue = 29; +export const IdxResultCount = 25; +export const IdxResultIotas = 26; +export const IdxResultLength = 27; +export const IdxResultRandom = 28; +export const IdxResultRecord = 29; +export const IdxResultValue = 30; -export const IdxStateArrays = 30; -export const IdxStateRandom = 31; +export const IdxStateArrays = 31; +export const IdxStateMaps = 32; +export const IdxStateRandom = 33; export let keyMap: string[] = [ sc.ParamAddress, @@ -58,6 +60,7 @@ export let keyMap: string[] = [ sc.ParamInt32, sc.ParamInt64, sc.ParamInt8, + sc.ParamKey, sc.ParamName, sc.ParamParam, sc.ParamRecordIndex, @@ -75,6 +78,7 @@ export let keyMap: string[] = [ sc.ResultRecord, sc.ResultValue, sc.StateArrays, + sc.StateMaps, sc.StateRandom, ]; diff --git a/contracts/wasm/testwasmlib/ts/testwasmlib/lib.ts b/contracts/wasm/testwasmlib/ts/testwasmlib/lib.ts index 6517abda64..10066f63d0 100644 --- a/contracts/wasm/testwasmlib/ts/testwasmlib/lib.ts +++ b/contracts/wasm/testwasmlib/ts/testwasmlib/lib.ts @@ -17,14 +17,19 @@ export function on_load(): void { exports.addFunc(sc.FuncArrayClear, funcArrayClearThunk); exports.addFunc(sc.FuncArrayCreate, funcArrayCreateThunk); exports.addFunc(sc.FuncArraySet, funcArraySetThunk); + exports.addFunc(sc.FuncMapClear, funcMapClearThunk); + exports.addFunc(sc.FuncMapCreate, funcMapCreateThunk); + exports.addFunc(sc.FuncMapSet, funcMapSetThunk); exports.addFunc(sc.FuncParamTypes, funcParamTypesThunk); exports.addFunc(sc.FuncRandom, funcRandomThunk); + exports.addFunc(sc.FuncTriggerEvent, funcTriggerEventThunk); exports.addView(sc.ViewArrayLength, viewArrayLengthThunk); exports.addView(sc.ViewArrayValue, viewArrayValueThunk); exports.addView(sc.ViewBlockRecord, viewBlockRecordThunk); exports.addView(sc.ViewBlockRecords, viewBlockRecordsThunk); exports.addView(sc.ViewGetRandom, viewGetRandomThunk); exports.addView(sc.ViewIotaBalance, viewIotaBalanceThunk); + exports.addView(sc.ViewMapValue, viewMapValueThunk); for (let i = 0; i < sc.keyMap.length; i++) { sc.idxMap[i] = wasmlib.Key32.fromString(sc.keyMap[i]); @@ -63,6 +68,38 @@ function funcArraySetThunk(ctx: wasmlib.ScFuncContext): void { ctx.log("testwasmlib.funcArraySet ok"); } +function funcMapClearThunk(ctx: wasmlib.ScFuncContext): void { + ctx.log("testwasmlib.funcMapClear"); + let f = new sc.MapClearContext(); + f.params.mapID = wasmlib.OBJ_ID_PARAMS; + f.state.mapID = wasmlib.OBJ_ID_STATE; + ctx.require(f.params.name().exists(), "missing mandatory name"); + sc.funcMapClear(ctx, f); + ctx.log("testwasmlib.funcMapClear ok"); +} + +function funcMapCreateThunk(ctx: wasmlib.ScFuncContext): void { + ctx.log("testwasmlib.funcMapCreate"); + let f = new sc.MapCreateContext(); + f.params.mapID = wasmlib.OBJ_ID_PARAMS; + f.state.mapID = wasmlib.OBJ_ID_STATE; + ctx.require(f.params.name().exists(), "missing mandatory name"); + sc.funcMapCreate(ctx, f); + ctx.log("testwasmlib.funcMapCreate ok"); +} + +function funcMapSetThunk(ctx: wasmlib.ScFuncContext): void { + ctx.log("testwasmlib.funcMapSet"); + let f = new sc.MapSetContext(); + f.params.mapID = wasmlib.OBJ_ID_PARAMS; + f.state.mapID = wasmlib.OBJ_ID_STATE; + ctx.require(f.params.key().exists(), "missing mandatory key"); + ctx.require(f.params.name().exists(), "missing mandatory name"); + ctx.require(f.params.value().exists(), "missing mandatory value"); + sc.funcMapSet(ctx, f); + ctx.log("testwasmlib.funcMapSet ok"); +} + function funcParamTypesThunk(ctx: wasmlib.ScFuncContext): void { ctx.log("testwasmlib.funcParamTypes"); let f = new sc.ParamTypesContext(); @@ -80,6 +117,17 @@ function funcRandomThunk(ctx: wasmlib.ScFuncContext): void { ctx.log("testwasmlib.funcRandom ok"); } +function funcTriggerEventThunk(ctx: wasmlib.ScFuncContext): void { + ctx.log("testwasmlib.funcTriggerEvent"); + let f = new sc.TriggerEventContext(); + f.params.mapID = wasmlib.OBJ_ID_PARAMS; + f.state.mapID = wasmlib.OBJ_ID_STATE; + ctx.require(f.params.address().exists(), "missing mandatory address"); + ctx.require(f.params.name().exists(), "missing mandatory name"); + sc.funcTriggerEvent(ctx, f); + ctx.log("testwasmlib.funcTriggerEvent ok"); +} + function viewArrayLengthThunk(ctx: wasmlib.ScViewContext): void { ctx.log("testwasmlib.viewArrayLength"); let f = new sc.ArrayLengthContext(); @@ -143,3 +191,15 @@ function viewIotaBalanceThunk(ctx: wasmlib.ScViewContext): void { sc.viewIotaBalance(ctx, f); ctx.log("testwasmlib.viewIotaBalance ok"); } + +function viewMapValueThunk(ctx: wasmlib.ScViewContext): void { + ctx.log("testwasmlib.viewMapValue"); + let f = new sc.MapValueContext(); + f.params.mapID = wasmlib.OBJ_ID_PARAMS; + f.results.mapID = wasmlib.OBJ_ID_RESULTS; + f.state.mapID = wasmlib.OBJ_ID_STATE; + ctx.require(f.params.key().exists(), "missing mandatory key"); + ctx.require(f.params.name().exists(), "missing mandatory name"); + sc.viewMapValue(ctx, f); + ctx.log("testwasmlib.viewMapValue ok"); +} diff --git a/contracts/wasm/testwasmlib/ts/testwasmlib/params.ts b/contracts/wasm/testwasmlib/ts/testwasmlib/params.ts index b4865a4e4e..cacc72ca4d 100644 --- a/contracts/wasm/testwasmlib/ts/testwasmlib/params.ts +++ b/contracts/wasm/testwasmlib/ts/testwasmlib/params.ts @@ -10,53 +10,105 @@ import * as sc from "./index"; export class ImmutableArrayClearParams extends wasmlib.ScMapID { name(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamName]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); } } export class MutableArrayClearParams extends wasmlib.ScMapID { name(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamName]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); } } export class ImmutableArrayCreateParams extends wasmlib.ScMapID { name(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamName]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); } } export class MutableArrayCreateParams extends wasmlib.ScMapID { name(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamName]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); } } export class ImmutableArraySetParams extends wasmlib.ScMapID { index(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxParamIndex]); + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamIndex)); } name(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamName]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); } value(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamValue]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamValue)); } } export class MutableArraySetParams extends wasmlib.ScMapID { index(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxParamIndex]); + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamIndex)); } name(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamName]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); } value(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamValue]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamValue)); + } +} + +export class ImmutableMapClearParams extends wasmlib.ScMapID { + name(): wasmlib.ScImmutableString { + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); + } +} + +export class MutableMapClearParams extends wasmlib.ScMapID { + name(): wasmlib.ScMutableString { + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); + } +} + +export class ImmutableMapCreateParams extends wasmlib.ScMapID { + name(): wasmlib.ScImmutableString { + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); + } +} + +export class MutableMapCreateParams extends wasmlib.ScMapID { + name(): wasmlib.ScMutableString { + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); + } +} + +export class ImmutableMapSetParams extends wasmlib.ScMapID { + key(): wasmlib.ScImmutableString { + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamKey)); + } + + name(): wasmlib.ScImmutableString { + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); + } + + value(): wasmlib.ScImmutableString { + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamValue)); + } +} + +export class MutableMapSetParams extends wasmlib.ScMapID { + key(): wasmlib.ScMutableString { + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamKey)); + } + + name(): wasmlib.ScMutableString { + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); + } + + value(): wasmlib.ScMutableString { + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamValue)); } } @@ -74,51 +126,51 @@ export class MapStringToImmutableBytes { export class ImmutableParamTypesParams extends wasmlib.ScMapID { address(): wasmlib.ScImmutableAddress { - return new wasmlib.ScImmutableAddress(this.mapID, sc.idxMap[sc.IdxParamAddress]); + return new wasmlib.ScImmutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamAddress)); } agentID(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAgentID]); + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAgentID)); } bool(): wasmlib.ScImmutableBool { - return new wasmlib.ScImmutableBool(this.mapID, sc.idxMap[sc.IdxParamBool]); + return new wasmlib.ScImmutableBool(this.mapID, wasmlib.Key32.fromString(sc.ParamBool)); } bytes(): wasmlib.ScImmutableBytes { - return new wasmlib.ScImmutableBytes(this.mapID, sc.idxMap[sc.IdxParamBytes]); + return new wasmlib.ScImmutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ParamBytes)); } chainID(): wasmlib.ScImmutableChainID { - return new wasmlib.ScImmutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); + return new wasmlib.ScImmutableChainID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainID)); } color(): wasmlib.ScImmutableColor { - return new wasmlib.ScImmutableColor(this.mapID, sc.idxMap[sc.IdxParamColor]); + return new wasmlib.ScImmutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamColor)); } hash(): wasmlib.ScImmutableHash { - return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamHash]); + return new wasmlib.ScImmutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamHash)); } hname(): wasmlib.ScImmutableHname { - return new wasmlib.ScImmutableHname(this.mapID, sc.idxMap[sc.IdxParamHname]); + return new wasmlib.ScImmutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHname)); } int16(): wasmlib.ScImmutableInt16 { - return new wasmlib.ScImmutableInt16(this.mapID, sc.idxMap[sc.IdxParamInt16]); + return new wasmlib.ScImmutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ParamInt16)); } int32(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxParamInt32]); + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamInt32)); } int64(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamInt64)); } int8(): wasmlib.ScImmutableInt8 { - return new wasmlib.ScImmutableInt8(this.mapID, sc.idxMap[sc.IdxParamInt8]); + return new wasmlib.ScImmutableInt8(this.mapID, wasmlib.Key32.fromString(sc.ParamInt8)); } param(): sc.MapStringToImmutableBytes { @@ -126,27 +178,27 @@ export class ImmutableParamTypesParams extends wasmlib.ScMapID { } requestID(): wasmlib.ScImmutableRequestID { - return new wasmlib.ScImmutableRequestID(this.mapID, sc.idxMap[sc.IdxParamRequestID]); + return new wasmlib.ScImmutableRequestID(this.mapID, wasmlib.Key32.fromString(sc.ParamRequestID)); } string(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamString]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamString)); } uint16(): wasmlib.ScImmutableUint16 { - return new wasmlib.ScImmutableUint16(this.mapID, sc.idxMap[sc.IdxParamUint16]); + return new wasmlib.ScImmutableUint16(this.mapID, wasmlib.Key32.fromString(sc.ParamUint16)); } uint32(): wasmlib.ScImmutableUint32 { - return new wasmlib.ScImmutableUint32(this.mapID, sc.idxMap[sc.IdxParamUint32]); + return new wasmlib.ScImmutableUint32(this.mapID, wasmlib.Key32.fromString(sc.ParamUint32)); } uint64(): wasmlib.ScImmutableUint64 { - return new wasmlib.ScImmutableUint64(this.mapID, sc.idxMap[sc.IdxParamUint64]); + return new wasmlib.ScImmutableUint64(this.mapID, wasmlib.Key32.fromString(sc.ParamUint64)); } uint8(): wasmlib.ScImmutableUint8 { - return new wasmlib.ScImmutableUint8(this.mapID, sc.idxMap[sc.IdxParamUint8]); + return new wasmlib.ScImmutableUint8(this.mapID, wasmlib.Key32.fromString(sc.ParamUint8)); } } @@ -168,51 +220,51 @@ export class MapStringToMutableBytes { export class MutableParamTypesParams extends wasmlib.ScMapID { address(): wasmlib.ScMutableAddress { - return new wasmlib.ScMutableAddress(this.mapID, sc.idxMap[sc.IdxParamAddress]); + return new wasmlib.ScMutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamAddress)); } agentID(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAgentID]); + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAgentID)); } bool(): wasmlib.ScMutableBool { - return new wasmlib.ScMutableBool(this.mapID, sc.idxMap[sc.IdxParamBool]); + return new wasmlib.ScMutableBool(this.mapID, wasmlib.Key32.fromString(sc.ParamBool)); } bytes(): wasmlib.ScMutableBytes { - return new wasmlib.ScMutableBytes(this.mapID, sc.idxMap[sc.IdxParamBytes]); + return new wasmlib.ScMutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ParamBytes)); } chainID(): wasmlib.ScMutableChainID { - return new wasmlib.ScMutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); + return new wasmlib.ScMutableChainID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainID)); } color(): wasmlib.ScMutableColor { - return new wasmlib.ScMutableColor(this.mapID, sc.idxMap[sc.IdxParamColor]); + return new wasmlib.ScMutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamColor)); } hash(): wasmlib.ScMutableHash { - return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamHash]); + return new wasmlib.ScMutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamHash)); } hname(): wasmlib.ScMutableHname { - return new wasmlib.ScMutableHname(this.mapID, sc.idxMap[sc.IdxParamHname]); + return new wasmlib.ScMutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHname)); } int16(): wasmlib.ScMutableInt16 { - return new wasmlib.ScMutableInt16(this.mapID, sc.idxMap[sc.IdxParamInt16]); + return new wasmlib.ScMutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ParamInt16)); } int32(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxParamInt32]); + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamInt32)); } int64(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamInt64)); } int8(): wasmlib.ScMutableInt8 { - return new wasmlib.ScMutableInt8(this.mapID, sc.idxMap[sc.IdxParamInt8]); + return new wasmlib.ScMutableInt8(this.mapID, wasmlib.Key32.fromString(sc.ParamInt8)); } param(): sc.MapStringToMutableBytes { @@ -220,90 +272,130 @@ export class MutableParamTypesParams extends wasmlib.ScMapID { } requestID(): wasmlib.ScMutableRequestID { - return new wasmlib.ScMutableRequestID(this.mapID, sc.idxMap[sc.IdxParamRequestID]); + return new wasmlib.ScMutableRequestID(this.mapID, wasmlib.Key32.fromString(sc.ParamRequestID)); } string(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamString]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamString)); } uint16(): wasmlib.ScMutableUint16 { - return new wasmlib.ScMutableUint16(this.mapID, sc.idxMap[sc.IdxParamUint16]); + return new wasmlib.ScMutableUint16(this.mapID, wasmlib.Key32.fromString(sc.ParamUint16)); } uint32(): wasmlib.ScMutableUint32 { - return new wasmlib.ScMutableUint32(this.mapID, sc.idxMap[sc.IdxParamUint32]); + return new wasmlib.ScMutableUint32(this.mapID, wasmlib.Key32.fromString(sc.ParamUint32)); } uint64(): wasmlib.ScMutableUint64 { - return new wasmlib.ScMutableUint64(this.mapID, sc.idxMap[sc.IdxParamUint64]); + return new wasmlib.ScMutableUint64(this.mapID, wasmlib.Key32.fromString(sc.ParamUint64)); } uint8(): wasmlib.ScMutableUint8 { - return new wasmlib.ScMutableUint8(this.mapID, sc.idxMap[sc.IdxParamUint8]); + return new wasmlib.ScMutableUint8(this.mapID, wasmlib.Key32.fromString(sc.ParamUint8)); + } +} + +export class ImmutableTriggerEventParams extends wasmlib.ScMapID { + address(): wasmlib.ScImmutableAddress { + return new wasmlib.ScImmutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamAddress)); + } + + name(): wasmlib.ScImmutableString { + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); + } +} + +export class MutableTriggerEventParams extends wasmlib.ScMapID { + address(): wasmlib.ScMutableAddress { + return new wasmlib.ScMutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamAddress)); + } + + name(): wasmlib.ScMutableString { + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); } } export class ImmutableArrayLengthParams extends wasmlib.ScMapID { name(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamName]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); } } export class MutableArrayLengthParams extends wasmlib.ScMapID { name(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamName]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); } } export class ImmutableArrayValueParams extends wasmlib.ScMapID { index(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxParamIndex]); + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamIndex)); } name(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamName]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); } } export class MutableArrayValueParams extends wasmlib.ScMapID { index(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxParamIndex]); + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamIndex)); } name(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamName]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); } } export class ImmutableBlockRecordParams extends wasmlib.ScMapID { blockIndex(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxParamBlockIndex]); + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamBlockIndex)); } recordIndex(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxParamRecordIndex]); + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamRecordIndex)); } } export class MutableBlockRecordParams extends wasmlib.ScMapID { blockIndex(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxParamBlockIndex]); + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamBlockIndex)); } recordIndex(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxParamRecordIndex]); + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamRecordIndex)); } } export class ImmutableBlockRecordsParams extends wasmlib.ScMapID { blockIndex(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxParamBlockIndex]); + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamBlockIndex)); } } export class MutableBlockRecordsParams extends wasmlib.ScMapID { blockIndex(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxParamBlockIndex]); + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamBlockIndex)); + } +} + +export class ImmutableMapValueParams extends wasmlib.ScMapID { + key(): wasmlib.ScImmutableString { + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamKey)); + } + + name(): wasmlib.ScImmutableString { + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); + } +} + +export class MutableMapValueParams extends wasmlib.ScMapID { + key(): wasmlib.ScMutableString { + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamKey)); + } + + name(): wasmlib.ScMutableString { + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); } } diff --git a/contracts/wasm/testwasmlib/ts/testwasmlib/results.ts b/contracts/wasm/testwasmlib/ts/testwasmlib/results.ts index 5c4de29bc1..476649ffcd 100644 --- a/contracts/wasm/testwasmlib/ts/testwasmlib/results.ts +++ b/contracts/wasm/testwasmlib/ts/testwasmlib/results.ts @@ -10,72 +10,84 @@ import * as sc from "./index"; export class ImmutableArrayLengthResults extends wasmlib.ScMapID { length(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxResultLength]); + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultLength)); } } export class MutableArrayLengthResults extends wasmlib.ScMapID { length(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxResultLength]); + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultLength)); } } export class ImmutableArrayValueResults extends wasmlib.ScMapID { value(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxResultValue]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultValue)); } } export class MutableArrayValueResults extends wasmlib.ScMapID { value(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxResultValue]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultValue)); } } export class ImmutableBlockRecordResults extends wasmlib.ScMapID { record(): wasmlib.ScImmutableBytes { - return new wasmlib.ScImmutableBytes(this.mapID, sc.idxMap[sc.IdxResultRecord]); + return new wasmlib.ScImmutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultRecord)); } } export class MutableBlockRecordResults extends wasmlib.ScMapID { record(): wasmlib.ScMutableBytes { - return new wasmlib.ScMutableBytes(this.mapID, sc.idxMap[sc.IdxResultRecord]); + return new wasmlib.ScMutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultRecord)); } } export class ImmutableBlockRecordsResults extends wasmlib.ScMapID { count(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxResultCount]); + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultCount)); } } export class MutableBlockRecordsResults extends wasmlib.ScMapID { count(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxResultCount]); + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultCount)); } } export class ImmutableGetRandomResults extends wasmlib.ScMapID { random(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultRandom]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultRandom)); } } export class MutableGetRandomResults extends wasmlib.ScMapID { random(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultRandom]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultRandom)); } } export class ImmutableIotaBalanceResults extends wasmlib.ScMapID { iotas(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultIotas]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultIotas)); } } export class MutableIotaBalanceResults extends wasmlib.ScMapID { iotas(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultIotas]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultIotas)); + } +} + +export class ImmutableMapValueResults extends wasmlib.ScMapID { + value(): wasmlib.ScImmutableString { + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultValue)); + } +} + +export class MutableMapValueResults extends wasmlib.ScMapID { + value(): wasmlib.ScMutableString { + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultValue)); } } diff --git a/contracts/wasm/testwasmlib/ts/testwasmlib/state.ts b/contracts/wasm/testwasmlib/ts/testwasmlib/state.ts index a823238696..bdc4b782a3 100644 --- a/contracts/wasm/testwasmlib/ts/testwasmlib/state.ts +++ b/contracts/wasm/testwasmlib/ts/testwasmlib/state.ts @@ -21,14 +21,32 @@ export class MapStringToImmutableStringArray { } } +export class MapStringToImmutableStringMap { + objID: i32; + + constructor(objID: i32) { + this.objID = objID; + } + + getStringMap(key: string): sc.ImmutableStringMap { + let subID = wasmlib.getObjectID(this.objID, wasmlib.Key32.fromString(key), wasmlib.TYPE_MAP); + return new sc.ImmutableStringMap(subID); + } +} + export class ImmutableTestWasmLibState extends wasmlib.ScMapID { arrays(): sc.MapStringToImmutableStringArray { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateArrays], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateArrays), wasmlib.TYPE_MAP); return new sc.MapStringToImmutableStringArray(mapID); } + maps(): sc.MapStringToImmutableStringMap { + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateMaps), wasmlib.TYPE_MAP); + return new sc.MapStringToImmutableStringMap(mapID); + } + random(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateRandom]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateRandom)); } } @@ -49,13 +67,41 @@ export class MapStringToMutableStringArray { } } +export class MapStringToMutableStringMap { + objID: i32; + + constructor(objID: i32) { + this.objID = objID; + } + + clear(): void { + wasmlib.clear(this.objID); + } + + getStringMap(key: string): sc.MutableStringMap { + let subID = wasmlib.getObjectID(this.objID, wasmlib.Key32.fromString(key), wasmlib.TYPE_MAP); + return new sc.MutableStringMap(subID); + } +} + export class MutableTestWasmLibState extends wasmlib.ScMapID { + asImmutable(): sc.ImmutableTestWasmLibState { + const imm = new sc.ImmutableTestWasmLibState(); + imm.mapID = this.mapID; + return imm; + } + arrays(): sc.MapStringToMutableStringArray { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateArrays], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateArrays), wasmlib.TYPE_MAP); return new sc.MapStringToMutableStringArray(mapID); } + maps(): sc.MapStringToMutableStringMap { + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateMaps), wasmlib.TYPE_MAP); + return new sc.MapStringToMutableStringMap(mapID); + } + random(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateRandom]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateRandom)); } } diff --git a/contracts/wasm/testwasmlib/ts/testwasmlib/structs.ts b/contracts/wasm/testwasmlib/ts/testwasmlib/structs.ts new file mode 100644 index 0000000000..943ee88121 --- /dev/null +++ b/contracts/wasm/testwasmlib/ts/testwasmlib/structs.ts @@ -0,0 +1,73 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// (Re-)generated by schema tool +// >>>> DO NOT CHANGE THIS FILE! <<<< +// Change the json schema instead + +import * as wasmlib from "wasmlib"; + +export class Location { + x : i32 = 0; + y : i32 = 0; + + static fromBytes(bytes: u8[]): Location { + let decode = new wasmlib.BytesDecoder(bytes); + let data = new Location(); + data.x = decode.int32(); + data.y = decode.int32(); + decode.close(); + return data; + } + + bytes(): u8[] { + return new wasmlib.BytesEncoder(). + int32(this.x). + int32(this.y). + data(); + } +} + +export class ImmutableLocation { + objID: i32; + keyID: wasmlib.Key32; + + constructor(objID: i32, keyID: wasmlib.Key32) { + this.objID = objID; + this.keyID = keyID; + } + + exists(): boolean { + return wasmlib.exists(this.objID, this.keyID, wasmlib.TYPE_BYTES); + } + + value(): Location { + return Location.fromBytes(wasmlib.getBytes(this.objID, this.keyID, wasmlib.TYPE_BYTES)); + } +} + +export class MutableLocation { + objID: i32; + keyID: wasmlib.Key32; + + constructor(objID: i32, keyID: wasmlib.Key32) { + this.objID = objID; + this.keyID = keyID; + } + + delete(): void { + wasmlib.delKey(this.objID, this.keyID, wasmlib.TYPE_BYTES); + } + + exists(): boolean { + return wasmlib.exists(this.objID, this.keyID, wasmlib.TYPE_BYTES); + } + + setValue(value: Location): void { + wasmlib.setBytes(this.objID, this.keyID, wasmlib.TYPE_BYTES, value.bytes()); + } + + value(): Location { + return Location.fromBytes(wasmlib.getBytes(this.objID, this.keyID, wasmlib.TYPE_BYTES)); + } +} diff --git a/contracts/wasm/testwasmlib/ts/testwasmlib/testwasmlib.ts b/contracts/wasm/testwasmlib/ts/testwasmlib/testwasmlib.ts index 1bfc31f7bd..c92f97dba5 100644 --- a/contracts/wasm/testwasmlib/ts/testwasmlib/testwasmlib.ts +++ b/contracts/wasm/testwasmlib/ts/testwasmlib/testwasmlib.ts @@ -128,3 +128,19 @@ export function funcRandom(ctx: wasmlib.ScFuncContext, f: sc.RandomContext): voi export function viewGetRandom(ctx: wasmlib.ScViewContext, f: sc.GetRandomContext): void { f.results.random().setValue(f.state.random().value()); } + +export function funcTriggerEvent(ctx: wasmlib.ScFuncContext, f: sc.TriggerEventContext): void { + f.events.test(f.params.address().value(), f.params.name().value()); +} + +export function funcMapClear(ctx: wasmlib.ScFuncContext, f: sc.MapClearContext): void { +} + +export function funcMapCreate(ctx: wasmlib.ScFuncContext, f: sc.MapCreateContext): void { +} + +export function funcMapSet(ctx: wasmlib.ScFuncContext, f: sc.MapSetContext): void { +} + +export function viewMapValue(ctx: wasmlib.ScViewContext, f: sc.MapValueContext): void { +} diff --git a/contracts/wasm/testwasmlib/ts/testwasmlib/typedefs.ts b/contracts/wasm/testwasmlib/ts/testwasmlib/typedefs.ts index aab311ce94..a38bec20bd 100644 --- a/contracts/wasm/testwasmlib/ts/testwasmlib/typedefs.ts +++ b/contracts/wasm/testwasmlib/ts/testwasmlib/typedefs.ts @@ -49,3 +49,37 @@ export class ArrayOfMutableString { export class MutableStringArray extends ArrayOfMutableString { }; + +export class MapStringToImmutableString { + objID: i32; + + constructor(objID: i32) { + this.objID = objID; + } + + getString(key: string): wasmlib.ScImmutableString { + return new wasmlib.ScImmutableString(this.objID, wasmlib.Key32.fromString(key)); + } +} + +export class ImmutableStringMap extends MapStringToImmutableString { +}; + +export class MapStringToMutableString { + objID: i32; + + constructor(objID: i32) { + this.objID = objID; + } + + clear(): void { + wasmlib.clear(this.objID); + } + + getString(key: string): wasmlib.ScMutableString { + return new wasmlib.ScMutableString(this.objID, wasmlib.Key32.fromString(key)); + } +} + +export class MutableStringMap extends MapStringToMutableString { +}; diff --git a/contracts/wasm/testwasmlib/ts/testwasmlibclient/events.ts b/contracts/wasm/testwasmlib/ts/testwasmlibclient/events.ts new file mode 100644 index 0000000000..6d066c0cf0 --- /dev/null +++ b/contracts/wasm/testwasmlib/ts/testwasmlibclient/events.ts @@ -0,0 +1,24 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// (Re-)generated by schema tool +// >>>> DO NOT CHANGE THIS FILE! <<<< +// Change the json schema instead + +import * as wasmclient from "wasmclient" +import * as app from "./testwasmlib" + +export const eventHandlers: wasmclient.EventHandlers = new Map([ + ["testwasmlib.test", (msg: string[]) => app.onTestWasmLibTest(new EventTest(msg))], +]); + +export class EventTest extends wasmclient.Event { + public readonly address: wasmclient.Address; + public readonly name: wasmclient.String; + + public constructor(msg: string[]) { + super(msg) + this.address = this.nextAddress(); + this.name = this.nextString(); + } +} diff --git a/contracts/wasm/testwasmlib/ts/testwasmlibclient/index.ts b/contracts/wasm/testwasmlib/ts/testwasmlibclient/index.ts new file mode 100644 index 0000000000..f3eff69c33 --- /dev/null +++ b/contracts/wasm/testwasmlib/ts/testwasmlibclient/index.ts @@ -0,0 +1,10 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// (Re-)generated by schema tool +// >>>> DO NOT CHANGE THIS FILE! <<<< +// Change the json schema instead + +export * from "./testwasmlib"; +export * from "./events"; +export * from "./service"; diff --git a/contracts/wasm/testwasmlib/ts/testwasmlibclient/service.ts b/contracts/wasm/testwasmlib/ts/testwasmlibclient/service.ts new file mode 100644 index 0000000000..f738825fd4 --- /dev/null +++ b/contracts/wasm/testwasmlib/ts/testwasmlibclient/service.ts @@ -0,0 +1,511 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// (Re-)generated by schema tool +// >>>> DO NOT CHANGE THIS FILE! <<<< +// Change the json schema instead + +import * as wasmclient from "wasmclient" +import * as events from "./events" + +const ArgAddress = "address"; +const ArgAgentID = "agentID"; +const ArgBlockIndex = "blockIndex"; +const ArgBool = "bool"; +const ArgBytes = "bytes"; +const ArgChainID = "chainID"; +const ArgColor = "color"; +const ArgHash = "hash"; +const ArgHname = "hname"; +const ArgIndex = "index"; +const ArgInt16 = "int16"; +const ArgInt32 = "int32"; +const ArgInt64 = "int64"; +const ArgInt8 = "int8"; +const ArgKey = "key"; +const ArgName = "name"; +const ArgParam = "this"; +const ArgRecordIndex = "recordIndex"; +const ArgRequestID = "requestID"; +const ArgString = "string"; +const ArgUint16 = "uint16"; +const ArgUint32 = "uint32"; +const ArgUint64 = "uint64"; +const ArgUint8 = "uint8"; +const ArgValue = "value"; + +const ResCount = "count"; +const ResIotas = "iotas"; +const ResLength = "length"; +const ResRandom = "random"; +const ResRecord = "record"; +const ResValue = "value"; + +///////////////////////////// arrayClear ///////////////////////////// + +export class ArrayClearFunc extends wasmclient.ClientFunc { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public name(v: string): void { + this.args.set(ArgName, this.args.fromString(v)); + } + + public async post(): Promise { + this.args.mandatory(ArgName); + return await super.post(0x88021821, this.args); + } +} + +///////////////////////////// arrayCreate ///////////////////////////// + +export class ArrayCreateFunc extends wasmclient.ClientFunc { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public name(v: string): void { + this.args.set(ArgName, this.args.fromString(v)); + } + + public async post(): Promise { + this.args.mandatory(ArgName); + return await super.post(0x1ed5b23b, this.args); + } +} + +///////////////////////////// arraySet ///////////////////////////// + +export class ArraySetFunc extends wasmclient.ClientFunc { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public index(v: wasmclient.Int32): void { + this.args.set(ArgIndex, this.args.fromInt32(v)); + } + + public name(v: string): void { + this.args.set(ArgName, this.args.fromString(v)); + } + + public value(v: string): void { + this.args.set(ArgValue, this.args.fromString(v)); + } + + public async post(): Promise { + this.args.mandatory(ArgIndex); + this.args.mandatory(ArgName); + this.args.mandatory(ArgValue); + return await super.post(0x2c4150b3, this.args); + } +} + +///////////////////////////// mapClear ///////////////////////////// + +export class MapClearFunc extends wasmclient.ClientFunc { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public name(v: string): void { + this.args.set(ArgName, this.args.fromString(v)); + } + + public async post(): Promise { + this.args.mandatory(ArgName); + return await super.post(0x027f215a, this.args); + } +} + +///////////////////////////// mapCreate ///////////////////////////// + +export class MapCreateFunc extends wasmclient.ClientFunc { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public name(v: string): void { + this.args.set(ArgName, this.args.fromString(v)); + } + + public async post(): Promise { + this.args.mandatory(ArgName); + return await super.post(0x6295d599, this.args); + } +} + +///////////////////////////// mapSet ///////////////////////////// + +export class MapSetFunc extends wasmclient.ClientFunc { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public key(v: string): void { + this.args.set(ArgKey, this.args.fromString(v)); + } + + public name(v: string): void { + this.args.set(ArgName, this.args.fromString(v)); + } + + public value(v: string): void { + this.args.set(ArgValue, this.args.fromString(v)); + } + + public async post(): Promise { + this.args.mandatory(ArgKey); + this.args.mandatory(ArgName); + this.args.mandatory(ArgValue); + return await super.post(0xf2260404, this.args); + } +} + +///////////////////////////// paramTypes ///////////////////////////// + +export class ParamTypesFunc extends wasmclient.ClientFunc { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public address(v: wasmclient.Address): void { + this.args.set(ArgAddress, this.args.fromAddress(v)); + } + + public agentID(v: wasmclient.AgentID): void { + this.args.set(ArgAgentID, this.args.fromAgentID(v)); + } + + public bool(v: boolean): void { + this.args.set(ArgBool, this.args.fromBool(v)); + } + + public bytes(v: wasmclient.Bytes): void { + this.args.set(ArgBytes, this.args.fromBytes(v)); + } + + public chainID(v: wasmclient.ChainID): void { + this.args.set(ArgChainID, this.args.fromChainID(v)); + } + + public color(v: wasmclient.Color): void { + this.args.set(ArgColor, this.args.fromColor(v)); + } + + public hash(v: wasmclient.Hash): void { + this.args.set(ArgHash, this.args.fromHash(v)); + } + + public hname(v: wasmclient.Hname): void { + this.args.set(ArgHname, this.args.fromHname(v)); + } + + public int16(v: wasmclient.Int16): void { + this.args.set(ArgInt16, this.args.fromInt16(v)); + } + + public int32(v: wasmclient.Int32): void { + this.args.set(ArgInt32, this.args.fromInt32(v)); + } + + public int64(v: wasmclient.Int64): void { + this.args.set(ArgInt64, this.args.fromInt64(v)); + } + + public int8(v: wasmclient.Int8): void { + this.args.set(ArgInt8, this.args.fromInt8(v)); + } + + public param(v: wasmclient.Bytes): void { + this.args.set(ArgParam, this.args.fromBytes(v)); + } + + public requestID(v: wasmclient.RequestID): void { + this.args.set(ArgRequestID, this.args.fromRequestID(v)); + } + + public string(v: string): void { + this.args.set(ArgString, this.args.fromString(v)); + } + + public uint16(v: wasmclient.Uint16): void { + this.args.set(ArgUint16, this.args.fromUint16(v)); + } + + public uint32(v: wasmclient.Uint32): void { + this.args.set(ArgUint32, this.args.fromUint32(v)); + } + + public uint64(v: wasmclient.Uint64): void { + this.args.set(ArgUint64, this.args.fromUint64(v)); + } + + public uint8(v: wasmclient.Uint8): void { + this.args.set(ArgUint8, this.args.fromUint8(v)); + } + + public async post(): Promise { + return await super.post(0x6921c4cd, this.args); + } +} + +///////////////////////////// random ///////////////////////////// + +export class RandomFunc extends wasmclient.ClientFunc { + + public async post(): Promise { + return await super.post(0xe86c97ca, null); + } +} + +///////////////////////////// triggerEvent ///////////////////////////// + +export class TriggerEventFunc extends wasmclient.ClientFunc { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public address(v: wasmclient.Address): void { + this.args.set(ArgAddress, this.args.fromAddress(v)); + } + + public name(v: string): void { + this.args.set(ArgName, this.args.fromString(v)); + } + + public async post(): Promise { + this.args.mandatory(ArgAddress); + this.args.mandatory(ArgName); + return await super.post(0xd5438ac6, this.args); + } +} + +///////////////////////////// arrayLength ///////////////////////////// + +export class ArrayLengthView extends wasmclient.ClientView { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public name(v: string): void { + this.args.set(ArgName, this.args.fromString(v)); + } + + public async call(): Promise { + this.args.mandatory(ArgName); + const res = new ArrayLengthResults(); + await this.callView("arrayLength", this.args, res); + return res; + } +} + +export class ArrayLengthResults extends wasmclient.Results { + + length(): wasmclient.Int32 { + return this.toInt32(this.get(ResLength)); + } +} + +///////////////////////////// arrayValue ///////////////////////////// + +export class ArrayValueView extends wasmclient.ClientView { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public index(v: wasmclient.Int32): void { + this.args.set(ArgIndex, this.args.fromInt32(v)); + } + + public name(v: string): void { + this.args.set(ArgName, this.args.fromString(v)); + } + + public async call(): Promise { + this.args.mandatory(ArgIndex); + this.args.mandatory(ArgName); + const res = new ArrayValueResults(); + await this.callView("arrayValue", this.args, res); + return res; + } +} + +export class ArrayValueResults extends wasmclient.Results { + + value(): string { + return this.toString(this.get(ResValue)); + } +} + +///////////////////////////// blockRecord ///////////////////////////// + +export class BlockRecordView extends wasmclient.ClientView { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public blockIndex(v: wasmclient.Int32): void { + this.args.set(ArgBlockIndex, this.args.fromInt32(v)); + } + + public recordIndex(v: wasmclient.Int32): void { + this.args.set(ArgRecordIndex, this.args.fromInt32(v)); + } + + public async call(): Promise { + this.args.mandatory(ArgBlockIndex); + this.args.mandatory(ArgRecordIndex); + const res = new BlockRecordResults(); + await this.callView("blockRecord", this.args, res); + return res; + } +} + +export class BlockRecordResults extends wasmclient.Results { + + record(): wasmclient.Bytes { + return this.toBytes(this.get(ResRecord)); + } +} + +///////////////////////////// blockRecords ///////////////////////////// + +export class BlockRecordsView extends wasmclient.ClientView { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public blockIndex(v: wasmclient.Int32): void { + this.args.set(ArgBlockIndex, this.args.fromInt32(v)); + } + + public async call(): Promise { + this.args.mandatory(ArgBlockIndex); + const res = new BlockRecordsResults(); + await this.callView("blockRecords", this.args, res); + return res; + } +} + +export class BlockRecordsResults extends wasmclient.Results { + + count(): wasmclient.Int32 { + return this.toInt32(this.get(ResCount)); + } +} + +///////////////////////////// getRandom ///////////////////////////// + +export class GetRandomView extends wasmclient.ClientView { + + public async call(): Promise { + const res = new GetRandomResults(); + await this.callView("getRandom", null, res); + return res; + } +} + +export class GetRandomResults extends wasmclient.Results { + + random(): wasmclient.Int64 { + return this.toInt64(this.get(ResRandom)); + } +} + +///////////////////////////// iotaBalance ///////////////////////////// + +export class IotaBalanceView extends wasmclient.ClientView { + + public async call(): Promise { + const res = new IotaBalanceResults(); + await this.callView("iotaBalance", null, res); + return res; + } +} + +export class IotaBalanceResults extends wasmclient.Results { + + iotas(): wasmclient.Int64 { + return this.toInt64(this.get(ResIotas)); + } +} + +///////////////////////////// mapValue ///////////////////////////// + +export class MapValueView extends wasmclient.ClientView { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public key(v: string): void { + this.args.set(ArgKey, this.args.fromString(v)); + } + + public name(v: string): void { + this.args.set(ArgName, this.args.fromString(v)); + } + + public async call(): Promise { + this.args.mandatory(ArgKey); + this.args.mandatory(ArgName); + const res = new MapValueResults(); + await this.callView("mapValue", this.args, res); + return res; + } +} + +export class MapValueResults extends wasmclient.Results { + + value(): string { + return this.toString(this.get(ResValue)); + } +} + +///////////////////////////// TestWasmLibService ///////////////////////////// + +export class TestWasmLibService extends wasmclient.Service { + + public constructor(cl: wasmclient.ServiceClient) { + super(cl, 0x89703a45, events.eventHandlers); + } + + public arrayClear(): ArrayClearFunc { + return new ArrayClearFunc(this); + } + + public arrayCreate(): ArrayCreateFunc { + return new ArrayCreateFunc(this); + } + + public arraySet(): ArraySetFunc { + return new ArraySetFunc(this); + } + + public mapClear(): MapClearFunc { + return new MapClearFunc(this); + } + + public mapCreate(): MapCreateFunc { + return new MapCreateFunc(this); + } + + public mapSet(): MapSetFunc { + return new MapSetFunc(this); + } + + public paramTypes(): ParamTypesFunc { + return new ParamTypesFunc(this); + } + + public random(): RandomFunc { + return new RandomFunc(this); + } + + public triggerEvent(): TriggerEventFunc { + return new TriggerEventFunc(this); + } + + public arrayLength(): ArrayLengthView { + return new ArrayLengthView(this); + } + + public arrayValue(): ArrayValueView { + return new ArrayValueView(this); + } + + public blockRecord(): BlockRecordView { + return new BlockRecordView(this); + } + + public blockRecords(): BlockRecordsView { + return new BlockRecordsView(this); + } + + public getRandom(): GetRandomView { + return new GetRandomView(this); + } + + public iotaBalance(): IotaBalanceView { + return new IotaBalanceView(this); + } + + public mapValue(): MapValueView { + return new MapValueView(this); + } +} diff --git a/contracts/wasm/testwasmlib/ts/testwasmlibclient/testwasmlib.ts b/contracts/wasm/testwasmlib/ts/testwasmlibclient/testwasmlib.ts new file mode 100644 index 0000000000..cbae805e63 --- /dev/null +++ b/contracts/wasm/testwasmlib/ts/testwasmlibclient/testwasmlib.ts @@ -0,0 +1,8 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import * as events from "./events" +import * as service from "./service" + +export function onTestWasmLibTest(event: events.EventTest): void { +} diff --git a/contracts/wasm/testwasmlib/ts/testwasmlibclient/tsconfig.json b/contracts/wasm/testwasmlib/ts/testwasmlibclient/tsconfig.json new file mode 100644 index 0000000000..bc17186726 --- /dev/null +++ b/contracts/wasm/testwasmlib/ts/testwasmlibclient/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": ["es2020"], + "target": "es2020", + "sourceMap": true + }, + "exclude": [ + "node_modules" + ], +} diff --git a/contracts/wasm/timestamp/go/main.go b/contracts/wasm/timestamp/go/main.go index 24e856e140..1d75f182d8 100644 --- a/contracts/wasm/timestamp/go/main.go +++ b/contracts/wasm/timestamp/go/main.go @@ -9,7 +9,7 @@ package main -import "github.com/iotaledger/wasp/packages/vm/wasmclient" +import "github.com/iotaledger/wasp/packages/vm/wasmvmhost" import "github.com/iotaledger/wasp/contracts/wasm/timestamp/go/timestamp" @@ -18,7 +18,7 @@ func main() { //export on_load func onLoad() { - h := &wasmclient.WasmVMHost{} + h := &wasmvmhost.WasmVMHost{} h.ConnectWasmHost() timestamp.OnLoad() } diff --git a/contracts/wasm/timestamp/go/timestamp/results.go b/contracts/wasm/timestamp/go/timestamp/results.go index cb8989f123..ca6aaac36a 100644 --- a/contracts/wasm/timestamp/go/timestamp/results.go +++ b/contracts/wasm/timestamp/go/timestamp/results.go @@ -14,7 +14,7 @@ type ImmutableGetTimestampResults struct { } func (s ImmutableGetTimestampResults) Timestamp() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultTimestamp]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultTimestamp)) } type MutableGetTimestampResults struct { @@ -22,5 +22,5 @@ type MutableGetTimestampResults struct { } func (s MutableGetTimestampResults) Timestamp() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultTimestamp]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultTimestamp)) } diff --git a/contracts/wasm/timestamp/go/timestamp/state.go b/contracts/wasm/timestamp/go/timestamp/state.go index d57540232e..8d1efbe83e 100644 --- a/contracts/wasm/timestamp/go/timestamp/state.go +++ b/contracts/wasm/timestamp/go/timestamp/state.go @@ -14,13 +14,17 @@ type ImmutabletimestampState struct { } func (s ImmutabletimestampState) Timestamp() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxStateTimestamp]) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(StateTimestamp)) } type MutabletimestampState struct { id int32 } +func (s MutabletimestampState) AsImmutable() ImmutabletimestampState { + return ImmutabletimestampState(s) +} + func (s MutabletimestampState) Timestamp() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, idxMap[IdxStateTimestamp]) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(StateTimestamp)) } diff --git a/contracts/wasm/timestamp/src/results.rs b/contracts/wasm/timestamp/src/results.rs index 53e7d5cf08..b0de1e3b73 100644 --- a/contracts/wasm/timestamp/src/results.rs +++ b/contracts/wasm/timestamp/src/results.rs @@ -21,7 +21,7 @@ pub struct ImmutableGetTimestampResults { impl ImmutableGetTimestampResults { pub fn timestamp(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_TIMESTAMP)) + ScImmutableInt64::new(self.id, RESULT_TIMESTAMP.get_key_id()) } } @@ -32,6 +32,6 @@ pub struct MutableGetTimestampResults { impl MutableGetTimestampResults { pub fn timestamp(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_TIMESTAMP)) + ScMutableInt64::new(self.id, RESULT_TIMESTAMP.get_key_id()) } } diff --git a/contracts/wasm/timestamp/src/state.rs b/contracts/wasm/timestamp/src/state.rs index f5554bae10..3b05d63230 100644 --- a/contracts/wasm/timestamp/src/state.rs +++ b/contracts/wasm/timestamp/src/state.rs @@ -21,7 +21,7 @@ pub struct ImmutabletimestampState { impl ImmutabletimestampState { pub fn timestamp(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_STATE_TIMESTAMP)) + ScImmutableInt64::new(self.id, STATE_TIMESTAMP.get_key_id()) } } @@ -31,7 +31,11 @@ pub struct MutabletimestampState { } impl MutabletimestampState { + pub fn as_immutable(&self) -> ImmutabletimestampState { + ImmutabletimestampState { id: self.id } + } + pub fn timestamp(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_STATE_TIMESTAMP)) + ScMutableInt64::new(self.id, STATE_TIMESTAMP.get_key_id()) } } diff --git a/contracts/wasm/timestamp/test/timestamp_bg.wasm b/contracts/wasm/timestamp/test/timestamp_bg.wasm index 6b26a708a3..9c3c530519 100644 Binary files a/contracts/wasm/timestamp/test/timestamp_bg.wasm and b/contracts/wasm/timestamp/test/timestamp_bg.wasm differ diff --git a/contracts/wasm/timestamp/ts/timestamp/results.ts b/contracts/wasm/timestamp/ts/timestamp/results.ts index 3eb8e9ffba..5644226dec 100644 --- a/contracts/wasm/timestamp/ts/timestamp/results.ts +++ b/contracts/wasm/timestamp/ts/timestamp/results.ts @@ -10,12 +10,12 @@ import * as sc from "./index"; export class ImmutableGetTimestampResults extends wasmlib.ScMapID { timestamp(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultTimestamp]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultTimestamp)); } } export class MutableGetTimestampResults extends wasmlib.ScMapID { timestamp(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultTimestamp]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultTimestamp)); } } diff --git a/contracts/wasm/timestamp/ts/timestamp/state.ts b/contracts/wasm/timestamp/ts/timestamp/state.ts index cfa1eaab07..43c2fce463 100644 --- a/contracts/wasm/timestamp/ts/timestamp/state.ts +++ b/contracts/wasm/timestamp/ts/timestamp/state.ts @@ -10,12 +10,18 @@ import * as sc from "./index"; export class ImmutabletimestampState extends wasmlib.ScMapID { timestamp(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateTimestamp]); + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateTimestamp)); } } export class MutabletimestampState extends wasmlib.ScMapID { + asImmutable(): sc.ImmutabletimestampState { + const imm = new sc.ImmutabletimestampState(); + imm.mapID = this.mapID; + return imm; + } + timestamp(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateTimestamp]); + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.StateTimestamp)); } } diff --git a/contracts/wasm/tokenregistry/go/main.go b/contracts/wasm/tokenregistry/go/main.go index e00719edd8..be160c7c43 100644 --- a/contracts/wasm/tokenregistry/go/main.go +++ b/contracts/wasm/tokenregistry/go/main.go @@ -9,7 +9,7 @@ package main -import "github.com/iotaledger/wasp/packages/vm/wasmclient" +import "github.com/iotaledger/wasp/packages/vm/wasmvmhost" import "github.com/iotaledger/wasp/contracts/wasm/tokenregistry/go/tokenregistry" @@ -18,7 +18,7 @@ func main() { //export on_load func onLoad() { - h := &wasmclient.WasmVMHost{} + h := &wasmvmhost.WasmVMHost{} h.ConnectWasmHost() tokenregistry.OnLoad() } diff --git a/contracts/wasm/tokenregistry/go/tokenregistry/params.go b/contracts/wasm/tokenregistry/go/tokenregistry/params.go index 844d234539..4a71631851 100644 --- a/contracts/wasm/tokenregistry/go/tokenregistry/params.go +++ b/contracts/wasm/tokenregistry/go/tokenregistry/params.go @@ -14,11 +14,11 @@ type ImmutableMintSupplyParams struct { } func (s ImmutableMintSupplyParams) Description() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxParamDescription]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamDescription)) } func (s ImmutableMintSupplyParams) UserDefined() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, idxMap[IdxParamUserDefined]) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamUserDefined)) } type MutableMintSupplyParams struct { @@ -26,11 +26,11 @@ type MutableMintSupplyParams struct { } func (s MutableMintSupplyParams) Description() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxParamDescription]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamDescription)) } func (s MutableMintSupplyParams) UserDefined() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, idxMap[IdxParamUserDefined]) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamUserDefined)) } type ImmutableTransferOwnershipParams struct { @@ -38,7 +38,7 @@ type ImmutableTransferOwnershipParams struct { } func (s ImmutableTransferOwnershipParams) Color() wasmlib.ScImmutableColor { - return wasmlib.NewScImmutableColor(s.id, idxMap[IdxParamColor]) + return wasmlib.NewScImmutableColor(s.id, wasmlib.KeyID(ParamColor)) } type MutableTransferOwnershipParams struct { @@ -46,7 +46,7 @@ type MutableTransferOwnershipParams struct { } func (s MutableTransferOwnershipParams) Color() wasmlib.ScMutableColor { - return wasmlib.NewScMutableColor(s.id, idxMap[IdxParamColor]) + return wasmlib.NewScMutableColor(s.id, wasmlib.KeyID(ParamColor)) } type ImmutableUpdateMetadataParams struct { @@ -54,7 +54,7 @@ type ImmutableUpdateMetadataParams struct { } func (s ImmutableUpdateMetadataParams) Color() wasmlib.ScImmutableColor { - return wasmlib.NewScImmutableColor(s.id, idxMap[IdxParamColor]) + return wasmlib.NewScImmutableColor(s.id, wasmlib.KeyID(ParamColor)) } type MutableUpdateMetadataParams struct { @@ -62,7 +62,7 @@ type MutableUpdateMetadataParams struct { } func (s MutableUpdateMetadataParams) Color() wasmlib.ScMutableColor { - return wasmlib.NewScMutableColor(s.id, idxMap[IdxParamColor]) + return wasmlib.NewScMutableColor(s.id, wasmlib.KeyID(ParamColor)) } type ImmutableGetInfoParams struct { @@ -70,7 +70,7 @@ type ImmutableGetInfoParams struct { } func (s ImmutableGetInfoParams) Color() wasmlib.ScImmutableColor { - return wasmlib.NewScImmutableColor(s.id, idxMap[IdxParamColor]) + return wasmlib.NewScImmutableColor(s.id, wasmlib.KeyID(ParamColor)) } type MutableGetInfoParams struct { @@ -78,5 +78,5 @@ type MutableGetInfoParams struct { } func (s MutableGetInfoParams) Color() wasmlib.ScMutableColor { - return wasmlib.NewScMutableColor(s.id, idxMap[IdxParamColor]) + return wasmlib.NewScMutableColor(s.id, wasmlib.KeyID(ParamColor)) } diff --git a/contracts/wasm/tokenregistry/go/tokenregistry/state.go b/contracts/wasm/tokenregistry/go/tokenregistry/state.go index 8b7ca0c52a..ffd7d313f9 100644 --- a/contracts/wasm/tokenregistry/go/tokenregistry/state.go +++ b/contracts/wasm/tokenregistry/go/tokenregistry/state.go @@ -34,12 +34,12 @@ type ImmutableTokenRegistryState struct { } func (s ImmutableTokenRegistryState) ColorList() ArrayOfImmutableColor { - arrID := wasmlib.GetObjectID(s.id, idxMap[IdxStateColorList], wasmlib.TYPE_ARRAY|wasmlib.TYPE_COLOR) + arrID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateColorList), wasmlib.TYPE_ARRAY|wasmlib.TYPE_COLOR) return ArrayOfImmutableColor{objID: arrID} } func (s ImmutableTokenRegistryState) Registry() MapColorToImmutableToken { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateRegistry], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateRegistry), wasmlib.TYPE_MAP) return MapColorToImmutableToken{objID: mapID} } @@ -75,12 +75,16 @@ type MutableTokenRegistryState struct { id int32 } +func (s MutableTokenRegistryState) AsImmutable() ImmutableTokenRegistryState { + return ImmutableTokenRegistryState(s) +} + func (s MutableTokenRegistryState) ColorList() ArrayOfMutableColor { - arrID := wasmlib.GetObjectID(s.id, idxMap[IdxStateColorList], wasmlib.TYPE_ARRAY|wasmlib.TYPE_COLOR) + arrID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateColorList), wasmlib.TYPE_ARRAY|wasmlib.TYPE_COLOR) return ArrayOfMutableColor{objID: arrID} } func (s MutableTokenRegistryState) Registry() MapColorToMutableToken { - mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateRegistry], wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(StateRegistry), wasmlib.TYPE_MAP) return MapColorToMutableToken{objID: mapID} } diff --git a/contracts/wasm/tokenregistry/src/params.rs b/contracts/wasm/tokenregistry/src/params.rs index 6cf7b6ae67..324f58e091 100644 --- a/contracts/wasm/tokenregistry/src/params.rs +++ b/contracts/wasm/tokenregistry/src/params.rs @@ -22,11 +22,11 @@ pub struct ImmutableMintSupplyParams { impl ImmutableMintSupplyParams { pub fn description(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_DESCRIPTION)) + ScImmutableString::new(self.id, PARAM_DESCRIPTION.get_key_id()) } pub fn user_defined(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_USER_DEFINED)) + ScImmutableString::new(self.id, PARAM_USER_DEFINED.get_key_id()) } } @@ -37,11 +37,11 @@ pub struct MutableMintSupplyParams { impl MutableMintSupplyParams { pub fn description(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_DESCRIPTION)) + ScMutableString::new(self.id, PARAM_DESCRIPTION.get_key_id()) } pub fn user_defined(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_USER_DEFINED)) + ScMutableString::new(self.id, PARAM_USER_DEFINED.get_key_id()) } } @@ -52,7 +52,7 @@ pub struct ImmutableTransferOwnershipParams { impl ImmutableTransferOwnershipParams { pub fn color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + ScImmutableColor::new(self.id, PARAM_COLOR.get_key_id()) } } @@ -63,7 +63,7 @@ pub struct MutableTransferOwnershipParams { impl MutableTransferOwnershipParams { pub fn color(&self) -> ScMutableColor { - ScMutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + ScMutableColor::new(self.id, PARAM_COLOR.get_key_id()) } } @@ -74,7 +74,7 @@ pub struct ImmutableUpdateMetadataParams { impl ImmutableUpdateMetadataParams { pub fn color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + ScImmutableColor::new(self.id, PARAM_COLOR.get_key_id()) } } @@ -85,7 +85,7 @@ pub struct MutableUpdateMetadataParams { impl MutableUpdateMetadataParams { pub fn color(&self) -> ScMutableColor { - ScMutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + ScMutableColor::new(self.id, PARAM_COLOR.get_key_id()) } } @@ -96,7 +96,7 @@ pub struct ImmutableGetInfoParams { impl ImmutableGetInfoParams { pub fn color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + ScImmutableColor::new(self.id, PARAM_COLOR.get_key_id()) } } @@ -107,6 +107,6 @@ pub struct MutableGetInfoParams { impl MutableGetInfoParams { pub fn color(&self) -> ScMutableColor { - ScMutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + ScMutableColor::new(self.id, PARAM_COLOR.get_key_id()) } } diff --git a/contracts/wasm/tokenregistry/src/state.rs b/contracts/wasm/tokenregistry/src/state.rs index 3726c7b438..786e448ff1 100644 --- a/contracts/wasm/tokenregistry/src/state.rs +++ b/contracts/wasm/tokenregistry/src/state.rs @@ -15,6 +15,7 @@ use crate::*; use crate::keys::*; use crate::structs::*; +#[derive(Clone, Copy)] pub struct ArrayOfImmutableColor { pub(crate) obj_id: i32, } @@ -29,6 +30,7 @@ impl ArrayOfImmutableColor { } } +#[derive(Clone, Copy)] pub struct MapColorToImmutableToken { pub(crate) obj_id: i32, } @@ -46,16 +48,17 @@ pub struct ImmutableTokenRegistryState { impl ImmutableTokenRegistryState { pub fn color_list(&self) -> ArrayOfImmutableColor { - let arr_id = get_object_id(self.id, idx_map(IDX_STATE_COLOR_LIST), TYPE_ARRAY | TYPE_COLOR); + let arr_id = get_object_id(self.id, STATE_COLOR_LIST.get_key_id(), TYPE_ARRAY | TYPE_COLOR); ArrayOfImmutableColor { obj_id: arr_id } } pub fn registry(&self) -> MapColorToImmutableToken { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_REGISTRY), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_REGISTRY.get_key_id(), TYPE_MAP); MapColorToImmutableToken { obj_id: map_id } } } +#[derive(Clone, Copy)] pub struct ArrayOfMutableColor { pub(crate) obj_id: i32, } @@ -74,6 +77,7 @@ impl ArrayOfMutableColor { } } +#[derive(Clone, Copy)] pub struct MapColorToMutableToken { pub(crate) obj_id: i32, } @@ -94,13 +98,17 @@ pub struct MutableTokenRegistryState { } impl MutableTokenRegistryState { + pub fn as_immutable(&self) -> ImmutableTokenRegistryState { + ImmutableTokenRegistryState { id: self.id } + } + pub fn color_list(&self) -> ArrayOfMutableColor { - let arr_id = get_object_id(self.id, idx_map(IDX_STATE_COLOR_LIST), TYPE_ARRAY | TYPE_COLOR); + let arr_id = get_object_id(self.id, STATE_COLOR_LIST.get_key_id(), TYPE_ARRAY | TYPE_COLOR); ArrayOfMutableColor { obj_id: arr_id } } pub fn registry(&self) -> MapColorToMutableToken { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_REGISTRY), TYPE_MAP); + let map_id = get_object_id(self.id, STATE_REGISTRY.get_key_id(), TYPE_MAP); MapColorToMutableToken { obj_id: map_id } } } diff --git a/contracts/wasm/tokenregistry/src/structs.rs b/contracts/wasm/tokenregistry/src/structs.rs index d5dd0a4c6b..3fce40d7f1 100644 --- a/contracts/wasm/tokenregistry/src/structs.rs +++ b/contracts/wasm/tokenregistry/src/structs.rs @@ -11,6 +11,7 @@ use wasmlib::*; use wasmlib::host::*; +#[derive(Clone)] pub struct Token { pub created : i64, // creation timestamp pub description : String, // description what minted token represents @@ -48,6 +49,7 @@ impl Token { } } +#[derive(Clone, Copy)] pub struct ImmutableToken { pub(crate) obj_id: i32, pub(crate) key_id: Key32, @@ -63,6 +65,7 @@ impl ImmutableToken { } } +#[derive(Clone, Copy)] pub struct MutableToken { pub(crate) obj_id: i32, pub(crate) key_id: Key32, diff --git a/contracts/wasm/tokenregistry/test/tokenregistry_bg.wasm b/contracts/wasm/tokenregistry/test/tokenregistry_bg.wasm index 27eecf21ae..5791385713 100644 Binary files a/contracts/wasm/tokenregistry/test/tokenregistry_bg.wasm and b/contracts/wasm/tokenregistry/test/tokenregistry_bg.wasm differ diff --git a/contracts/wasm/tokenregistry/ts/tokenregistry/params.ts b/contracts/wasm/tokenregistry/ts/tokenregistry/params.ts index 8d16af038f..7307270773 100644 --- a/contracts/wasm/tokenregistry/ts/tokenregistry/params.ts +++ b/contracts/wasm/tokenregistry/ts/tokenregistry/params.ts @@ -10,56 +10,56 @@ import * as sc from "./index"; export class ImmutableMintSupplyParams extends wasmlib.ScMapID { description(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamDescription]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamDescription)); } userDefined(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamUserDefined]); + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamUserDefined)); } } export class MutableMintSupplyParams extends wasmlib.ScMapID { description(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamDescription]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamDescription)); } userDefined(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamUserDefined]); + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamUserDefined)); } } export class ImmutableTransferOwnershipParams extends wasmlib.ScMapID { color(): wasmlib.ScImmutableColor { - return new wasmlib.ScImmutableColor(this.mapID, sc.idxMap[sc.IdxParamColor]); + return new wasmlib.ScImmutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamColor)); } } export class MutableTransferOwnershipParams extends wasmlib.ScMapID { color(): wasmlib.ScMutableColor { - return new wasmlib.ScMutableColor(this.mapID, sc.idxMap[sc.IdxParamColor]); + return new wasmlib.ScMutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamColor)); } } export class ImmutableUpdateMetadataParams extends wasmlib.ScMapID { color(): wasmlib.ScImmutableColor { - return new wasmlib.ScImmutableColor(this.mapID, sc.idxMap[sc.IdxParamColor]); + return new wasmlib.ScImmutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamColor)); } } export class MutableUpdateMetadataParams extends wasmlib.ScMapID { color(): wasmlib.ScMutableColor { - return new wasmlib.ScMutableColor(this.mapID, sc.idxMap[sc.IdxParamColor]); + return new wasmlib.ScMutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamColor)); } } export class ImmutableGetInfoParams extends wasmlib.ScMapID { color(): wasmlib.ScImmutableColor { - return new wasmlib.ScImmutableColor(this.mapID, sc.idxMap[sc.IdxParamColor]); + return new wasmlib.ScImmutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamColor)); } } export class MutableGetInfoParams extends wasmlib.ScMapID { color(): wasmlib.ScMutableColor { - return new wasmlib.ScMutableColor(this.mapID, sc.idxMap[sc.IdxParamColor]); + return new wasmlib.ScMutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamColor)); } } diff --git a/contracts/wasm/tokenregistry/ts/tokenregistry/state.ts b/contracts/wasm/tokenregistry/ts/tokenregistry/state.ts index bdbf15f919..99141b917a 100644 --- a/contracts/wasm/tokenregistry/ts/tokenregistry/state.ts +++ b/contracts/wasm/tokenregistry/ts/tokenregistry/state.ts @@ -38,12 +38,12 @@ export class MapColorToImmutableToken { export class ImmutableTokenRegistryState extends wasmlib.ScMapID { colorList(): sc.ArrayOfImmutableColor { - let arrID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateColorList], wasmlib.TYPE_ARRAY|wasmlib.TYPE_COLOR); + let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateColorList), wasmlib.TYPE_ARRAY|wasmlib.TYPE_COLOR); return new sc.ArrayOfImmutableColor(arrID); } registry(): sc.MapColorToImmutableToken { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateRegistry], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateRegistry), wasmlib.TYPE_MAP); return new sc.MapColorToImmutableToken(mapID); } } @@ -85,13 +85,19 @@ export class MapColorToMutableToken { } export class MutableTokenRegistryState extends wasmlib.ScMapID { + asImmutable(): sc.ImmutableTokenRegistryState { + const imm = new sc.ImmutableTokenRegistryState(); + imm.mapID = this.mapID; + return imm; + } + colorList(): sc.ArrayOfMutableColor { - let arrID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateColorList], wasmlib.TYPE_ARRAY|wasmlib.TYPE_COLOR); + let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateColorList), wasmlib.TYPE_ARRAY|wasmlib.TYPE_COLOR); return new sc.ArrayOfMutableColor(arrID); } registry(): sc.MapColorToMutableToken { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateRegistry], wasmlib.TYPE_MAP); + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.StateRegistry), wasmlib.TYPE_MAP); return new sc.MapColorToMutableToken(mapID); } } diff --git a/documentation/docs/guide/chains_and_nodes/running-a-node.md b/documentation/docs/guide/chains_and_nodes/running-a-node.md index 40e4e85728..71f89d6936 100644 --- a/documentation/docs/guide/chains_and_nodes/running-a-node.md +++ b/documentation/docs/guide/chains_and_nodes/running-a-node.md @@ -245,4 +245,4 @@ wasp --webapi.adminWhitelist=127.0.0.1,YOUR_IP ## Video Tutorial - + diff --git a/documentation/docs/guide/core_concepts/consensus.md b/documentation/docs/guide/core_concepts/consensus.md index 9caeab9032..d173018a48 100644 --- a/documentation/docs/guide/core_concepts/consensus.md +++ b/documentation/docs/guide/core_concepts/consensus.md @@ -35,7 +35,7 @@ The anchor transaction contains chain state transition, the AliasOutput and toke **It is only possible to produce valid signatures of inputs of the anchor transaction by the quorum** of nodes. In this case, a confirmed anchor transaction becomes a cryptographical **proof of consensus** in the committee. -To archive this, IOTA Smart Contracts uses **BLS threshold signatures in combination with polynomial (Shamir) secret sharing** to identify the address controlling the chain state. In order for the secret keys to be distributed across the chain validators, a DKG (Distributed Key Generation) procedure is executed when starting a chain (using the Rabin-Gennaro algorithm). +To achieve this, IOTA Smart Contracts uses **BLS threshold signatures in combination with polynomial (Shamir) secret sharing** to identify the address controlling the chain state. In order for the secret keys to be distributed across the chain validators, a DKG (Distributed Key Generation) procedure is executed when starting a chain (using the Rabin-Gennaro algorithm). ## The Consensus Algorithm diff --git a/documentation/docs/guide/evm/create-chain.md b/documentation/docs/guide/evm/create-chain.md index f35e3819c7..57adfc6031 100644 --- a/documentation/docs/guide/evm/create-chain.md +++ b/documentation/docs/guide/evm/create-chain.md @@ -79,3 +79,7 @@ Re-using an existing Chain ID is not recommended, and can be a security risk. Fo The current implementation uses the wasp-cli's saves the account to pay for any fees in IOTA while using the JSON-RPC interface. This is of course not ideal in a normal usage scenario. Upcoming releases will address this in a more user-friendly way. ::: + +## Video Tutorial + + diff --git a/documentation/docs/guide/evm/examples/ERC20.md b/documentation/docs/guide/evm/examples/ERC20.md index 57084d5630..2b06394e3c 100644 --- a/documentation/docs/guide/evm/examples/ERC20.md +++ b/documentation/docs/guide/evm/examples/ERC20.md @@ -20,7 +20,7 @@ With the ERC20 standart you can create your own tokens and transfer them in the You can use the [Remix IDE](https://remix.ethereum.org/) to deploy any regular Solidity Smart Contract. Set the environment to `Injected Web3`, and connect Remix with your MetaMask wallet. -Read this [how to connect your Metamask with the public Testnet.](/wasp/guide/chains_and_nodes/testnet#interact-with-evm). +Read this [how to connect your Metamask with the public Testnet.](/smart-contracts/guide/chains_and_nodes/testnet#interact-with-evm). ## 1. Create a Smart Contract @@ -74,4 +74,4 @@ Now you should see your token in MetaMask - send them to your friends without an [![Copy contract address](./images/erc20-balance.png)](./images/erc20-balance.png) -You also can ask in the [Discord Chat Server](https://discord.iota.org) to send them around and discover what the community is building on IOTA Smart Contracts. \ No newline at end of file +You also can ask in the [Discord Chat Server](https://discord.iota.org) to send them around and discover what the community is building on IOTA Smart Contracts. diff --git a/documentation/docs/guide/evm/tooling.md b/documentation/docs/guide/evm/tooling.md index ee957c8f09..e90b4cd2fd 100644 --- a/documentation/docs/guide/evm/tooling.md +++ b/documentation/docs/guide/evm/tooling.md @@ -52,11 +52,15 @@ If you wish to use additional EVM chains with Metamask, you can simply add more If you also want to use the [Remix IDE](https://remix.ethereum.org/) to deploy any regular Solidity Smart Contract, you should set the environment as **Injected Web3**, which should then connect with your MetaMask wallet. +## Video Tutorial + + + ## Hardhat [Hardhat](https://hardhat.org/) is a commandline toolbox that allows you to deploy, test, verify, and interact with Solidity smart contracts on an EVM chain. EVM chains running on IOTA Smart Contracts are compatible with Hardhat; simply make sure you add the correct network parameters to your `hardhat.config.js`, for example: -```javascript= +```javascript networks: { local: { url: 'http://localhost:8545', @@ -73,6 +77,10 @@ Currently, there is no validation service available for EVM/Solidity smart contr ::: +## Video Tutorial + + + ## Ethers.js/Web3.js diff --git a/documentation/docs/guide/example_projects/fair_roulette.md b/documentation/docs/guide/example_projects/fair_roulette.md index a475b6e17f..4713eae723 100644 --- a/documentation/docs/guide/example_projects/fair_roulette.md +++ b/documentation/docs/guide/example_projects/fair_roulette.md @@ -65,7 +65,7 @@ Off-ledger requests are directly sent to Wasp nodes and do not require validatio :::note This example uses On-ledger requests to initiate a betting request. A method to invoke Off-ledger requests is implemented inside the frontend. -See: [placeBetOffLedger](https://github.com/iotaledger/wasp/blob/7b3ddc54891ccf021c7aaa32db35d88361fade16/contracts/rust/fairroulette/frontend/src/lib/fairroulette_client/fair_roulette_service.ts#L133) +See: [placeBetOffLedger](https://github.com/iotaledger/wasp/blob/7b3ddc54891ccf021c7aaa32db35d88361fade16/contracts/wasm/fairroulette/frontend/src/lib/fairroulette_client/fair_roulette_service.ts#L133) ::: #### Funds @@ -217,7 +217,7 @@ This service comprises two parts: ##### PlaceBetOnLedger -The [placeBetOnLedger](https://github.com/iotaledger/wasp/blob/7b3ddc54891ccf021c7aaa32db35d88361fade16/contracts/rust/fairroulette/frontend/src/lib/fairroulette_client/fair_roulette_service.ts#L149) function is responsible for sending On-Ledger bet requests. It constructs a simple OnLedger object containing: +The [placeBetOnLedger](https://github.com/iotaledger/wasp/blob/7b3ddc54891ccf021c7aaa32db35d88361fade16/contracts/wasm/fairroulette/frontend/src/lib/fairroulette_client/fair_roulette_service.ts#L149) function is responsible for sending On-Ledger bet requests. It constructs a simple OnLedger object containing: * The smart contract ID: `fairroulette` * The function to invoke: `placeBet` @@ -235,7 +235,7 @@ See: [CoreTypes](https://wiki.iota.org/wasp/misc/coretypes) and [Invoking](https ##### CallView -The [callView](https://github.com/iotaledger/wasp/blob/7b3ddc54891ccf021c7aaa32db35d88361fade16/contracts/rust/fairroulette/frontend/src/lib/fairroulette_client/fair_roulette_service.ts#L165) function is responsible for calling smart contract view functions. +The [callView](https://github.com/iotaledger/wasp/blob/7b3ddc54891ccf021c7aaa32db35d88361fade16/contracts/wasm/fairroulette/frontend/src/lib/fairroulette_client/fair_roulette_service.ts#L165) function is responsible for calling smart contract view functions. See: [Calling a view](https://wiki.iota.org/wasp/guide/solo/view-sc) @@ -246,9 +246,9 @@ State changes that happen afterwards are published through the websocket event s You can find examples to guide you in building similar functions in: -* Frontend: [getRoundStatus](https://github.com/iotaledger/wasp/blob/7b3ddc54891ccf021c7aaa32db35d88361fade16/contracts/rust/fairroulette/frontend/src/lib/fairroulette_client/fair_roulette_service.ts#L181) +* Frontend: [getRoundStatus](https://github.com/iotaledger/wasp/blob/7b3ddc54891ccf021c7aaa32db35d88361fade16/contracts/wasm/fairroulette/frontend/src/lib/fairroulette_client/fair_roulette_service.ts#L181) -* Smart Contract: [view_round_status](https://github.com/iotaledger/wasp/blob/7b3ddc54891ccf021c7aaa32db35d88361fade16/contracts/rust/fairroulette/src/fairroulette.rs#L312) +* Smart Contract: [view_round_status](https://github.com/iotaledger/wasp/blob/7b3ddc54891ccf021c7aaa32db35d88361fade16/contracts/wasm/fairroulette/src/fairroulette.rs#L312) Since data returned by the views is encoded in Base64, the frontend needs to decode this by using simple `Buffer` methods. The `view_round_status` view returns an `UInt16` which has a state of either `0` or `1`. diff --git a/documentation/docs/guide/schema/usage.mdx b/documentation/docs/guide/schema/usage.mdx index 076bf53a9a..22811f06d7 100644 --- a/documentation/docs/guide/schema/usage.mdx +++ b/documentation/docs/guide/schema/usage.mdx @@ -338,3 +338,11 @@ parameter. In the next section we will look at how a smart contract uses [Structured Data Types](structs.mdx). + +## Video Tutorial + + + +### Creating Smart Contracts using AssemblyScript + + diff --git a/documentation/docs/guide/solo/what-is-solo.md b/documentation/docs/guide/solo/what-is-solo.md index e3661fe9a9..28fbe2c076 100644 --- a/documentation/docs/guide/solo/what-is-solo.md +++ b/documentation/docs/guide/solo/what-is-solo.md @@ -45,7 +45,7 @@ The GoLang environment with the Rust plugin is a good combination. You can find example implementations of smart contracts (including source code and tests) in the Wasp repository, in the -[contracts/rust folder](https://github.com/iotaledger/wasp/tree/master/contracts/rust). +[contracts/wasm folder](https://github.com/iotaledger/wasp/tree/master/contracts/wasm). :::tip You can find the documentation for all the functionalities available in solo in [go-docs](https://pkg.go.dev/github.com/iotaledger/wasp/packages/solo). diff --git a/documentation/docs/guide/wasm_vm/intro.mdx b/documentation/docs/guide/wasm_vm/intro.mdx index 1177a97023..a04246a558 100644 --- a/documentation/docs/guide/wasm_vm/intro.mdx +++ b/documentation/docs/guide/wasm_vm/intro.mdx @@ -86,3 +86,6 @@ languages, without having to dive deeply into all aspects of the chosen language We will now dive deeper into the concepts that are central to WasmLib smart contract programming. +## Video Tutorial + + diff --git a/documentation/temp/misc/install.md b/documentation/temp/misc/install.md index 33b8045c20..93a8c94370 100644 --- a/documentation/temp/misc/install.md +++ b/documentation/temp/misc/install.md @@ -26,4 +26,4 @@ environment with the Rust plugin is a good combination. You can find example implementations of smart contracts (including source code and tests) in the Wasp repository, in the -[contracts/rust folder](https://github.com/iotaledger/wasp/tree/master/contracts/rust). +[contracts/wasm folder](https://github.com/iotaledger/wasp/tree/master/contracts/wasm). diff --git a/documentation/uml/class__Governance__Governance.png b/documentation/uml/class__Governance__Governance.png new file mode 100644 index 0000000000..0096625429 Binary files /dev/null and b/documentation/uml/class__Governance__Governance.png differ diff --git a/documentation/uml/sd__Governance__Governance.png b/documentation/uml/sd__Governance__Governance.png new file mode 100644 index 0000000000..1ddd3b9c7f Binary files /dev/null and b/documentation/uml/sd__Governance__Governance.png differ diff --git a/documentation/uml/stm__Governance-OwnershipFSM__Governance-OwnershipFSM.png b/documentation/uml/stm__Governance-OwnershipFSM__Governance-OwnershipFSM.png new file mode 100644 index 0000000000..e8ecb916e0 Binary files /dev/null and b/documentation/uml/stm__Governance-OwnershipFSM__Governance-OwnershipFSM.png differ diff --git a/documentation/uml/stm__GovernanceSC-RotationFSM__GovernanceSC-RotationFSM.png b/documentation/uml/stm__GovernanceSC-RotationFSM__GovernanceSC-RotationFSM.png new file mode 100644 index 0000000000..e88800a7d5 Binary files /dev/null and b/documentation/uml/stm__GovernanceSC-RotationFSM__GovernanceSC-RotationFSM.png differ diff --git a/documentation/uml/uc__Use_Cases__Governance.png b/documentation/uml/uc__Use_Cases__Governance.png new file mode 100644 index 0000000000..8328b3ea78 Binary files /dev/null and b/documentation/uml/uc__Use_Cases__Governance.png differ diff --git a/documentation/uml/wasp.mdzip b/documentation/uml/wasp.mdzip index 169fb8e92c..6ec789f5d8 100644 Binary files a/documentation/uml/wasp.mdzip and b/documentation/uml/wasp.mdzip differ diff --git a/go.mod b/go.mod index 669a802d98..b34c5c63e6 100644 --- a/go.mod +++ b/go.mod @@ -8,9 +8,7 @@ require ( github.com/PuerkitoBio/goquery v1.6.1 github.com/anthdm/hbbft v0.0.0-20190702061856-0826ffdcf567 github.com/bygui86/multi-profile/v2 v2.1.0 - github.com/bytecodealliance/wasmtime-go v0.31.0 - github.com/wasmerio/wasmer-go v1.0.4 - github.com/second-state/WasmEdge-go v0.9.0-rc3 // indirect + github.com/bytecodealliance/wasmtime-go v0.32.0 github.com/ethereum/go-ethereum v1.10.10 github.com/iotaledger/goshimmer v0.7.5-0.20210811162925-25c827e8326a github.com/iotaledger/hive.go v0.0.0-20210625103722-68b2cf52ef4e @@ -26,10 +24,12 @@ require ( github.com/pangpanglabs/echoswagger/v2 v2.1.0 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.10.0 + github.com/second-state/WasmEdge-go v0.9.0 // indirect github.com/spf13/cobra v1.1.3 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.7.0 github.com/stretchr/testify v1.7.0 + github.com/wasmerio/wasmer-go v1.0.4 go.dedis.ch/kyber/v3 v3.0.13 go.nanomsg.org/mangos/v3 v3.0.1 go.uber.org/atomic v1.7.0 @@ -43,6 +43,7 @@ require ( replace ( github.com/anthdm/hbbft => github.com/kape1395/hbbft v0.0.0-20210824083459-b949585b7515 github.com/ethereum/go-ethereum => github.com/dessaya/go-ethereum v1.10.10-0.20211102133541-45878bcd628c + github.com/iotaledger/goshimmer => github.com/kape1395/goshimmer v0.7.5-0.20220126105741-2bc797667497 github.com/linxGnu/grocksdb => github.com/gohornet/grocksdb v1.6.38-0.20211012114404-55f425442260 go.dedis.ch/kyber/v3 v3.0.13 => github.com/kape1395/kyber/v3 v3.0.14-0.20210622094514-fefb81148dc3 ) diff --git a/go.sum b/go.sum index 6ba6d789cd..bccf796c22 100644 --- a/go.sum +++ b/go.sum @@ -155,6 +155,8 @@ github.com/bytecodealliance/wasmtime-go v0.21.0 h1:8C6fNmpfzF6QQ9h0PCvGaYORhtgMv github.com/bytecodealliance/wasmtime-go v0.21.0/go.mod h1:q320gUxqyI8yB+ZqRuaJOEnGkAnHh6WtJjMaT2CW4wI= github.com/bytecodealliance/wasmtime-go v0.31.0 h1:AbMdV1pwjw/0Ito5yARcGzY366cq5NIiDk5vpy1c2Lw= github.com/bytecodealliance/wasmtime-go v0.31.0/go.mod h1:q320gUxqyI8yB+ZqRuaJOEnGkAnHh6WtJjMaT2CW4wI= +github.com/bytecodealliance/wasmtime-go v0.32.0 h1:/GsrnJz2bfULAIZygN4vUElLYliQrx/o/1opP9X7Gck= +github.com/bytecodealliance/wasmtime-go v0.32.0/go.mod h1:q320gUxqyI8yB+ZqRuaJOEnGkAnHh6WtJjMaT2CW4wI= github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= github.com/capossele/asset-registry v0.0.0-20210521112927-c9d6e74574e8/go.mod h1:BXwVCA0+rgYcMKC3vVkfjF+2nXYIYq3h/HndbaCuw08= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= @@ -677,6 +679,8 @@ github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/kabukky/httpscerts v0.0.0-20150320125433-617593d7dcb3/go.mod h1:BYpt4ufZiIGv2nXn4gMxnfKV306n3mWXgNu/d2TqdTU= github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= +github.com/kape1395/goshimmer v0.7.5-0.20220126105741-2bc797667497 h1:Xteehyq9wIA12gi4lkvmd+VOXrgjlt9PGmm2AtOIotA= +github.com/kape1395/goshimmer v0.7.5-0.20220126105741-2bc797667497/go.mod h1:L4a9tQOOlD37go7UztwlCFMrNlmgwKK9ixaPf45A/8U= github.com/kape1395/hbbft v0.0.0-20210824083459-b949585b7515 h1:5oWqeyYqb0A+XNeM4qIESTfrgbTdCF+YTPgb9Rc50iM= github.com/kape1395/hbbft v0.0.0-20210824083459-b949585b7515/go.mod h1:XadZ7V3kvoIfFGVb8s/ndgVitoHRNRjzgPlHhhb9HlI= github.com/kape1395/kyber/v3 v3.0.14-0.20210622094514-fefb81148dc3 h1:b7VGpy3biHI8Q0O8BthxiJfOXhx5F0Ej4TNuJ9A1omo= @@ -1294,6 +1298,8 @@ github.com/second-state/WasmEdge-go v0.8.2 h1:dD5+ZKY9Vr+Ye5F9VZGP/WP2MnXfORQocU github.com/second-state/WasmEdge-go v0.8.2/go.mod h1:Q3h79fwQs7GUSOm3ZzHXK+j4cKmCFP3SKpGfFNDtqD8= github.com/second-state/WasmEdge-go v0.9.0-rc3 h1:Ol6KaPguuqyd42vb9W7VCRR4V92yZdVpqUh0MWD07Y4= github.com/second-state/WasmEdge-go v0.9.0-rc3/go.mod h1:Q3h79fwQs7GUSOm3ZzHXK+j4cKmCFP3SKpGfFNDtqD8= +github.com/second-state/WasmEdge-go v0.9.0 h1:CapdsNNP5HG8nIeX8qmRteie8SZC/+BkmNXq+IoQlKE= +github.com/second-state/WasmEdge-go v0.9.0/go.mod h1:Q3h79fwQs7GUSOm3ZzHXK+j4cKmCFP3SKpGfFNDtqD8= github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= github.com/sercand/kuberesolver v2.1.0+incompatible/go.mod h1:lWF3GL0xptCB/vCiJPl/ZshwPsX/n4Y7u0CW9E7aQIQ= diff --git a/main.go b/main.go index 1944d8dbf9..0611734d9b 100644 --- a/main.go +++ b/main.go @@ -21,6 +21,7 @@ import ( "github.com/iotaledger/wasp/plugins/profiling" "github.com/iotaledger/wasp/plugins/publishernano" "github.com/iotaledger/wasp/plugins/registry" + "github.com/iotaledger/wasp/plugins/wal" "github.com/iotaledger/wasp/plugins/wasmtimevm" "github.com/iotaledger/wasp/plugins/webapi" ) @@ -43,6 +44,7 @@ func main() { nodeconn.Init(), processors.Init(), wasmtimevm.Init(), + wal.Init(), chains.Init(), metrics.Init(), webapi.Init(), diff --git a/packages/apilib/deploychain.go b/packages/apilib/deploychain.go index 4f71778df4..33d0e9fdb1 100644 --- a/packages/apilib/deploychain.go +++ b/packages/apilib/deploychain.go @@ -16,38 +16,28 @@ import ( "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/registry" "github.com/iotaledger/wasp/packages/transaction" - "github.com/iotaledger/wasp/packages/util" "golang.org/x/xerrors" ) // TODO DeployChain on peering domain, not on committee type CreateChainParams struct { - Node *goshimmer.Client - AllAPIHosts []string - AllPeeringHosts []string - CommitteeAPIHosts []string - CommitteePeeringHosts []string - N uint16 - T uint16 - OriginatorKeyPair *ed25519.KeyPair - Description string - Textout io.Writer - Prefix string + Node *goshimmer.Client + CommitteeAPIHosts []string + CommitteePubKeys []string + N uint16 + T uint16 + OriginatorKeyPair *ed25519.KeyPair + Description string + Textout io.Writer + Prefix string } // DeployChainWithDKG performs all actions needed to deploy the chain // TODO: [KP] Shouldn't that be in the client packages? func DeployChainWithDKG(par CreateChainParams) (*iscp.ChainID, ledgerstate.Address, error) { - if len(par.AllPeeringHosts) > 0 { - // all committee nodes most also be among allPeers - if !util.IsSubset(par.CommitteePeeringHosts, par.AllPeeringHosts) { - return nil, nil, xerrors.Errorf("DeployChainWithDKG: committee nodes must all be among peers") - } - } - dkgInitiatorIndex := uint16(rand.Intn(len(par.CommitteeAPIHosts))) - stateControllerAddr, err := RunDKG(par.CommitteeAPIHosts, par.CommitteePeeringHosts, par.T, dkgInitiatorIndex) + stateControllerAddr, err := RunDKG(par.CommitteeAPIHosts, par.CommitteePubKeys, par.T, dkgInitiatorIndex) if err != nil { return nil, nil, err } @@ -83,7 +73,7 @@ func DeployChain(par CreateChainParams, stateControllerAddr ledgerstate.Address) fmt.Fprintf(textout, "creating chain origin and init transaction %s.. OK\n", initRequestTx.ID().Base58()) fmt.Fprint(textout, "sending committee record to nodes.. OK\n") - err = ActivateChainOnAccessNodes(par.AllAPIHosts, par.AllPeeringHosts, chainID) + err = ActivateChainOnAccessNodes(par.CommitteeAPIHosts, chainID) fmt.Fprint(textout, par.Prefix) if err != nil { fmt.Fprintf(textout, "activating chain %s.. FAILED: %v\n", chainID.Base58(), err) @@ -162,12 +152,11 @@ func CreateChainOrigin(node *goshimmer.Client, originator *ed25519.KeyPair, stat // ActivateChainOnAccessNodes puts chain records into nodes and activates its // TODO needs refactoring and optimization -func ActivateChainOnAccessNodes(apiHosts, peers []string, chainID *iscp.ChainID) error { +func ActivateChainOnAccessNodes(apiHosts []string, chainID *iscp.ChainID) error { nodes := multiclient.New(apiHosts) // ------------ put chain records to hosts err := nodes.PutChainRecord(®istry.ChainRecord{ ChainID: chainID, - Peers: peers, }) if err != nil { return xerrors.Errorf("ActivateChainOnAccessNodes: %w", err) diff --git a/packages/apilib/rundkg.go b/packages/apilib/rundkg.go index 4a7d3cb7af..5e4d2307fc 100644 --- a/packages/apilib/rundkg.go +++ b/packages/apilib/rundkg.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package apilib import ( @@ -5,8 +8,6 @@ import ( "github.com/iotaledger/goshimmer/packages/ledgerstate" "github.com/iotaledger/wasp/client" - "github.com/iotaledger/wasp/client/multiclient" - "github.com/iotaledger/wasp/packages/registry" "github.com/iotaledger/wasp/packages/util" "github.com/iotaledger/wasp/packages/webapi/model" "golang.org/x/xerrors" @@ -14,7 +15,7 @@ import ( // RunDKG runs DKG procedure on specific Wasp hosts: generates new keys and puts corresponding committee records // into nodes. In case of success, generated address is returned -func RunDKG(apiHosts, peeringHosts []string, threshold, initiatorIndex uint16, timeout ...time.Duration) (ledgerstate.Address, error) { +func RunDKG(apiHosts, peerPubKeys []string, threshold, initiatorIndex uint16, timeout ...time.Duration) (ledgerstate.Address, error) { to := uint32(60 * 1000) if len(timeout) > 0 { n := timeout[0].Milliseconds() @@ -26,8 +27,7 @@ func RunDKG(apiHosts, peeringHosts []string, threshold, initiatorIndex uint16, t return nil, xerrors.New("RunDKG: wrong initiator index") } dkShares, err := client.NewWaspClient(apiHosts[initiatorIndex]).DKSharesPost(&model.DKSharesPostRequest{ - PeerNetIDs: peeringHosts, - PeerPubKeys: nil, + PeerPubKeys: peerPubKeys, Threshold: threshold, TimeoutMS: to, // 1 min }) @@ -39,13 +39,5 @@ func RunDKG(apiHosts, peeringHosts []string, threshold, initiatorIndex uint16, t return nil, xerrors.Errorf("RunDKG: invalid address returned from DKG: %w", err) } - // put committee records to hosts - err = multiclient.New(apiHosts).PutCommitteeRecord(®istry.CommitteeRecord{ - Address: addr, - Nodes: peeringHosts, - }) - if err != nil { - return nil, xerrors.Errorf("RunDKG: PutCommitteeRecord: %w", err) - } return addr, nil } diff --git a/packages/chain/chain.go b/packages/chain/chain.go index ef7b0a1f9f..eb5dba9e7b 100644 --- a/packages/chain/chain.go +++ b/packages/chain/chain.go @@ -8,6 +8,7 @@ import ( "time" "github.com/iotaledger/goshimmer/packages/ledgerstate" + "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/hive.go/events" "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/wasp/packages/chain/messages" @@ -15,9 +16,11 @@ import ( "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/iscp/coreutil" "github.com/iotaledger/wasp/packages/metrics/nodeconnmetrics" + "github.com/iotaledger/wasp/packages/peering" "github.com/iotaledger/wasp/packages/state" "github.com/iotaledger/wasp/packages/tcrypto" "github.com/iotaledger/wasp/packages/util/ready" + "github.com/iotaledger/wasp/packages/vm/core/governance" "github.com/iotaledger/wasp/packages/vm/processors" ) @@ -29,6 +32,8 @@ type ChainCore interface { Processors() *processors.Cache GlobalStateSync() coreutil.ChainStateSync GetStateReader() state.OptimisticStateReader + GetChainNodes() []peering.PeerStatusProvider // CommitteeNodes + AccessNodes + GetCandidateNodes() []*governance.AccessNodeInfo // All the current candidates. Log() *logger.Logger // Most of these methods are made public for mocking in tests @@ -45,7 +50,6 @@ type ChainCore interface { type ChainEntry interface { ReceiveTransaction(*ledgerstate.Transaction) ReceiveState(stateOutput *ledgerstate.AliasOutput, timestamp time.Time) - Dismiss(reason string) IsDismissed() bool } @@ -59,6 +63,7 @@ type ChainRequests interface { type ChainMetrics interface { GetNodeConnectionMetrics() nodeconnmetrics.NodeConnectionMessagesMetrics + GetConsensusWorkflowStatus() ConsensusWorkflowStatus } type Chain interface { @@ -81,8 +86,7 @@ type Committee interface { IsReady() bool Close() RunACSConsensus(value []byte, sessionID uint64, stateIndex uint32, callback func(sessionID uint64, acs [][]byte)) - GetOtherValidatorsPeerIDs() []string - GetRandomValidators(upToN int) []string + GetRandomValidators(upToN int) []*ed25519.PublicKey // TODO: Remove after OffLedgerRequest dissemination is changed. } type ( @@ -95,19 +99,15 @@ type ( type NodeConnection interface { Subscribe(addr ledgerstate.Address) Unsubscribe(addr ledgerstate.Address) - AttachToTransactionReceived(*ledgerstate.AliasAddress, NodeConnectionHandleTransactionFun) AttachToInclusionStateReceived(*ledgerstate.AliasAddress, NodeConnectionHandleInclusionStateFun) AttachToOutputReceived(*ledgerstate.AliasAddress, NodeConnectionHandleOutputFun) AttachToUnspentAliasOutputReceived(*ledgerstate.AliasAddress, NodeConnectionHandleUnspentAliasOutputFun) - PullState(addr *ledgerstate.AliasAddress) PullTransactionInclusionState(addr ledgerstate.Address, txid ledgerstate.TransactionID) PullConfirmedOutput(addr ledgerstate.Address, outputID ledgerstate.OutputID) PostTransaction(tx *ledgerstate.Transaction) - GetMetrics() nodeconnmetrics.NodeConnectionMetrics - DetachFromTransactionReceived(*ledgerstate.AliasAddress) DetachFromInclusionStateReceived(*ledgerstate.AliasAddress) DetachFromOutputReceived(*ledgerstate.AliasAddress) @@ -120,14 +120,11 @@ type ChainNodeConnection interface { AttachToInclusionStateReceived(NodeConnectionHandleInclusionStateFun) AttachToOutputReceived(NodeConnectionHandleOutputFun) AttachToUnspentAliasOutputReceived(NodeConnectionHandleUnspentAliasOutputFun) - PullState() PullTransactionInclusionState(txid ledgerstate.TransactionID) PullConfirmedOutput(outputID ledgerstate.OutputID) PostTransaction(tx *ledgerstate.Transaction) - GetMetrics() nodeconnmetrics.NodeConnectionMessagesMetrics - DetachFromTransactionReceived() DetachFromInclusionStateReceived() DetachFromOutputReceived() @@ -144,6 +141,7 @@ type StateManager interface { EnqueueStateCandidateMsg(state.VirtualStateAccess, ledgerstate.OutputID) EnqueueTimerMsg(msg messages.TimerTick) GetStatusSnapshot() *SyncInfo + SetChainPeers(peers []*ed25519.PublicKey) Close() } @@ -158,6 +156,7 @@ type Consensus interface { IsReady() bool Close() GetStatusSnapshot() *ConsensusInfo + GetWorkflowStatus() ConsensusWorkflowStatus ShouldReceiveMissingRequest(req iscp.Request) bool } @@ -180,6 +179,12 @@ type AsynchronousCommonSubsetRunner interface { Close() } +type WAL interface { + Write(bytes []byte) error + Contains(i uint32) bool + Read(i uint32) ([]byte, error) +} + type MempoolInfo struct { TotalPool int ReadyCounter int @@ -206,6 +211,26 @@ type ConsensusInfo struct { TimerTick int } +type ConsensusWorkflowStatus interface { + IsStateReceived() bool + IsBatchProposalSent() bool + IsConsensusBatchKnown() bool + IsVMStarted() bool + IsVMResultSigned() bool + IsTransactionFinalized() bool + IsTransactionPosted() bool + IsTransactionSeen() bool + IsInProgress() bool + GetBatchProposalSentTime() time.Time + GetConsensusBatchKnownTime() time.Time + GetVMStartedTime() time.Time + GetVMResultSignedTime() time.Time + GetTransactionFinalizedTime() time.Time + GetTransactionPostedTime() time.Time + GetTransactionSeenTime() time.Time + GetCompletedTime() time.Time +} + type ReadyListRecord struct { Request iscp.Request Seen map[uint16]bool @@ -221,8 +246,8 @@ type CommitteeInfo struct { type PeerStatus struct { Index int - PeeringID string - IsSelf bool + PubKey *ed25519.PublicKey + NetID string Connected bool } diff --git a/packages/chain/chainimpl/chainimpl.go b/packages/chain/chainimpl/chainimpl.go index c1a72b1686..639613b32e 100644 --- a/packages/chain/chainimpl/chainimpl.go +++ b/packages/chain/chainimpl/chainimpl.go @@ -7,6 +7,7 @@ import ( "sync" "time" + "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/hive.go/events" "github.com/iotaledger/hive.go/kvstore" "github.com/iotaledger/hive.go/logger" @@ -26,18 +27,21 @@ import ( "github.com/iotaledger/wasp/packages/state" "github.com/iotaledger/wasp/packages/util/pipe" "github.com/iotaledger/wasp/packages/vm/core/blocklog" + "github.com/iotaledger/wasp/packages/vm/core/governance" "github.com/iotaledger/wasp/packages/vm/processors" + "github.com/iotaledger/wasp/packages/vm/viewcontext" "go.uber.org/atomic" ) const maxMsgBuffer = 1000 var ( - _ chain.Chain = &chainObj{} - _ chain.ChainCore = &chainObj{} - _ chain.ChainEntry = &chainObj{} - _ chain.ChainRequests = &chainObj{} - _ chain.ChainMetrics = &chainObj{} + _ chain.Chain = &chainObj{} + _ chain.ChainCore = &chainObj{} + _ chain.ChainEntry = &chainObj{} + _ chain.ChainRequests = &chainObj{} + _ chain.ChainMetrics = &chainObj{} + _ map[ed25519.PublicKey]bool // We rely on value comparison on the pubkeys, just assert that here. ) type chainObj struct { @@ -55,10 +59,8 @@ type chainObj struct { log *logger.Logger nodeConn chain.ChainNodeConnection db kvstore.KVStore - peerNetworkConfig registry.PeerNetworkConfigProvider netProvider peering.NetworkProvider dksProvider registry.DKShareRegistryProvider - committeeRegistry registry.CommitteeRegistryProvider blobProvider registry.BlobCache eventRequestProcessed *events.Event eventChainTransition *events.Event @@ -66,8 +68,9 @@ type chainObj struct { receiveChainPeerMessagesAttachID interface{} detachFromCommitteePeerMessagesFun func() chainPeers peering.PeerDomainProvider + candidateNodes []*governance.AccessNodeInfo offLedgerReqsAcksMutex sync.RWMutex - offLedgerReqsAcks map[iscp.RequestID][]string + offLedgerReqsAcks map[iscp.RequestID][]*ed25519.PublicKey offledgerBroadcastUpToNPeers int offledgerBroadcastInterval time.Duration pullMissingRequestsFromCommittee bool @@ -79,6 +82,7 @@ type chainObj struct { missingRequestIDsPeerMsgPipe pipe.Pipe missingRequestPeerMsgPipe pipe.Pipe timerTickMsgPipe pipe.Pipe + wal chain.WAL } type committeeStruct struct { @@ -90,43 +94,41 @@ func NewChain( chainID *iscp.ChainID, log *logger.Logger, nc chain.NodeConnection, - peerNetConfig registry.PeerNetworkConfigProvider, db kvstore.KVStore, netProvider peering.NetworkProvider, dksProvider registry.DKShareRegistryProvider, - committeeRegistry registry.CommitteeRegistryProvider, blobProvider registry.BlobCache, processorConfig *processors.Config, offledgerBroadcastUpToNPeers int, offledgerBroadcastInterval time.Duration, pullMissingRequestsFromCommittee bool, chainMetrics metrics.ChainMetrics, + wal chain.WAL, ) chain.Chain { log.Debugf("creating chain object for %s", chainID.String()) chainLog := log.Named(chainID.Base58()[:6] + ".") chainStateSync := coreutil.NewChainStateSync() ret := &chainObj{ - mempool: mempool.New(state.NewOptimisticStateReader(db, chainStateSync), blobProvider, chainLog, chainMetrics), - procset: processors.MustNew(processorConfig), - chainID: chainID, - log: chainLog, - nodeConn: nodeconnimpl.NewChainNodeConnection(chainID, nc, chainLog), - db: db, - chainStateSync: chainStateSync, - stateReader: state.NewOptimisticStateReader(db, chainStateSync), - peerNetworkConfig: peerNetConfig, - netProvider: netProvider, - dksProvider: dksProvider, - committeeRegistry: committeeRegistry, - blobProvider: blobProvider, + mempool: mempool.New(state.NewOptimisticStateReader(db, chainStateSync), blobProvider, chainLog, chainMetrics), + procset: processors.MustNew(processorConfig), + chainID: chainID, + log: chainLog, + nodeConn: nodeconnimpl.NewChainNodeConnection(chainID, nc, chainLog), + db: db, + chainStateSync: chainStateSync, + stateReader: state.NewOptimisticStateReader(db, chainStateSync), + netProvider: netProvider, + dksProvider: dksProvider, + blobProvider: blobProvider, eventRequestProcessed: events.NewEvent(func(handler interface{}, params ...interface{}) { handler.(func(_ iscp.RequestID))(params[0].(iscp.RequestID)) }), eventChainTransition: events.NewEvent(func(handler interface{}, params ...interface{}) { handler.(func(_ *chain.ChainTransitionEventData))(params[0].(*chain.ChainTransitionEventData)) }), - offLedgerReqsAcks: make(map[iscp.RequestID][]string), + candidateNodes: make([]*governance.AccessNodeInfo, 0), + offLedgerReqsAcks: make(map[iscp.RequestID][]*ed25519.PublicKey), offledgerBroadcastUpToNPeers: offledgerBroadcastUpToNPeers, offledgerBroadcastInterval: offledgerBroadcastInterval, pullMissingRequestsFromCommittee: pullMissingRequestsFromCommittee, @@ -138,16 +140,25 @@ func NewChain( missingRequestIDsPeerMsgPipe: pipe.NewLimitInfinitePipe(maxMsgBuffer), missingRequestPeerMsgPipe: pipe.NewLimitInfinitePipe(maxMsgBuffer), timerTickMsgPipe: pipe.NewLimitInfinitePipe(1), + wal: wal, } ret.committee.Store(&committeeStruct{}) var err error - ret.chainPeers, err = netProvider.PeerDomain(chainID.Array(), peerNetConfig.Neighbors()) + chainPeerNodes := []*ed25519.PublicKey{netProvider.Self().PubKey()} + ret.chainPeers, err = netProvider.PeerDomain(chainID.Array(), chainPeerNodes) if err != nil { - log.Errorf("NewChain: %v", err) + log.Errorf("NewChain: unable to create chainPeers domain: %v", err) + return nil + } + stateMgrDomain, err := statemgr.NewDomainWithFallback(chainID.Array(), netProvider, log.Named("sm")) + if err != nil { + log.Errorf("NewChain: unable to create stateMgr.fallbackPeers domain: %v", err) return nil } - ret.stateMgr = statemgr.New(db, ret, ret.chainPeers, ret.nodeConn, chainMetrics) + + ret.stateMgr = statemgr.New(db, ret, stateMgrDomain, ret.nodeConn, chainMetrics, wal) + ret.stateMgr.SetChainPeers(chainPeerNodes) ret.eventChainTransitionClosure = events.NewClosure(ret.processChainTransition) ret.eventChainTransition.Attach(ret.eventChainTransitionClosure) @@ -183,7 +194,7 @@ func (c *chainObj) receiveCommitteePeerMessages(peerMsg *peering.PeerMessageGrou } c.EnqueueMissingRequestIDsMsg(&messages.MissingRequestIDsMsgIn{ MissingRequestIDsMsg: *msg, - SenderNetID: peerMsg.SenderNetID, + SenderPubKey: peerMsg.SenderPubKey, }) } @@ -197,7 +208,7 @@ func (c *chainObj) receiveChainPeerMessages(peerMsg *peering.PeerMessageIn) { } c.EnqueueOffLedgerRequestMsg(&messages.OffLedgerRequestMsgIn{ OffLedgerRequestMsg: *msg, - SenderNetID: peerMsg.SenderNetID, + SenderPubKey: peerMsg.SenderPubKey, }) case chain.PeerMsgTypeRequestAck: msg, err := messages.NewRequestAckMsg(peerMsg.MsgData) @@ -207,7 +218,7 @@ func (c *chainObj) receiveChainPeerMessages(peerMsg *peering.PeerMessageIn) { } c.EnqueueRequestAckMsg(&messages.RequestAckMsgIn{ RequestAckMsg: *msg, - SenderNetID: peerMsg.SenderNetID, + SenderPubKey: peerMsg.SenderPubKey, }) case chain.PeerMsgTypeMissingRequest: msg, err := messages.NewMissingRequestMsg(peerMsg.MsgData) @@ -261,6 +272,8 @@ func (c *chainObj) processChainTransition(msg *chain.ChainTransitionEventData) { chain.LogStateTransition(msg, reqids, c.log) c.mempoolLastCleanedIndex = stateIndex + c.updateChainNodes(stateIndex) + c.chainMetrics.CurrentStateIndex(stateIndex) } else { c.log.Debugf("processChainTransition state %d: output %s is governance updated; state hash %s", stateIndex, iscp.OID(msg.ChainOutput.ID()), msg.VirtualState.StateCommitment().String()) @@ -275,6 +288,54 @@ func (c *chainObj) processChainTransition(msg *chain.ChainTransitionEventData) { c.log.Debugf("processChainTransition completed: state index: %d, state hash: %s", stateIndex, msg.VirtualState.StateCommitment().String()) } +func (c *chainObj) updateChainNodes(stateIndex uint32) { + c.log.Debugf("updateChainNodes, stateIndex=%v", stateIndex) + govAccessNodes := make([]ed25519.PublicKey, 0) + govCandidateNodes := make([]*governance.AccessNodeInfo, 0) + if stateIndex > 0 { + res, err := viewcontext.NewFromChain(c).CallView( + governance.Contract.Hname(), + governance.FuncGetChainNodes.Hname(), + governance.GetChainNodesRequest{}.AsDict(), + ) + if err != nil { + c.log.Panicf("unable to read the governance contract state: %v", err) + } + govResponse := governance.NewGetChainNodesResponseFromDict(res) + govAccessNodes = govResponse.AccessNodes + govCandidateNodes = govResponse.AccessNodeCandidates + } + + // + // Collect the new set of access nodes in the communication domain. + // They include the committee nodes as well as the explicitly set access nodes. + newMembers := make(map[ed25519.PublicKey]bool) + newMembers[*c.netProvider.Self().PubKey()] = true + cmt := c.getCommittee() + if cmt != nil { + for _, cm := range cmt.DKShare().NodePubKeys { + newMembers[*cm] = true + } + } + for _, newAccessNode := range govAccessNodes { + newMembers[newAccessNode] = true + } + + // + // Pass it to the underlying domain to make a graceful update. + newMemberList := make([]*ed25519.PublicKey, 0) + for pubKey := range newMembers { + pubKeyCopy := pubKey + newMemberList = append(newMemberList, &pubKeyCopy) + } + c.chainPeers.UpdatePeers(newMemberList) + c.stateMgr.SetChainPeers(newMemberList) + + // + // Remember the candidate nodes as well (as a cache). + c.candidateNodes = govCandidateNodes +} + func (c *chainObj) publishNewBlockEvents(blockIndex uint32) { if blockIndex == 0 { // don't run on state #0, root contracts not initialized yet. @@ -313,4 +374,7 @@ func (c *chainObj) setCommittee(cmt chain.Committee) { cmt: cmt, }) } + if stateIndex, err := c.stateReader.BlockIndex(); err != nil { + c.updateChainNodes(stateIndex) + } } diff --git a/packages/chain/chainimpl/chainimpl_test.go b/packages/chain/chainimpl/chainimpl_test.go index 8670c53fe9..0273e02427 100644 --- a/packages/chain/chainimpl/chainimpl_test.go +++ b/packages/chain/chainimpl/chainimpl_test.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package chainimpl import ( diff --git a/packages/chain/chainimpl/core.go b/packages/chain/chainimpl/core.go index 3c05d06d99..5c41d236ba 100644 --- a/packages/chain/chainimpl/core.go +++ b/packages/chain/chainimpl/core.go @@ -11,7 +11,9 @@ import ( "github.com/iotaledger/wasp/packages/chain" "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/iscp/coreutil" + "github.com/iotaledger/wasp/packages/peering" "github.com/iotaledger/wasp/packages/state" + "github.com/iotaledger/wasp/packages/vm/core/governance" "github.com/iotaledger/wasp/packages/vm/processors" ) @@ -54,6 +56,14 @@ func (c *chainObj) GetStateReader() state.OptimisticStateReader { return state.NewOptimisticStateReader(c.db, c.chainStateSync) } +func (c *chainObj) GetChainNodes() []peering.PeerStatusProvider { + return c.chainPeers.PeerStatus() +} + +func (c *chainObj) GetCandidateNodes() []*governance.AccessNodeInfo { + return c.candidateNodes +} + func (c *chainObj) Log() *logger.Logger { return c.log } diff --git a/packages/chain/chainimpl/eventproc.go b/packages/chain/chainimpl/eventproc.go index 59bc90b82b..fd83d22a06 100644 --- a/packages/chain/chainimpl/eventproc.go +++ b/packages/chain/chainimpl/eventproc.go @@ -4,9 +4,11 @@ package chainimpl import ( + "errors" "time" "github.com/iotaledger/goshimmer/packages/ledgerstate" + "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/wasp/packages/chain" "github.com/iotaledger/wasp/packages/chain/committee" "github.com/iotaledger/wasp/packages/chain/consensus" @@ -16,7 +18,7 @@ import ( "github.com/iotaledger/wasp/packages/iscp/request" "github.com/iotaledger/wasp/packages/peering" "github.com/iotaledger/wasp/packages/registry" - "github.com/iotaledger/wasp/packages/util" + "github.com/iotaledger/wasp/packages/tcrypto" "golang.org/x/xerrors" ) @@ -106,7 +108,7 @@ func (c *chainObj) EnqueueLedgerState(chainOutput *ledgerstate.AliasOutput, time // handleLedgerState processes the only chain output which exists on the chain's address // If necessary, it creates/changes/rotates committee object func (c *chainObj) handleLedgerState(msg *messages.StateMsg) { - c.log.Debugf("handleLedgerState message received, stateIndex: %d, stateAddr: %s, state transition: %v, timestamp: ", + c.log.Debugf("handleLedgerState message received, stateIndex: %d, stateAddr: %s, state transition: %v, timestamp: %v", msg.ChainOutput.GetStateIndex(), msg.ChainOutput.GetStateAddress().Base58(), !msg.ChainOutput.GetIsGovernanceUpdated(), msg.Timestamp) sh, err := hashing.HashValueFromBytes(msg.ChainOutput.GetStateData()) if err != nil { @@ -138,9 +140,11 @@ func (c *chainObj) rotateCommitteeIfNeeded(anchorOutput *ledgerstate.AliasOutput if !anchorOutput.GetIsGovernanceUpdated() { return xerrors.Errorf("rotateCommitteeIfNeeded: inconsistency. Governance transition expected... New output: %s", anchorOutput.String()) } - rec, err := c.getOwnCommitteeRecord(anchorOutput.GetStateAddress()) + dkShare, err := c.getChainDKShare(anchorOutput.GetStateAddress()) if err != nil { - return xerrors.Errorf("rotateCommitteeIfNeeded: %w", err) + if !errors.Is(err, registry.ErrDKShareNotFound) { + return xerrors.Errorf("rotateCommitteeIfNeeded: unable to load dkShare: %w", err) + } } // rotation needed // close current in any case @@ -150,9 +154,9 @@ func (c *chainObj) rotateCommitteeIfNeeded(anchorOutput *ledgerstate.AliasOutput c.consensus.Close() c.setCommittee(nil) c.consensus = nil - if rec != nil { + if dkShare != nil { // create new if committee record is available - if err = c.createNewCommitteeAndConsensus(rec); err != nil { + if err = c.createNewCommitteeAndConsensus(dkShare); err != nil { return xerrors.Errorf("rotateCommitteeIfNeeded: creating committee and consensus: %v", err) } } @@ -161,63 +165,64 @@ func (c *chainObj) rotateCommitteeIfNeeded(anchorOutput *ledgerstate.AliasOutput func (c *chainObj) createCommitteeIfNeeded(anchorOutput *ledgerstate.AliasOutput) error { // check if I am in the committee - rec, err := c.getOwnCommitteeRecord(anchorOutput.GetStateAddress()) + dkShare, err := c.getChainDKShare(anchorOutput.GetStateAddress()) if err != nil { - return xerrors.Errorf("rotateCommitteeIfNeeded: %w", err) + if errors.Is(err, registry.ErrDKShareNotFound) { + return nil + } + return xerrors.Errorf("createCommitteeIfNeeded: unable to load dkShare: %w", err) } - if rec != nil { + if dkShare != nil { // create if record is present - if err = c.createNewCommitteeAndConsensus(rec); err != nil { - return xerrors.Errorf("rotateCommitteeIfNeeded: creating committee and consensus: %v", err) + if err = c.createNewCommitteeAndConsensus(dkShare); err != nil { + return xerrors.Errorf("createCommitteeIfNeeded: creating committee and consensus: %w", err) } } return nil } -func (c *chainObj) getOwnCommitteeRecord(addr ledgerstate.Address) (*registry.CommitteeRecord, error) { - rec, err := c.committeeRegistry.GetCommitteeRecord(addr) - if err != nil { - return nil, xerrors.Errorf("createCommitteeIfNeeded: reading committee record: %v", err) - } - if rec == nil { - // committee record wasn't found in th registry, I am not the part of the committee - return nil, nil - } +func (c *chainObj) getChainDKShare(addr ledgerstate.Address) (*tcrypto.DKShare, error) { + // // just in case check if I am among committee nodes // should not happen - if !util.StringInList(c.peerNetworkConfig.OwnNetID(), rec.Nodes) { - return nil, xerrors.Errorf("createCommitteeIfNeeded: I am not among nodes of the committee record. Inconsistency") + selfPubKey := c.netProvider.Self().PubKey() + cmtDKShare, err := c.dksProvider.LoadDKShare(addr) + if err != nil { + return nil, err + } + for i := range cmtDKShare.NodePubKeys { + if *cmtDKShare.NodePubKeys[i] == *selfPubKey { + return cmtDKShare, nil + } } - return rec, nil + return nil, xerrors.Errorf("createCommitteeIfNeeded: I am not among nodes of the committee record. Inconsistency") } -func (c *chainObj) createNewCommitteeAndConsensus(cmtRec *registry.CommitteeRecord) error { +func (c *chainObj) createNewCommitteeAndConsensus(dkShare *tcrypto.DKShare) error { c.log.Debugf("createNewCommitteeAndConsensus: creating a new committee...") if c.detachFromCommitteePeerMessagesFun != nil { c.detachFromCommitteePeerMessagesFun() } cmt, cmtPeerGroup, err := committee.New( - cmtRec, + dkShare, c.chainID, c.netProvider, - c.peerNetworkConfig, - c.dksProvider, c.log, ) if err != nil { c.setCommittee(nil) return xerrors.Errorf("createNewCommitteeAndConsensus: failed to create committee object for state address %s: %w", - cmtRec.Address.Base58(), err) + dkShare.Address.Base58(), err) } attachID := cmtPeerGroup.Attach(peering.PeerMessageReceiverChain, c.receiveCommitteePeerMessages) c.detachFromCommitteePeerMessagesFun = func() { cmtPeerGroup.Detach(attachID) } c.log.Debugf("creating new consensus object...") - c.consensus = consensus.New(c, c.mempool, cmt, cmtPeerGroup, c.nodeConn, c.pullMissingRequestsFromCommittee, c.chainMetrics) + c.consensus = consensus.New(c, c.mempool, cmt, cmtPeerGroup, c.nodeConn, c.pullMissingRequestsFromCommittee, c.chainMetrics, c.wal) c.setCommittee(cmt) - c.log.Infof("NEW COMMITTEE OF VALIDATORS has been initialized for the state address %s", cmtRec.Address.Base58()) + c.log.Infof("NEW COMMITTEE OF VALIDATORS has been initialized for the state address %s", dkShare.Address.Base58()) return nil } @@ -227,8 +232,8 @@ func (c *chainObj) EnqueueOffLedgerRequestMsg(msg *messages.OffLedgerRequestMsgI } func (c *chainObj) handleOffLedgerRequestMsg(msg *messages.OffLedgerRequestMsgIn) { - c.log.Debugf("handleOffLedgerRequestMsg message received from peer %v, reqID: %s", msg.SenderNetID, msg.Req.ID().Base58()) - c.sendRequestAcknowledgementMsg(msg.Req.ID(), msg.SenderNetID) + c.log.Debugf("handleOffLedgerRequestMsg message received from peer %v, reqID: %s", msg.SenderPubKey.String(), msg.Req.ID().Base58()) + c.sendRequestAcknowledgementMsg(msg.Req.ID(), msg.SenderPubKey) if !c.isRequestValid(msg.Req) { // this means some node broadcasted an invalid request (bad chainID or signature) @@ -244,13 +249,13 @@ func (c *chainObj) handleOffLedgerRequestMsg(msg *messages.OffLedgerRequestMsgIn c.log.Debugf("handleOffLedgerRequestMsg message added to mempool and broadcasted: reqID: %s", msg.Req.ID().Base58()) } -func (c *chainObj) sendRequestAcknowledgementMsg(reqID iscp.RequestID, peerID string) { - c.log.Debugf("sendRequestAcknowledgementMsg: reqID: %s, peerID: %s", reqID.Base58(), peerID) - if peerID == "" { +func (c *chainObj) sendRequestAcknowledgementMsg(reqID iscp.RequestID, peerPubKey *ed25519.PublicKey) { + if peerPubKey == nil { return } + c.log.Debugf("sendRequestAcknowledgementMsg: reqID: %s, peerID: %s", reqID.Base58(), peerPubKey.String()) msg := &messages.RequestAckMsg{ReqID: &reqID} - c.chainPeers.SendMsgByNetID(peerID, peering.PeerMessageReceiverChain, chain.PeerMsgTypeRequestAck, msg.Bytes()) + c.chainPeers.SendMsgByPubKey(peerPubKey, peering.PeerMessageReceiverChain, chain.PeerMsgTypeRequestAck, msg.Bytes()) } func (c *chainObj) isRequestValid(req *request.OffLedger) bool { @@ -264,18 +269,18 @@ func (c *chainObj) broadcastOffLedgerRequest(req *request.OffLedger) { Req: req, } cmt := c.getCommittee() - getPeerIDs := c.chainPeers.GetRandomPeers + getPeerPubKeys := c.chainPeers.GetRandomOtherPeers if cmt != nil { - getPeerIDs = cmt.GetRandomValidators + getPeerPubKeys = cmt.GetRandomValidators } - sendMessage := func(ackPeers []string) { - peerIDs := getPeerIDs(c.offledgerBroadcastUpToNPeers) - for _, peerID := range peerIDs { - if shouldSendToPeer(peerID, ackPeers) { - c.log.Debugf("sending offledger request ID: reqID: %s, peerID: %s", req.ID().Base58(), peerID) - c.chainPeers.SendMsgByNetID(peerID, peering.PeerMessageReceiverChain, chain.PeerMsgTypeOffLedgerRequest, msg.Bytes()) + sendMessage := func(ackPeers []*ed25519.PublicKey) { + peerPubKeys := getPeerPubKeys(c.offledgerBroadcastUpToNPeers) + for _, peerPubKey := range peerPubKeys { + if shouldSendToPeer(peerPubKey, ackPeers) { + c.log.Debugf("sending offledger request ID: reqID: %s, peerPubKey: %s", req.ID().Base58(), peerPubKey.String()) + c.chainPeers.SendMsgByPubKey(peerPubKey, peering.PeerMessageReceiverChain, chain.PeerMsgTypeOffLedgerRequest, msg.Bytes()) } } } @@ -308,9 +313,9 @@ func (c *chainObj) broadcastOffLedgerRequest(req *request.OffLedger) { }() } -func shouldSendToPeer(peerID string, ackPeers []string) bool { +func shouldSendToPeer(peerPubKey *ed25519.PublicKey, ackPeers []*ed25519.PublicKey) bool { for _, p := range ackPeers { - if p == peerID { + if *p == *peerPubKey { return false } } @@ -323,10 +328,10 @@ func (c *chainObj) EnqueueRequestAckMsg(msg *messages.RequestAckMsgIn) { } func (c *chainObj) handleRequestAckPeerMsg(msg *messages.RequestAckMsgIn) { - c.log.Debugf("handleRequestAckPeerMsg message received from peer %v, reqID: %s", msg.SenderNetID, msg.ReqID.Base58()) + c.log.Debugf("handleRequestAckPeerMsg message received from peer %v, reqID: %s", msg.SenderPubKey.String(), msg.ReqID.Base58()) c.offLedgerReqsAcksMutex.Lock() defer c.offLedgerReqsAcksMutex.Unlock() - c.offLedgerReqsAcks[*msg.ReqID] = append(c.offLedgerReqsAcks[*msg.ReqID], msg.SenderNetID) + c.offLedgerReqsAcks[*msg.ReqID] = append(c.offLedgerReqsAcks[*msg.ReqID], msg.SenderPubKey) c.chainMetrics.CountRequestAckMessages() c.log.Debugf("handleRequestAckPeerMsg comleted: reqID: %s", msg.ReqID.Base58()) } @@ -337,7 +342,7 @@ func (c *chainObj) EnqueueMissingRequestIDsMsg(msg *messages.MissingRequestIDsMs } func (c *chainObj) handleMissingRequestIDsMsg(msg *messages.MissingRequestIDsMsgIn) { - c.log.Debugf("handleMissingRequestIDsMsg message received from peer %v, number of reqIDs: %v", msg.SenderNetID, len(msg.IDs)) + c.log.Debugf("handleMissingRequestIDsMsg message received from peer %v, number of reqIDs: %v", msg.SenderPubKey.String(), len(msg.IDs)) if !c.pullMissingRequestsFromCommittee { c.log.Warnf("handleMissingRequestIDsMsg ignored: pull from committee disabled") return @@ -346,8 +351,8 @@ func (c *chainObj) handleMissingRequestIDsMsg(msg *messages.MissingRequestIDsMsg c.log.Debugf("handleMissingRequestIDsMsg: finding reqID %s...", reqID.Base58()) if req := c.mempool.GetRequest(reqID); req != nil { resultMsg := &messages.MissingRequestMsg{Request: req} - c.chainPeers.SendMsgByNetID(msg.SenderNetID, peering.PeerMessageReceiverChain, chain.PeerMsgTypeMissingRequest, resultMsg.Bytes()) - c.log.Warnf("handleMissingRequestIDsMsg: reqID %s sent to %v.", reqID.Base58(), msg.SenderNetID) + c.chainPeers.SendMsgByPubKey(msg.SenderPubKey, peering.PeerMessageReceiverChain, chain.PeerMsgTypeMissingRequest, resultMsg.Bytes()) + c.log.Warnf("handleMissingRequestIDsMsg: reqID %s sent to %v.", reqID.Base58(), msg.SenderPubKey.String()) } else { c.log.Warnf("handleMissingRequestIDsMsg: reqID %s not found.", reqID.Base58()) } diff --git a/packages/chain/chainimpl/messages.go b/packages/chain/chainimpl/messages.go index 90e8ca5228..77a9452bf3 100644 --- a/packages/chain/chainimpl/messages.go +++ b/packages/chain/chainimpl/messages.go @@ -3,22 +3,7 @@ package chainimpl -import ( - "github.com/iotaledger/wasp/packages/iscp" - "github.com/iotaledger/wasp/packages/iscp/request" -) - // DismissChainMsg sent by component to the chain core in case of major setback type DismissChainMsg struct { Reason string } - -type OffLedgerRequestMsg struct { - Req *request.OffLedger - SenderNetID string -} - -type RequestAckMsg struct { - ReqID *iscp.RequestID - SenderNetID string -} diff --git a/packages/chain/chainimpl/metrics.go b/packages/chain/chainimpl/metrics.go index 650f96769d..2b5f338213 100644 --- a/packages/chain/chainimpl/metrics.go +++ b/packages/chain/chainimpl/metrics.go @@ -5,9 +5,17 @@ package chainimpl import ( + "github.com/iotaledger/wasp/packages/chain" "github.com/iotaledger/wasp/packages/metrics/nodeconnmetrics" ) func (c *chainObj) GetNodeConnectionMetrics() nodeconnmetrics.NodeConnectionMessagesMetrics { return c.nodeConn.GetMetrics() } + +func (c *chainObj) GetConsensusWorkflowStatus() chain.ConsensusWorkflowStatus { + if c.consensus == nil { + return nil + } + return c.consensus.GetWorkflowStatus() +} diff --git a/packages/chain/committee/committee.go b/packages/chain/committee/committee.go index 027422dbda..127c38d4f4 100644 --- a/packages/chain/committee/committee.go +++ b/packages/chain/committee/committee.go @@ -8,12 +8,12 @@ import ( "time" "github.com/iotaledger/goshimmer/packages/ledgerstate" + "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/wasp/packages/chain" "github.com/iotaledger/wasp/packages/chain/consensus/commonsubset" "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/peering" - "github.com/iotaledger/wasp/packages/registry" "github.com/iotaledger/wasp/packages/tcrypto" "github.com/iotaledger/wasp/packages/util" "go.uber.org/atomic" @@ -23,7 +23,6 @@ import ( type committee struct { isReady *atomic.Bool address ledgerstate.Address - peerConfig registry.PeerNetworkConfigProvider validatorNodes peering.GroupProvider acsRunner chain.AsynchronousCommonSubsetRunner size uint16 @@ -38,28 +37,19 @@ var _ chain.Committee = &committee{} const waitReady = false func New( - cmtRec *registry.CommitteeRecord, + dkShare *tcrypto.DKShare, chainID *iscp.ChainID, netProvider peering.NetworkProvider, - peerConfig registry.PeerNetworkConfigProvider, - dksProvider registry.DKShareRegistryProvider, log *logger.Logger, acsRunner ...chain.AsynchronousCommonSubsetRunner, // Only for mocking. ) (chain.Committee, peering.GroupProvider, error) { - // load DKShare from the registry - dkshare, err := dksProvider.LoadDKShare(cmtRec.Address) - if err != nil { - return nil, nil, xerrors.Errorf("NewCommittee: failed loading DKShare for address %s: %w", cmtRec.Address.Base58(), err) - } - if dkshare.Index == nil { - return nil, nil, xerrors.Errorf("NewCommittee: wrong DKShare record for address %s: %w", cmtRec.Address.Base58(), err) - } - if err := checkValidatorNodeIDs(peerConfig, dkshare.N, *dkshare.Index, cmtRec.Nodes); err != nil { - return nil, nil, xerrors.Errorf("NewCommittee: %w", err) + var err error + if dkShare.Index == nil { + return nil, nil, xerrors.Errorf("NewCommittee: wrong DKShare record for address %s: nil index", dkShare.Address.Base58()) } // peerGroupID is calculated by XORing chainID and stateAddr. // It allows to use same statAddr for different chains - peerGroupID := cmtRec.Address.Array() + peerGroupID := dkShare.Address.Array() var chainArr [33]byte if chainID != nil { chainArr = chainID.Array() @@ -68,19 +58,18 @@ func New( peerGroupID[i] ^= chainArr[i] } var peers peering.GroupProvider - if peers, err = netProvider.PeerGroup(peerGroupID, cmtRec.Nodes); err != nil { - return nil, nil, xerrors.Errorf("NewCommittee: failed to create peer group for committee: %+v: %w", cmtRec.Nodes, err) + if peers, err = netProvider.PeerGroup(peerGroupID, dkShare.NodePubKeys); err != nil { + return nil, nil, xerrors.Errorf("NewCommittee: failed to create peer group for committee: %+v: %w", dkShare.NodePubKeys, err) } - log.Debugf("NewCommittee: peer group: %+v", cmtRec.Nodes) + log.Debugf("NewCommittee: peer group: %+v", dkShare.NodePubKeys) ret := &committee{ isReady: atomic.NewBool(false), - address: cmtRec.Address, + address: dkShare.Address, validatorNodes: peers, - peerConfig: peerConfig, - size: dkshare.N, - quorum: dkshare.T, - ownIndex: *dkshare.Index, - dkshare: dkshare, + size: dkShare.N, + quorum: dkShare.T, + ownIndex: *dkShare.Index, + dkshare: dkShare, log: log, } if len(acsRunner) > 0 { @@ -91,7 +80,7 @@ func New( ret.acsRunner = commonsubset.NewCommonSubsetCoordinator( netProvider, ret.validatorNodes, - dkshare, + dkShare, log, ) } @@ -158,17 +147,11 @@ func (c *committee) QuorumIsAlive(quorum ...uint16) bool { func (c *committee) PeerStatus() []*chain.PeerStatus { ret := make([]*chain.PeerStatus, 0) for i, peer := range c.validatorNodes.AllNodes() { - isSelf := peer == nil || peer.NetID() == c.peerConfig.OwnNetID() status := &chain.PeerStatus{ - Index: int(i), - IsSelf: isSelf, - } - if isSelf { - status.PeeringID = c.peerConfig.OwnNetID() - status.Connected = true - } else { - status.PeeringID = peer.NetID() - status.Connected = peer.IsAlive() + Index: int(i), + NetID: peer.NetID(), + PubKey: peer.PubKey(), + Connected: peer.IsAlive(), } ret = append(ret, status) } @@ -197,44 +180,14 @@ func (c *committee) waitReady(waitReady bool) { c.isReady.Store(true) } -func checkValidatorNodeIDs(cfg registry.PeerNetworkConfigProvider, n, ownIndex uint16, validatorNetIDs []string) error { - if !util.AllDifferentStrings(validatorNetIDs) { - return xerrors.Errorf("checkValidatorNodeIDs: list of validators nodes contains duplicates: %+v", validatorNetIDs) - } - if len(validatorNetIDs) != int(n) { - return xerrors.Errorf("checkValidatorNodeIDs: number of validator nodes must be equal to the N parameter of the committee") - } - if ownIndex >= n { - return xerrors.New("checkValidatorNodeIDs: wrong own validator index") - } - if validatorNetIDs[ownIndex] != cfg.OwnNetID() { - return xerrors.New("checkValidatorNodeIDs: own netID is expected at own validator index") - } - // check if all validator node IDs are among known validatorNodes - allPeers := []string{cfg.OwnNetID()} - allPeers = append(allPeers, cfg.Neighbors()...) - if !util.IsSubset(validatorNetIDs, allPeers) { - return xerrors.Errorf("not all validator nodes are among known neighbors: all peers: %+v, committee: %+v", - allPeers, validatorNetIDs) - } - return nil -} - -func (c *committee) GetOtherValidatorsPeerIDs() []string { - nodes := c.validatorNodes.OtherNodes() - ret := make([]string, len(nodes)) - i := 0 - for _, node := range nodes { - ret[i] = node.NetID() - i++ - } - return ret -} - -func (c *committee) GetRandomValidators(upToN int) []string { - validators := c.GetOtherValidatorsPeerIDs() +func (c *committee) GetRandomValidators(upToN int) []*ed25519.PublicKey { + validators := c.validatorNodes.OtherNodes() if upToN >= len(validators) { - return validators + valPubKeys := make([]*ed25519.PublicKey, 0) + for i := range validators { + valPubKeys = append(valPubKeys, validators[i].PubKey()) + } + return valPubKeys } var b [8]byte @@ -242,10 +195,10 @@ func (c *committee) GetRandomValidators(upToN int) []string { _, _ = rand.Read(seed) permutation := util.NewPermutation16(uint16(len(validators)), seed) permutation.Shuffle(seed) - ret := make([]string, 0) + ret := make([]*ed25519.PublicKey, 0) for len(ret) < upToN { i := permutation.Next() - ret = append(ret, validators[i]) + ret = append(ret, validators[i].PubKey()) } return ret diff --git a/packages/chain/committee/committee_test.go b/packages/chain/committee/committee_test.go index 696af24d72..3839cbdb66 100644 --- a/packages/chain/committee/committee_test.go +++ b/packages/chain/committee/committee_test.go @@ -4,11 +4,9 @@ package committee import ( - "fmt" "testing" "time" - "github.com/iotaledger/wasp/packages/registry" "github.com/iotaledger/wasp/packages/tcrypto" "github.com/iotaledger/wasp/packages/testutil" "github.com/iotaledger/wasp/packages/testutil/testlogger" @@ -22,20 +20,13 @@ func TestCommitteeBasic(t *testing.T) { defer log.Sync() nodeCount := 4 netIDs, identities := testpeers.SetupKeys(uint16(nodeCount)) - stateAddr, dksRegistries := testpeers.SetupDkgPregenerated(t, uint16((len(netIDs)*2)/3+1), netIDs, suite) + stateAddr, dksRegistries := testpeers.SetupDkgPregenerated(t, uint16((len(netIDs)*2)/3+1), identities, suite) nodes, netCloser := testpeers.SetupNet(netIDs, identities, testutil.NewPeeringNetReliable(log), log) net0 := nodes[0] + dks0, err := dksRegistries[0].LoadDKShare(stateAddr) + require.NoError(t, err) - cfg0 := &committeeimplTestConfigProvider{ - ownNetID: netIDs[0], - neighbors: netIDs, - } - - cmtRec := ®istry.CommitteeRecord{ - Address: stateAddr, - Nodes: netIDs, - } - c, _, err := New(cmtRec, nil, net0, cfg0, dksRegistries[0], log) + c, _, err := New(dks0, nil, net0, log) require.NoError(t, err) require.True(t, c.Address().Equals(stateAddr)) require.EqualValues(t, 4, c.Size()) @@ -47,29 +38,3 @@ func TestCommitteeBasic(t *testing.T) { require.False(t, c.IsReady()) require.NoError(t, netCloser.Close()) } - -var _ registry.PeerNetworkConfigProvider = &committeeimplTestConfigProvider{} - -// TODO: should this object be obtained from peering.NetworkProvider? -// Or should registry.PeerNetworkConfigProvider methods methods be part of -// peering.NetworkProvider interface -type committeeimplTestConfigProvider struct { - ownNetID string - neighbors []string -} - -func (p *committeeimplTestConfigProvider) OwnNetID() string { - return p.ownNetID -} - -func (p *committeeimplTestConfigProvider) PeeringPort() int { - return 0 // Anything -} - -func (p *committeeimplTestConfigProvider) Neighbors() []string { - return p.neighbors -} - -func (p *committeeimplTestConfigProvider) String() string { - return fmt.Sprintf("committeeimplPeerConfig( ownNetID: %s, neighbors: %+v )", p.OwnNetID(), p.Neighbors()) -} diff --git a/packages/chain/consensus/action.go b/packages/chain/consensus/action.go index 7dd8db883b..0bba2ca6f3 100644 --- a/packages/chain/consensus/action.go +++ b/packages/chain/consensus/action.go @@ -27,9 +27,9 @@ import ( // takeAction triggers actions whenever relevant func (c *consensus) takeAction() { - if !c.workflow.stateReceived || !c.workflow.inProgress { + if !c.workflow.IsStateReceived() || !c.workflow.IsInProgress() { c.log.Debugf("takeAction skipped: stateReceived: %v, workflow in progress: %v", - c.workflow.stateReceived, c.workflow.inProgress) + c.workflow.IsStateReceived(), c.workflow.IsInProgress()) return } @@ -44,11 +44,11 @@ func (c *consensus) takeAction() { // proposeBatchIfNeeded when non empty ready batch is available is in mempool propose it as a candidate // for the ACS agreement func (c *consensus) proposeBatchIfNeeded() { - if c.workflow.batchProposalSent { + if c.workflow.IsBatchProposalSent() { c.log.Debugf("proposeBatch not needed: batch proposal already sent") return } - if c.workflow.consensusBatchKnown { + if c.workflow.IsConsensusBatchKnown() { c.log.Debugf("proposeBatch not needed: consensus batch already known") return } @@ -78,19 +78,19 @@ func (c *consensus) proposeBatchIfNeeded() { c.log.Infof("proposeBatch: proposed batch len = %d, ACS session ID: %d, state index: %d", len(reqs), c.acsSessionID, c.stateOutput.GetStateIndex()) - c.workflow.batchProposalSent = true + c.workflow.setBatchProposalSent() } // runVMIfNeeded attempts to extract deterministic batch of requests from ACS. // If it succeeds (i.e. all requests are available) and the extracted batch is nonempty, it runs the request func (c *consensus) runVMIfNeeded() { - if !c.workflow.consensusBatchKnown { + if !c.workflow.IsConsensusBatchKnown() { c.log.Debugf("runVM not needed: consensus batch is not known") return } - if c.workflow.vmStarted || c.workflow.vmResultSigned { + if c.workflow.IsVMStarted() || c.workflow.IsVMResultSigned() { c.log.Debugf("runVM not needed: vmStarted %v, vmResultSigned %v", - c.workflow.vmStarted, c.workflow.vmResultSigned) + c.workflow.IsVMStarted(), c.workflow.IsVMResultSigned()) return } if time.Now().Before(c.delayRunVMUntil) { @@ -147,7 +147,7 @@ func (c *consensus) runVMIfNeeded() { "block index", vmTask.ChainInput.GetStateIndex(), "num req", len(vmTask.Requests), ) - c.workflow.vmStarted = true + c.workflow.setVMStarted() vmTask.StartTime = time.Now() c.consensusMetrics.CountVMRuns() go c.vmRunner.Run(vmTask) @@ -252,11 +252,14 @@ func (c *consensus) prepareVMTask(reqs []iscp.Request) *vm.VMTask { } func (c *consensus) broadcastSignedResultIfNeeded() { - if !c.workflow.vmResultSigned { + if !c.workflow.IsVMResultSigned() { c.log.Debugf("broadcastSignedResult not needed: vm result is not signed") return } - if len(c.resultSigAck) >= int(c.committee.Size()-1) { + acksReceived := len(c.resultSigAck) + acksNeeded := int(c.committee.Size() - 1) + if acksReceived >= acksNeeded { + c.log.Debugf("broadcastSignedResult not needed: acks received from %v peers, only %v needed", acksReceived, acksNeeded) return } if time.Now().After(c.delaySendingSignedResult) { @@ -282,11 +285,11 @@ func (c *consensus) broadcastSignedResultIfNeeded() { // the transaction to L1. The deadline por posting is set proportionally to the sequence number (deterministic) // If the node sees the transaction of the L1 before its deadline, it cancels its posting func (c *consensus) checkQuorum() { - if c.workflow.transactionFinalized { + if c.workflow.IsTransactionFinalized() { c.log.Debugf("checkQuorum not needed: transaction already finalized") return } - if !c.workflow.vmResultSigned { + if !c.workflow.IsVMResultSigned() { // only can aggregate signatures if own result is calculated c.log.Debugf("checkQuorum not needed: vm result is not signed") return @@ -341,6 +344,7 @@ func (c *consensus) checkQuorum() { if !chainOutput.GetIsGovernanceUpdated() { // if it is not state controller rotation, sending message to state manager // Otherwise state manager is not notified + c.writeToWAL() chainOutputID := chainOutput.ID() c.chain.StateCandidateToStateManager(c.resultState, chainOutputID) c.log.Debugf("checkQuorum: StateCandidateMsg sent for state index %v, approving output ID %v", @@ -360,13 +364,23 @@ func (c *consensus) checkQuorum() { } else { c.log.Debugf("checkQuorum: finalized tx %s, iAmContributor: false", tx.ID().Base58()) } - c.workflow.transactionFinalized = true + c.workflow.setTransactionFinalized() c.pullInclusionStateDeadline = time.Now() } +func (c *consensus) writeToWAL() { + block, err := c.resultState.ExtractBlock() + if err == nil { + err = c.wal.Write(block.Bytes()) + if err != nil { + c.log.Debugf("Error writing block to wal: %v", err) + } + } +} + // postTransactionIfNeeded posts a finalized transaction upon deadline unless it was evidenced on L1 before the deadline. func (c *consensus) postTransactionIfNeeded() { - if !c.workflow.transactionFinalized { + if !c.workflow.IsTransactionFinalized() { c.log.Debugf("postTransaction not needed: transaction is not finalized") return } @@ -375,11 +389,11 @@ func (c *consensus) postTransactionIfNeeded() { c.log.Debugf("postTransaction not needed: i am not a contributor") return } - if c.workflow.transactionPosted { + if c.workflow.IsTransactionPosted() { c.log.Debugf("postTransaction not needed: transaction already posted") return } - if c.workflow.transactionSeen { + if c.workflow.IsTransactionSeen() { c.log.Debugf("postTransaction not needed: transaction already seen") return } @@ -389,18 +403,18 @@ func (c *consensus) postTransactionIfNeeded() { } go c.nodeConn.PostTransaction(c.finalTx) - c.workflow.transactionPosted = true // TODO: Fix it, retries should be in place for robustness. + c.workflow.setTransactionPosted() // TODO: Fix it, retries should be in place for robustness. c.log.Infof("postTransaction: POSTED TRANSACTION: %s, number of inputs: %d, outputs: %d", c.finalTx.ID().Base58(), len(c.finalTx.Essence().Inputs()), len(c.finalTx.Essence().Outputs())) } // pullInclusionStateIfNeeded periodic pull to know the inclusions state of the transaction. Note that pulling // starts immediately after finalization of the transaction, not after posting it func (c *consensus) pullInclusionStateIfNeeded() { - if !c.workflow.transactionFinalized { + if !c.workflow.IsTransactionFinalized() { c.log.Debugf("pullInclusionState not needed: transaction is not finalized") return } - if c.workflow.transactionSeen { + if c.workflow.IsTransactionSeen() { c.log.Debugf("pullInclusionState not needed: transaction already seen") return } @@ -453,7 +467,7 @@ func (c *consensus) receiveACS(values [][]byte, sessionID uint64) { c.log.Debugf("receiveACS: session id missmatch: expected %v, received %v", c.acsSessionID, sessionID) return } - if c.workflow.consensusBatchKnown { + if c.workflow.IsConsensusBatchKnown() { // should not happen c.log.Debugf("receiveACS: consensus batch already known (should not happen)") return @@ -549,7 +563,7 @@ func (c *consensus) receiveACS(values [][]byte, sessionID uint64) { c.myContributionSeqNumber = myContributionSeqNumber c.contributors = contributors - c.workflow.consensusBatchKnown = true + c.workflow.setConsensusBatchKnown() if c.iAmContributor { c.log.Debugf("receiveACS: ACS received. Contributors to ACS: %+v, iAmContributor: true, seqnr: %d, reqs: %+v", @@ -563,8 +577,8 @@ func (c *consensus) receiveACS(values [][]byte, sessionID uint64) { } func (c *consensus) processInclusionState(msg *messages.InclusionStateMsg) { - if !c.workflow.transactionFinalized { - c.log.Debugf("processInclusionState: transaction finalized -> skipping.") + if !c.workflow.IsTransactionFinalized() { + c.log.Debugf("processInclusionState: transaction not finalized -> skipping.") return } if msg.TxID != c.finalTx.ID() { @@ -574,15 +588,15 @@ func (c *consensus) processInclusionState(msg *messages.InclusionStateMsg) { } switch msg.State { case ledgerstate.Pending: - c.workflow.transactionSeen = true + c.workflow.setTransactionSeen() c.log.Debugf("processInclusionState: transaction id %v is pending.", c.finalTx.ID().Base58()) case ledgerstate.Confirmed: - c.workflow.transactionSeen = true - c.workflow.inProgress = false + c.workflow.setTransactionSeen() + c.workflow.setCompleted() c.refreshConsensusInfo() c.log.Debugf("processInclusionState: transaction id %s is confirmed; workflow finished", msg.TxID.Base58()) case ledgerstate.Rejected: - c.workflow.transactionSeen = true + c.workflow.setTransactionSeen() c.log.Infof("processInclusionState: transaction id %s is rejected; restarting consensus.", msg.TxID.Base58()) c.resetWorkflow() } @@ -665,20 +679,17 @@ func (c *consensus) resetWorkflow() { c.consensusBatch = nil c.contributors = nil c.resultSigAck = c.resultSigAck[:0] - c.workflow = workflowFlags{ - stateReceived: c.stateOutput != nil, - inProgress: c.stateOutput != nil, - } + c.workflow = newWorkflowStatus(c.stateOutput != nil) c.log.Debugf("Workflow reset") } func (c *consensus) processVMResult(result *vm.VMTask) { - if !c.workflow.vmStarted || - c.workflow.vmResultSigned || + if !c.workflow.IsVMStarted() || + c.workflow.IsVMResultSigned() || c.acsSessionID != result.ACSSessionID { // out of context c.log.Debugf("processVMResult: out of context vmStarted %v, vmResultSignedAndBroadcasted %v, expected ACS session ID %v, returned ACS session ID %v", - c.workflow.vmStarted, c.workflow.vmResultSigned, c.acsSessionID, result.ACSSessionID) + c.workflow.IsVMStarted(), c.workflow.IsVMResultSigned(), c.acsSessionID, result.ACSSessionID) return } rotation := result.RotationAddress != nil @@ -710,7 +721,7 @@ func (c *consensus) processVMResult(result *vm.VMTask) { SenderIndex: c.committee.OwnPeerIndex(), } - c.workflow.vmResultSigned = true + c.workflow.setVMResultSigned() c.log.Debugf("processVMResult signed: essence hash: %s", essenceHash.String()) } @@ -770,15 +781,29 @@ func (c *consensus) receiveSignedResult(msg *messages.SignedResultMsgIn) { func (c *consensus) receiveSignedResultAck(msg *messages.SignedResultAckMsgIn) { own := c.resultSignatures[c.committee.OwnPeerIndex()] - if own == nil || msg.EssenceHash != own.EssenceHash || msg.ChainInputID != own.ChainInputID { + if own == nil { + c.log.Debugf("receiveSignedResultAck: ack from %v ignored, because own signature is nil", msg.SenderIndex) return } + if msg.EssenceHash != own.EssenceHash { + c.log.Debugf("receiveSignedResultAck: ack from %v ignored, because essence hash in ack %v is different than own signature essence hash %v", + msg.SenderIndex, msg.EssenceHash.String(), own.EssenceHash.String()) + return + } + if msg.ChainInputID != own.ChainInputID { + c.log.Debugf("receiveSignedResultAck: ack from %v ignored, because chain input id in ack %v is different than own chain input id %v", + msg.SenderIndex, iscp.OID(msg.ChainInputID), iscp.OID(own.ChainInputID)) + return + } + for _, i := range c.resultSigAck { if i == msg.SenderIndex { + c.log.Debugf("receiveSignedResultAck: ack from %v ignored, because it has already been received", msg.SenderIndex) return } } c.resultSigAck = append(c.resultSigAck, msg.SenderIndex) + c.log.Debugf("receiveSignedResultAck: ack from %v accepted; acks from nodes %v have already been received", msg.SenderIndex, c.resultSigAck) } // TODO mutex inside is not good diff --git a/packages/chain/consensus/commoncoin/commoncoin_test.go b/packages/chain/consensus/commoncoin/commoncoin_test.go index 8dadf7aee7..33e9336e8e 100644 --- a/packages/chain/consensus/commoncoin/commoncoin_test.go +++ b/packages/chain/consensus/commoncoin/commoncoin_test.go @@ -16,8 +16,8 @@ import ( func TestBlsCommonCoin(t *testing.T) { var err error - netIDs, _ := testpeers.SetupKeys(10) - address, regProviders := testpeers.SetupDkgPregenerated(t, 7, netIDs, tcrypto.DefaultSuite()) + netIDs, identities := testpeers.SetupKeys(10) + address, regProviders := testpeers.SetupDkgPregenerated(t, 7, identities, tcrypto.DefaultSuite()) ccs := make([]hbbft.CommonCoin, len(netIDs)) salt := []byte{0, 1, 2, 3} diff --git a/packages/chain/consensus/commonsubset/commonsubset_test.go b/packages/chain/consensus/commonsubset/commonsubset_test.go index 53a67c4f7e..eef363d172 100644 --- a/packages/chain/consensus/commonsubset/commonsubset_test.go +++ b/packages/chain/consensus/commonsubset/commonsubset_test.go @@ -51,7 +51,7 @@ func testBasic(t *testing.T, peerCount, threshold uint16, allRandom bool) { ) t.Logf("Network created.") - dkAddress, dkRegistries := testpeers.SetupDkgPregenerated(t, threshold, peerNetIDs, tcrypto.DefaultSuite()) + dkAddress, dkRegistries := testpeers.SetupDkgPregenerated(t, threshold, peerIdentities, tcrypto.DefaultSuite()) dkShares := make([]*tcrypto.DKShare, len(peerNetIDs)) for i := range dkShares { dkShare, err := dkRegistries[i].LoadDKShare(dkAddress) @@ -61,7 +61,7 @@ func testBasic(t *testing.T, peerCount, threshold uint16, allRandom bool) { acsPeers := make([]*CommonSubset, peerCount) for a := range acsPeers { - group, err := networkProviders[a].PeerGroup(peeringID, peerNetIDs) + group, err := networkProviders[a].PeerGroup(peeringID, testpeers.PublicKeys(peerIdentities)) require.Nil(t, err) acsLog := testlogger.WithLevel(log.Named(fmt.Sprintf("ACS[%02d]", a)), logger.LevelInfo, false) acsPeers[a], err = NewCommonSubset(0, 0, group, dkShares[a], allRandom, nil, acsLog) @@ -100,7 +100,7 @@ func TestRandomized(t *testing.T) { networkProviders, networkCloser := testpeers.SetupNet(peerNetIDs, peerIdentities, netBehavior, netLogger) t.Logf("Network created.") - dkAddress, dkRegistries := testpeers.SetupDkgPregenerated(t, threshold, peerNetIDs, tcrypto.DefaultSuite()) + dkAddress, dkRegistries := testpeers.SetupDkgPregenerated(t, threshold, peerIdentities, tcrypto.DefaultSuite()) dkShares := make([]*tcrypto.DKShare, len(peerNetIDs)) for i := range dkShares { dkShare, err := dkRegistries[i].LoadDKShare(dkAddress) @@ -110,7 +110,7 @@ func TestRandomized(t *testing.T) { acsPeers := make([]*CommonSubset, peerCount) for a := range acsPeers { - group, err := networkProviders[a].PeerGroup(peeringID, peerNetIDs) + group, err := networkProviders[a].PeerGroup(peeringID, testpeers.PublicKeys(peerIdentities)) require.Nil(t, err) acsLog := testlogger.WithLevel(log.Named(fmt.Sprintf("ACS[%02d]", a)), logger.LevelInfo, false) acsPeers[a], err = NewCommonSubset(0, 0, group, dkShares[a], true, nil, acsLog) @@ -195,7 +195,7 @@ func testCoordinator(t *testing.T, peerCount, threshold uint16, inputLen int) { ) t.Logf("Network created.") - dkAddress, dkRegistries := testpeers.SetupDkgPregenerated(t, threshold, peerNetIDs, tcrypto.DefaultSuite()) + dkAddress, dkRegistries := testpeers.SetupDkgPregenerated(t, threshold, peerIdentities, tcrypto.DefaultSuite()) dkShares := make([]*tcrypto.DKShare, len(peerNetIDs)) for i := range dkShares { dkShare, err := dkRegistries[i].LoadDKShare(dkAddress) @@ -205,7 +205,7 @@ func testCoordinator(t *testing.T, peerCount, threshold uint16, inputLen int) { acsCoords := make([]*CommonSubsetCoordinator, peerCount) for i := range acsCoords { - group, err := networkProviders[i].PeerGroup(peeringID, peerNetIDs) + group, err := networkProviders[i].PeerGroup(peeringID, testpeers.PublicKeys(peerIdentities)) require.Nil(t, err) acsLog := testlogger.WithLevel(log.Named(fmt.Sprintf("CSC[%02d]", i)), logger.LevelInfo, false) acsCoords[i] = NewCommonSubsetCoordinator(networkProviders[i], group, dkShares[i], acsLog) @@ -264,10 +264,10 @@ func testRandomizedWithCC(t *testing.T, peerCount, threshold uint16, inputLen in logs[i] = testlogger.WithLevel(log.Named(fmt.Sprintf("CSC[%02d]", i)), logger.LevelInfo, false) } - dkAddress, dkShares := testpeers.SetupDkgPregenerated(t, threshold, peerNetIDs, tcrypto.DefaultSuite()) + dkAddress, dkShares := testpeers.SetupDkgPregenerated(t, threshold, peerIdentities, tcrypto.DefaultSuite()) acsCoords := make([]*CommonSubsetCoordinator, peerCount) for i := range acsCoords { - group, err := networkProviders[i].PeerGroup(peeringID, peerNetIDs) + group, err := networkProviders[i].PeerGroup(peeringID, testpeers.PublicKeys(peerIdentities)) require.Nil(t, err) dkShare, err := dkShares[i].LoadDKShare(dkAddress) require.Nil(t, err) diff --git a/packages/chain/consensus/consensus.go b/packages/chain/consensus/consensus.go index ea579de2d8..2f13161618 100644 --- a/packages/chain/consensus/consensus.go +++ b/packages/chain/consensus/consensus.go @@ -40,7 +40,7 @@ type consensus struct { iAmContributor bool myContributionSeqNumber uint16 contributors []uint16 - workflow workflowFlags + workflow *workflowStatus delayBatchProposalUntil time.Time delayRunVMUntil time.Time delaySendingSignedResult time.Time @@ -68,18 +68,7 @@ type consensus struct { pullMissingRequestsFromCommittee bool receivePeerMessagesAttachID interface{} consensusMetrics metrics.ConsensusMetrics -} - -type workflowFlags struct { - stateReceived bool - batchProposalSent bool - consensusBatchKnown bool - vmStarted bool - vmResultSigned bool - transactionFinalized bool - transactionPosted bool - transactionSeen bool - inProgress bool + wal chain.WAL } var _ chain.Consensus = &consensus{} @@ -91,7 +80,17 @@ const ( maxMsgBuffer = 1000 ) -func New(chainCore chain.ChainCore, mempool chain.Mempool, committee chain.Committee, peerGroup peering.GroupProvider, nodeConn chain.ChainNodeConnection, pullMissingRequestsFromCommittee bool, consensusMetrics metrics.ConsensusMetrics, timersOpt ...ConsensusTimers) chain.Consensus { +func New( + chainCore chain.ChainCore, + mempool chain.Mempool, + committee chain.Committee, + peerGroup peering.GroupProvider, + nodeConn chain.ChainNodeConnection, + pullMissingRequestsFromCommittee bool, + consensusMetrics metrics.ConsensusMetrics, + wal chain.WAL, + timersOpt ...ConsensusTimers, +) chain.Consensus { var timers ConsensusTimers if len(timersOpt) > 0 { timers = timersOpt[0] @@ -106,6 +105,7 @@ func New(chainCore chain.ChainCore, mempool chain.Mempool, committee chain.Commi mempool: mempool, nodeConn: nodeConn, vmRunner: runvm.NewVMRunner(), + workflow: newWorkflowStatus(false), resultSignatures: make([]*messages.SignedResultMsgIn, committee.Size()), resultSigAck: make([]uint16, 0, committee.Size()), timers: timers, @@ -120,6 +120,7 @@ func New(chainCore chain.ChainCore, mempool chain.Mempool, committee chain.Commi assert: assert.NewAssert(log), pullMissingRequestsFromCommittee: pullMissingRequestsFromCommittee, consensusMetrics: consensusMetrics, + wal: wal, } ret.receivePeerMessagesAttachID = ret.committeePeerGroup.Attach(peering.PeerMessageReceiverConsensus, ret.receiveCommitteePeerMessages) ret.nodeConn.AttachToInclusionStateReceived(func(txID ledgerstate.TransactionID, inclusionState ledgerstate.InclusionState) { @@ -294,3 +295,7 @@ func (c *consensus) GetStatusSnapshot() *chain.ConsensusInfo { } return ret.(*chain.ConsensusInfo) } + +func (c *consensus) GetWorkflowStatus() chain.ConsensusWorkflowStatus { + return c.workflow +} diff --git a/packages/chain/consensus/consensus_diagram.png b/packages/chain/consensus/consensus_diagram.png index 5f4c271198..280348ff62 100644 Binary files a/packages/chain/consensus/consensus_diagram.png and b/packages/chain/consensus/consensus_diagram.png differ diff --git a/packages/chain/consensus/consensus_diagram.uxf b/packages/chain/consensus/consensus_diagram.uxf index ed462028a2..aa62251c29 100644 --- a/packages/chain/consensus/consensus_diagram.uxf +++ b/packages/chain/consensus/consensus_diagram.uxf @@ -6,12 +6,12 @@ 603 36 - 441 + 432 513 lt=.> r2=/ACSConsensus(proposal, acsSessionID, stateOutput.Index())/ - 10.0;550.0;110.0;550.0;110.0;20.0;470.0;20.0 + 10.0;550.0;110.0;550.0;110.0;20.0;460.0;20.0 UMLSpecialState @@ -27,25 +27,25 @@ r2=/ACSConsensus(proposal, acsSessionID, stateOutput.Index())/ Relation - 36 + 72 108 - 261 + 225 54 lt=-> -m1=!stateReceived || workflowFinished - 270.0;30.0;50.0;30.0;50.0;10.0 +m1=!stateReceived || !inProgress + 230.0;30.0;10.0;30.0;10.0;10.0 Relation 288 144 - 252 + 207 54 lt=-> -m2=stateReceived && !workflowFinished +m2=stateReceived && inProgress 10.0;10.0;10.0;40.0 @@ -53,8 +53,8 @@ m2=stateReceived && !workflowFinished 0 0 - 1719 - 2403 + 1710 + 2439 _Wasp:this_ @@ -77,13 +77,13 @@ valign=top UMLClass - 1773 + 1764 0 90 36 *Consensus* -version: 3 +version: 4 @@ -239,7 +239,7 @@ halign=left UMLDeployment - 1026 + 1017 27 99 36 @@ -250,7 +250,7 @@ halign=left Relation - 1062 + 1053 54 342 54 @@ -441,14 +441,15 @@ len(reqs) == 0 UMLState - 585 - 2124 + 657 + 2142 270 - 261 + 279 *resetWorkflow()* -- resultSignatures[i] := nil for all i +resultSigAck := [] acsSessionID++ resultState := nil resultTxEssence := nil @@ -459,11 +460,11 @@ stateReceived := (stateOutput != nil) batchProposalSent := false consensusBatchKnown := false vmStarted := false -vmResultSignedAndBroadcasted := false +vmResultSigned := false transactionFinalized := false transactionPosted := false transactionSeen := false -workflowFinished := false +inProgress := (stateOutput != nil) valign=top @@ -509,17 +510,17 @@ halign=left 450 837 - 594 + 585 234 lt=.> r1=/Run(task)/ - 10.0;240.0;450.0;240.0;450.0;10.0;640.0;10.0 + 10.0;240.0;450.0;240.0;450.0;10.0;630.0;10.0 UMLDeployment - 1026 + 1017 828 117 36 @@ -530,7 +531,7 @@ r1=/Run(task)/ Relation - 1071 + 1062 855 144 54 @@ -555,7 +556,7 @@ m2=/VMResultMsg(task)/ UMLState 54 - 1278 + 1296 801 567 @@ -569,7 +570,7 @@ valign=top Relation 81 - 1323 + 1341 45 27 @@ -580,7 +581,7 @@ valign=top UMLSpecialState 72 - 1323 + 1341 18 18 @@ -591,7 +592,7 @@ valign=top UMLSpecialState 108 - 1314 + 1332 36 36 @@ -602,7 +603,7 @@ valign=top Relation 135 - 1314 + 1332 774 603 @@ -614,7 +615,7 @@ r1=transactionFinalized || !vmResultSigned Relation 117 - 1341 + 1359 288 54 @@ -626,7 +627,7 @@ m2=!transactionFinalized && vmResultSigned UMLState 72 - 1377 + 1395 675 36 @@ -637,8 +638,8 @@ halign=left Relation - 117 - 1404 + 99 + 1422 27 45 @@ -649,8 +650,8 @@ halign=left UMLSpecialState - 108 - 1431 + 90 + 1449 36 36 @@ -660,8 +661,8 @@ halign=left Relation - 117 - 1458 + 99 + 1476 288 54 @@ -672,20 +673,20 @@ len(contributors) >= committee.Quorum() Relation - 135 - 1431 - 765 + 117 + 1449 + 783 477 lt=-> r1=len(contributors) < committee.Quorum() - 10.0;20.0;830.0;20.0;830.0;510.0;760.0;510.0 + 10.0;20.0;850.0;20.0;850.0;510.0;780.0;510.0 UMLSpecialState - 108 - 1494 + 90 + 1512 36 36 @@ -695,20 +696,20 @@ r1=len(contributors) < committee.Quorum() Relation - 135 - 1494 - 594 + 117 + 1512 + 612 36 lt=-> for some i DKShare.VerifySig(resultTxEssence, resultSignatures[contributors[i]]) is error - 10.0;20.0;640.0;20.0 + 10.0;20.0;660.0;20.0 Relation - 117 - 1521 + 99 + 1539 549 54 @@ -732,7 +733,7 @@ m2=for all i DKShare.VerifySig(resultTxEssence, resultSignatures[contributors[i] Relation 810 - 1503 + 1521 81 396 @@ -744,7 +745,7 @@ m2=for all i DKShare.VerifySig(resultTxEssence, resultSignatures[contributors[i] UMLState 711 - 1503 + 1521 126 27 @@ -756,7 +757,7 @@ halign=left UMLState 243 - 1800 + 1818 594 27 @@ -767,8 +768,8 @@ halign=left UMLDeployment - 1026 - 1728 + 1017 + 1746 99 36 @@ -778,8 +779,8 @@ halign=left Relation - 1062 - 1755 + 1053 + 1773 360 54 @@ -791,19 +792,19 @@ m2=/StateTransitionMsg(state, output, outputTimestamp)/ Relation 504 - 1728 - 540 + 1746 + 531 36 lt=.> /StateCandidateMsg(resultState, chainOutput.ID())/ - 10.0;20.0;580.0;20.0 + 10.0;20.0;570.0;20.0 Relation 99 - 1701 + 1719 27 45 @@ -815,7 +816,7 @@ m2=/StateTransitionMsg(state, output, outputTimestamp)/ UMLSpecialState 90 - 1791 + 1809 36 36 @@ -826,7 +827,7 @@ m2=/StateTransitionMsg(state, output, outputTimestamp)/ Relation 99 - 1818 + 1836 126 63 @@ -839,7 +840,7 @@ m2pos=0,-10 Relation 117 - 1791 + 1809 144 36 @@ -850,8 +851,8 @@ iAmContributor UMLState - 81 - 1557 + 72 + 1575 594 153 @@ -871,7 +872,7 @@ halign=left Relation 252 - 1818 + 1836 27 63 @@ -883,7 +884,7 @@ halign=left UMLSpecialState 72 - 1908 + 1926 18 18 @@ -894,7 +895,7 @@ halign=left UMLSpecialState 108 - 1899 + 1917 36 36 @@ -905,7 +906,7 @@ halign=left Relation 81 - 1908 + 1926 45 27 @@ -916,7 +917,7 @@ halign=left Relation 117 - 1926 + 1944 414 63 @@ -929,7 +930,7 @@ transactionSeen || Now is before postTxDeadline Relation 135 - 1899 + 1917 468 45 @@ -942,7 +943,7 @@ transactionFinalized && iAmContributor && !transactionPosted &am UMLState 585 - 1899 + 1917 189 36 @@ -954,19 +955,19 @@ halign=left Relation 765 - 1899 - 1053 + 1917 + 1044 153 lt=.> /MsgPostTransaction(finalTx)/ - 10.0;20.0;1150.0;20.0;1150.0;150.0 + 10.0;20.0;1140.0;20.0;1140.0;150.0 Relation 630 - 1926 + 1944 27 63 @@ -978,7 +979,7 @@ halign=left UMLState 54 - 1971 + 1989 873 117 @@ -992,7 +993,7 @@ valign=top UMLSpecialState 72 - 2007 + 2025 18 18 @@ -1003,7 +1004,7 @@ valign=top Relation 81 - 2007 + 2025 270 45 @@ -1014,7 +1015,7 @@ valign=top UMLSpecialState 315 - 2034 + 2052 36 36 @@ -1027,18 +1028,18 @@ valign=top 27 99 306 - 1980 + 1998 lt=-> !transactionFinalized || transactionSeen || Now is before pullInclusionStateDeadline - 320.0;2170.0;10.0;2170.0;320.0;2170.0;10.0;2170.0;10.0;10.0;30.0;10.0 + 320.0;2190.0;10.0;2190.0;320.0;2190.0;10.0;2190.0;10.0;10.0;30.0;10.0 Relation 342 - 2034 + 2052 324 45 @@ -1051,7 +1052,7 @@ Now is not before pullInclusionStateDeadline UMLState 648 - 2034 + 2052 261 36 @@ -1065,29 +1066,29 @@ halign=left 18 81 774 - 2043 + 2061 lt=-> - 840.0;2210.0;840.0;2250.0;10.0;2250.0;10.0;10.0;40.0;10.0 + 840.0;2230.0;840.0;2270.0;10.0;2270.0;10.0;10.0;40.0;10.0 Relation 900 - 2034 - 855 + 2052 + 846 36 lt=.> /MsgGetTxInclusionState(chain.ID(), finalTx.ID())/ - 10.0;20.0;930.0;20.0 + 10.0;20.0;920.0;20.0 UMLDeployment - 1737 - 2034 + 1728 + 2052 126 36 @@ -1097,8 +1098,8 @@ halign=left Relation - 1395 - 2061 + 1386 + 2079 423 54 @@ -1146,7 +1147,7 @@ TimerTick UMLSpecialState - 1062 + 1053 891 36 36 @@ -1157,7 +1158,7 @@ TimerTick Relation - 1089 + 1080 891 360 45 @@ -1170,7 +1171,7 @@ acsSessionID != task.ACSSessionID UMLSpecialState - 1431 + 1422 900 18 18 @@ -1181,7 +1182,7 @@ acsSessionID != task.ACSSessionID Relation - 1071 + 1062 918 486 54 @@ -1193,13 +1194,14 @@ acsSessionID != task.ACSSessionID UMLState - 1026 + 1017 1071 - 405 - 99 + 441 + 117 essenceHash = Hash(resultTxEssence) sigShare = DKShare.Sign(resultTxEssence) +resultSignatures[ownPeerIndex].ChainInputID = task.ChainInput.ID() resultSignatures[ownPeerIndex].SenderIndex = ownPeerIndex resultSignatures[ownPeerIndex].EssenceHash = essenceHash resultSignatures[ownPeerIndex].SigShare = sigShare @@ -1211,30 +1213,30 @@ halign=left Relation 324 - 1206 - 1431 + 1224 + 1422 36 lt=.> r1=/SignedResultMsg(ownPeerIndex, stateOutput.ID(), essenceHash, sigShare, Now)/ - 10.0;20.0;1570.0;20.0 + 10.0;20.0;1560.0;20.0 Relation 306 126 - 738 + 729 1044 lt=-> - 800.0;1140.0;770.0;1140.0;770.0;10.0;10.0;10.0 + 790.0;1140.0;760.0;1140.0;760.0;10.0;10.0;10.0 UMLState - 1026 - 2115 + 1017 + 2133 153 27 @@ -1245,8 +1247,8 @@ halign=left UMLSpecialState - 1368 - 2079 + 1359 + 2097 36 36 @@ -1256,8 +1258,8 @@ halign=left Relation - 1377 - 2106 + 1368 + 2124 288 54 @@ -1268,8 +1270,8 @@ halign=left UMLSpecialState - 1377 - 2142 + 1368 + 2160 18 18 @@ -1279,8 +1281,8 @@ halign=left Relation - 1089 - 2079 + 1080 + 2097 297 54 @@ -1291,8 +1293,8 @@ transactionFinalized && txID == finalTx.ID() Relation - 1089 - 2133 + 1080 + 2151 27 45 @@ -1303,8 +1305,8 @@ transactionFinalized && txID == finalTx.ID() UMLSpecialState - 1080 - 2160 + 1071 + 2178 36 36 @@ -1314,8 +1316,8 @@ transactionFinalized && txID == finalTx.ID() Relation - 1089 - 2187 + 1080 + 2205 126 54 @@ -1326,8 +1328,8 @@ m2=state is Rejected UMLState - 1026 - 2223 + 1017 + 2241 126 27 @@ -1340,18 +1342,18 @@ halign=left 306 126 - 738 - 2133 + 729 + 2151 lt=-> - 800.0;2350.0;720.0;2350.0;720.0;10.0;10.0;10.0 + 790.0;2370.0;720.0;2370.0;720.0;10.0;10.0;10.0 Relation - 1107 - 2160 + 1098 + 2178 171 36 @@ -1362,12 +1364,12 @@ state is Confirmed UMLState - 1260 - 2169 + 1251 + 2187 180 45 - finished = true + inProgress = false *refreshConsensusInfo()* halign=left @@ -1377,18 +1379,18 @@ halign=left 306 126 - 1062 - 2160 + 1053 + 2178 lt=-> - 1160.0;2320.0;1160.0;2380.0;710.0;2380.0;710.0;10.0;10.0;10.0 + 1150.0;2340.0;1150.0;2400.0;710.0;2400.0;710.0;10.0;10.0;10.0 UMLState - 873 - 2286 + 945 + 2322 351 99 @@ -1406,7 +1408,7 @@ valign=top UMLSpecialState - 1053 + 1044 90 36 36 @@ -1417,7 +1419,7 @@ valign=top Relation - 1080 + 1071 90 387 36 @@ -1429,7 +1431,7 @@ acsSessionID != sessionID || consensusBatchKnown UMLSpecialState - 1449 + 1440 99 18 18 @@ -1440,7 +1442,7 @@ acsSessionID != sessionID || consensusBatchKnown Relation - 1062 + 1053 117 369 54 @@ -1452,7 +1454,7 @@ acsSessionID == sessionID && !consensusBatchKnown UMLSpecialState - 1053 + 1044 153 36 36 @@ -1463,7 +1465,7 @@ acsSessionID == sessionID && !consensusBatchKnown Relation - 1080 + 1071 153 432 72 @@ -1478,7 +1480,7 @@ for some i, j: acs[i].ValidatorIndex == acs[j].ValidatorIndex UMLState - 1494 + 1485 162 126 27 @@ -1490,7 +1492,7 @@ halign=left Relation - 1062 + 1053 180 369 135 @@ -1505,7 +1507,7 @@ for all i, j: acs[i].ValidatorIndex != acs[j].ValidatorIndex UMLState - 1026 + 1017 297 495 63 @@ -1519,7 +1521,7 @@ halign=left UMLState - 1206 + 1197 531 270 45 @@ -1532,7 +1534,7 @@ halign=left Relation - 1062 + 1053 351 27 45 @@ -1543,7 +1545,7 @@ halign=left UMLSpecialState - 1053 + 1044 378 36 36 @@ -1554,7 +1556,7 @@ halign=left Relation - 1080 + 1071 378 189 36 @@ -1566,7 +1568,7 @@ len(inBatchSet) == 0 UMLSpecialState - 1539 + 1530 387 18 18 @@ -1577,7 +1579,7 @@ len(inBatchSet) == 0 UMLState - 1251 + 1242 378 270 36 @@ -1590,7 +1592,7 @@ halign=left Relation - 1512 + 1503 387 45 27 @@ -1601,7 +1603,7 @@ halign=left Relation - 1062 + 1053 405 144 54 @@ -1613,7 +1615,7 @@ m2=len(inBatchSet) > 0 UMLState - 1026 + 1017 441 594 72 @@ -1628,7 +1630,7 @@ halign=left UMLSpecialState - 1053 + 1044 531 36 36 @@ -1639,7 +1641,7 @@ halign=left Relation - 1062 + 1053 504 27 45 @@ -1650,7 +1652,7 @@ halign=left Relation - 1080 + 1071 531 144 36 @@ -1662,7 +1664,7 @@ DKShare error UMLState - 1026 + 1017 594 594 207 @@ -1686,7 +1688,7 @@ halign=left Relation - 1062 + 1053 558 99 54 @@ -1698,7 +1700,7 @@ m2=DKShare ok Relation - 1467 + 1458 558 45 54 @@ -1711,11 +1713,11 @@ m2=DKShare ok 306 126 - 738 + 729 675 lt=-> - 800.0;730.0;780.0;730.0;780.0;10.0;10.0;10.0 + 790.0;730.0;770.0;730.0;770.0;10.0;10.0;10.0 UMLSpecialState @@ -1765,8 +1767,8 @@ halign=center UMLState - 1026 - 1791 + 1017 + 1809 405 81 @@ -1783,19 +1785,19 @@ halign=left 306 126 - 738 - 1746 + 729 + 1764 lt=-> - 800.0;1920.0;740.0;1920.0;740.0;10.0;10.0;10.0 + 790.0;1940.0;740.0;1940.0;740.0;10.0;10.0;10.0 UMLDeployment - 1737 - 1206 + 1728 + 1224 126 - 36 + 342 _Wasp:Other_ @@ -1803,20 +1805,21 @@ halign=left Relation - 1359 - 1233 - 513 - 54 + 1341 + 1269 + 405 + 45 lt=.> -r2=/SignedResultMsg(senderIndex, chainInputID, essenceHash, sigShare, Now)/ - 480.0;10.0;480.0;40.0;10.0;40.0 +/SignedResultMsg(senderIndex, chainInputID, essenceHash,/ +/sigShare, Now)/ + 430.0;20.0;10.0;20.0 UMLSpecialState - 1332 - 1251 + 1314 + 1269 36 36 @@ -1826,46 +1829,41 @@ r2=/SignedResultMsg(senderIndex, chainInputID, essenceHash, sigShare, Now)/ Relation - 306 - 126 - 1044 - 1224 + 1062 + 1269 + 270 + 54 lt=-> stateOutput == nil || stateOutput.ID() != chainInputID || -resultSignatures[senderIndex] != nil || -sigShare >= committee.Size() || -sigShare == ownPeerIndex || -sigShare != senderIndex - 1140.0;1270.0;760.0;1270.0;1140.0;1270.0;760.0;1270.0;760.0;10.0;10.0;10.0 +resultSignatures[senderIndex] != nil + 280.0;20.0;10.0;20.0 Relation - 1341 - 1278 - 279 - 117 + 1323 + 1296 + 261 + 81 lt=-> stateOutput != nil && stateOutput.ID() == chainInputID && -resultSignatures[senderIndex] == nil && -sigShare < committee.Size() && -sigShare != ownPeerIndex && -sigShare == senderIndex - 10.0;10.0;10.0;80.0;10.0;10.0;10.0;110.0 +resultSignatures[senderIndex] == nil + 10.0;10.0;10.0;50.0;10.0;10.0;10.0;70.0 UMLState - 1026 - 1377 + 1017 + 1413 387 - 54 + 72 - resultSignatures[senderIndex].SenderIndex = senderIndex + resultSignatures[senderIndex].ChainInputID = chainInputID +resultSignatures[senderIndex].SenderIndex = senderIndex resultSignatures[senderIndex].EssenceHash = essenceHash resultSignatures[senderIndex].SigShare = sigShare halign=left @@ -1876,18 +1874,18 @@ halign=left 306 126 - 738 - 1305 + 729 + 1431 lt=-> - 800.0;1430.0;750.0;1430.0;750.0;10.0;10.0;10.0 + 790.0;1570.0;750.0;1570.0;750.0;10.0;10.0;10.0 UMLState 54 - 1863 + 1881 765 90 @@ -1900,7 +1898,7 @@ valign=top Relation - 1458 + 1449 99 117 81 @@ -1913,12 +1911,12 @@ valign=top 306 126 - 792 - 2070 + 783 + 2088 lt=-> r1= state is Pending - 860.0;2280.0;730.0;2280.0;730.0;10.0;10.0;10.0 + 850.0;2300.0;730.0;2300.0;730.0;10.0;10.0;10.0 UMLState @@ -1926,7 +1924,7 @@ r1= state is Pending 54 1107 297 - 153 + 171 *broadcastSignedResultIfNeeded()* -- @@ -1972,30 +1970,32 @@ valign=top 117 1170 - 405 - 54 + 423 + 72 lt=-> -vmResultSigned && Now is after delaySendingSignedResult - 10.0;10.0;10.0;20.0;10.0;10.0;10.0;40.0 +vmResultSigned && len(resultSigAck) < committee.Size()-1 && +Now is after delaySendingSignedResult + 10.0;10.0;10.0;40.0;10.0;10.0;10.0;60.0 Relation 135 1143 - 423 - 153 + 450 + 171 lt=-> -!vmResultSigned || Now is not after delaySendingSignedResult - 10.0;20.0;450.0;20.0;450.0;150.0 +!vmResultSigned || len(resultSigAck) >= committee.Size()-1 || +Now is not after delaySendingSignedResult + 10.0;20.0;480.0;20.0;480.0;170.0 UMLState 72 - 1206 + 1224 261 36 @@ -2008,7 +2008,7 @@ halign=left Relation 117 - 1233 + 1251 27 63 @@ -2020,7 +2020,7 @@ halign=left UMLSpecialState 90 - 1728 + 1746 36 36 @@ -2031,7 +2031,7 @@ halign=left Relation 117 - 1728 + 1746 279 36 @@ -2043,7 +2043,7 @@ halign=left Relation 99 - 1755 + 1773 243 54 @@ -2055,7 +2055,7 @@ m2=chainOutput.isGovernanceUpdated UMLState 378 - 1737 + 1755 135 27 @@ -2066,7 +2066,7 @@ halign=left UMLSpecialState - 1062 + 1053 954 36 36 @@ -2077,7 +2077,7 @@ halign=left Relation - 1089 + 1080 954 288 36 @@ -2089,7 +2089,7 @@ result.RotationAddress != nil Relation - 1071 + 1062 981 207 54 @@ -2101,7 +2101,7 @@ result.RotationAddress == nil UMLState - 1026 + 1017 1017 324 36 @@ -2114,7 +2114,7 @@ halign=left UMLState - 1359 + 1350 954 333 99 @@ -2131,7 +2131,7 @@ halign=left Relation - 1071 + 1062 1044 27 45 @@ -2142,7 +2142,7 @@ halign=left Relation - 1377 + 1368 1044 27 45 @@ -2150,4 +2150,176 @@ halign=left lt=-> 10.0;10.0;10.0;30.0 + + UMLSpecialState + + 1314 + 1359 + 36 + 36 + + type=decision + + + + Relation + + 1089 + 1359 + 243 + 72 + + lt=-> +sigShare < committee.Size() && +sigShare != ownPeerIndex && +sigShare == senderIndex + 250.0;20.0;10.0;20.0;10.0;60.0 + + + Relation + + 1152 + 1359 + 486 + 180 + + lt=-> +sigShare >= committee.Size() || +sigShare == ownPeerIndex || +sigShare != senderIndex + 220.0;20.0;300.0;20.0;300.0;40.0;300.0;20.0;300.0;160.0;10.0;160.0;10.0;180.0 + + + UMLState + + 1017 + 1521 + 162 + 27 + + sendSignedResultAck() +halign=left + + + + Relation + + 1089 + 1476 + 27 + 63 + + lt=-> + 10.0;10.0;10.0;50.0 + + + Relation + + 1170 + 1512 + 576 + 36 + + lt=.> +r1=/SignedResultAckMsg(ownPeerIndex, chainInputID, essenceHash)/ + 10.0;20.0;620.0;20.0 + + + Relation + + 1305 + 1539 + 441 + 54 + + lt=.> +r1=/SignedResultAckMsg(senderIndex, chainInputID, essenceHash)/ + 470.0;20.0;90.0;20.0;80.0;40.0 + + + UMLSpecialState + + 1359 + 1575 + 36 + 36 + + type=decision + + + + UMLSpecialState + + 1053 + 1278 + 18 + 18 + + type=final + + + + Relation + + 1368 + 1602 + 333 + 90 + + lt=-> +ownSignature := resultSignatures[ownPeerIndex] +ownSignature == nil || +ownSignature.EssenceHash != essenceHash || +ownSignature.ChainInputID != chainInputID + 10.0;10.0;10.0;50.0;10.0;10.0;10.0;80.0 + + + UMLSpecialState + + 1368 + 1674 + 18 + 18 + + type=final + + + + Relation + + 1026 + 1575 + 351 + 108 + + lt=-> +ownSignature := resultSignatures[ownPeerIndex] +ownSignature == nil || +ownSignature.EssenceHash != essenceHash || +ownSignature.ChainInputID != chainInputID + 370.0;20.0;10.0;20.0;10.0;100.0 + + + UMLState + + 1017 + 1665 + 234 + 27 + + append(resultSigAck, senderIndex) +halign=left + + + + Relation + + 1242 + 1674 + 144 + 27 + + lt=-> + 10.0;10.0;140.0;10.0 + diff --git a/packages/chain/consensus/setup_test.go b/packages/chain/consensus/setup_test.go index c78ead2e88..e1dd02dfd4 100644 --- a/packages/chain/consensus/setup_test.go +++ b/packages/chain/consensus/setup_test.go @@ -40,6 +40,7 @@ import ( "github.com/iotaledger/wasp/packages/testutil/testpeers" "github.com/iotaledger/wasp/packages/transaction" "github.com/iotaledger/wasp/packages/util" + "github.com/iotaledger/wasp/packages/wal" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" ) @@ -114,10 +115,10 @@ func newMockedEnv(t *testing.T, n, quorum uint16, debug, mockACS bool) (*MockedE ret.NetworkBehaviour = testutil.NewPeeringNetDynamic(log) log.Infof("running DKG and setting up mocked network..") - nodeIDs, identities := testpeers.SetupKeys(n) + nodeIDs, nodeIdentities := testpeers.SetupKeys(n) ret.NodeIDs = nodeIDs - ret.StateAddress, ret.DKSRegistries = testpeers.SetupDkgPregenerated(t, quorum, ret.NodeIDs, tcrypto.DefaultSuite()) - ret.NetworkProviders, ret.NetworkCloser = testpeers.SetupNet(ret.NodeIDs, identities, ret.NetworkBehaviour, log) + ret.StateAddress, ret.DKSRegistries = testpeers.SetupDkgPregenerated(t, quorum, nodeIdentities, tcrypto.DefaultSuite()) + ret.NetworkProviders, ret.NetworkCloser = testpeers.SetupNet(ret.NodeIDs, nodeIdentities, ret.NetworkBehaviour, log) ret.OriginatorKeyPair, ret.OriginatorAddress = ret.Ledger.NewKeyPairByIndex(0) _, err = ret.Ledger.RequestFunds(ret.OriginatorAddress) @@ -203,32 +204,26 @@ func (env *MockedEnv) NewNode(nodeIndex uint16, timers ConsensusTimers) *mockedN mempoolMetrics := metrics.DefaultChainMetrics() ret.Mempool = mempool.New(ret.ChainCore.GetStateReader(), iscp.NewInMemoryBlobCache(), log, mempoolMetrics) - cfg := &consensusTestConfigProvider{ - ownNetID: nodeID, - neighbors: env.NodeIDs, - } // // Pass the ACS mock, if it was set in env.MockedACS. acs := make([]chain.AsynchronousCommonSubsetRunner, 0, 1) if env.MockedACS != nil { acs = append(acs, env.MockedACS) } - cmtRec := ®istry.CommitteeRecord{ - Address: env.StateAddress, - Nodes: env.NodeIDs, + dkShare, err := env.DKSRegistries[nodeIndex].LoadDKShare(env.StateAddress) + if err != nil { + panic(err) } cmt, cmtPeerGroup, err := committee.New( - cmtRec, + dkShare, env.ChainID, env.NetworkProviders[nodeIndex], - cfg, - env.DKSRegistries[nodeIndex], log, acs..., ) require.NoError(env.T, err) cmtPeerGroup.Attach(peering.PeerMessageReceiverConsensus, func(peerMsg *peering.PeerMessageGroupIn) { - log.Debugf("Consensus received peer message from %v of type %v", peerMsg.SenderNetID, peerMsg.MsgType) + log.Debugf("Consensus received peer message from %v of type %v", peerMsg.SenderPubKey.String(), peerMsg.MsgType) switch peerMsg.MsgType { case peerMsgTypeSignedResult: msg, err := messages.NewSignedResultMsg(peerMsg.MsgData) @@ -258,7 +253,7 @@ func (env *MockedEnv) NewNode(nodeIndex uint16, timers ConsensusTimers) *mockedN ret.stateSync.SetSolidIndex(0) require.NoError(env.T, err) - cons := New(ret.ChainCore, ret.Mempool, cmt, cmtPeerGroup, ret.NodeConn, true, metrics.DefaultChainMetrics(), timers) + cons := New(ret.ChainCore, ret.Mempool, cmt, cmtPeerGroup, ret.NodeConn, true, metrics.DefaultChainMetrics(), wal.NewDefault(), timers) cons.(*consensus).vmRunner = testchain.NewMockedVMRunner(env.T, log) ret.Consensus = cons @@ -444,27 +439,3 @@ func (env *MockedEnv) PostDummyRequests(n int, randomize ...bool) { } } } - -// TODO: should this object be obtained from peering.NetworkProvider? -// Or should registry.PeerNetworkConfigProvider methods methods be part of -// peering.NetworkProvider interface -type consensusTestConfigProvider struct { - ownNetID string - neighbors []string -} - -func (p *consensusTestConfigProvider) OwnNetID() string { - return p.ownNetID -} - -func (p *consensusTestConfigProvider) PeeringPort() int { - return 0 // Anything -} - -func (p *consensusTestConfigProvider) Neighbors() []string { - return p.neighbors -} - -func (p *consensusTestConfigProvider) String() string { - return fmt.Sprintf("consensusTestConfigProvider( ownNetID: %s, neighbors: %+v )", p.OwnNetID(), p.Neighbors()) -} diff --git a/packages/chain/consensus/workflow_status.go b/packages/chain/consensus/workflow_status.go new file mode 100644 index 0000000000..65726d0178 --- /dev/null +++ b/packages/chain/consensus/workflow_status.go @@ -0,0 +1,148 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package consensus + +import ( + "time" + + "github.com/iotaledger/wasp/packages/chain" +) + +type workflowStatus struct { + flagStateReceived bool + flagBatchProposalSent bool + flagConsensusBatchKnown bool + flagVMStarted bool + flagVMResultSigned bool + flagTransactionFinalized bool + flagTransactionPosted bool + flagTransactionSeen bool + flagInProgress bool + + timeBatchProposalSent time.Time + timeConsensusBatchKnown time.Time + timeVMStarted time.Time + timeVMResultSigned time.Time + timeTransactionFinalized time.Time + timeTransactionPosted time.Time + timeTransactionSeen time.Time + timeCompleted time.Time +} + +var _ chain.ConsensusWorkflowStatus = &workflowStatus{} + +func newWorkflowStatus(stateReceived bool) *workflowStatus { + return &workflowStatus{ + flagStateReceived: stateReceived, + flagInProgress: stateReceived, + } +} + +func (wsT *workflowStatus) setBatchProposalSent() { + wsT.flagBatchProposalSent = true + wsT.timeBatchProposalSent = time.Now() +} + +func (wsT *workflowStatus) setConsensusBatchKnown() { + wsT.flagConsensusBatchKnown = true + wsT.timeConsensusBatchKnown = time.Now() +} + +func (wsT *workflowStatus) setVMStarted() { + wsT.flagVMStarted = true + wsT.timeVMStarted = time.Now() +} + +func (wsT *workflowStatus) setVMResultSigned() { + wsT.flagVMResultSigned = true + wsT.timeVMResultSigned = time.Now() +} + +func (wsT *workflowStatus) setTransactionFinalized() { + wsT.flagTransactionFinalized = true + wsT.timeTransactionFinalized = time.Now() +} + +func (wsT *workflowStatus) setTransactionPosted() { + wsT.flagTransactionPosted = true + wsT.timeTransactionPosted = time.Now() +} + +func (wsT *workflowStatus) setTransactionSeen() { + wsT.flagTransactionSeen = true + wsT.timeTransactionSeen = time.Now() +} + +func (wsT *workflowStatus) setCompleted() { + wsT.flagInProgress = false + wsT.timeCompleted = time.Now() +} + +func (wsT *workflowStatus) IsStateReceived() bool { + return wsT.flagStateReceived +} + +func (wsT *workflowStatus) IsBatchProposalSent() bool { + return wsT.flagBatchProposalSent +} + +func (wsT *workflowStatus) IsConsensusBatchKnown() bool { + return wsT.flagConsensusBatchKnown +} + +func (wsT *workflowStatus) IsVMStarted() bool { + return wsT.flagVMStarted +} + +func (wsT *workflowStatus) IsVMResultSigned() bool { + return wsT.flagVMResultSigned +} + +func (wsT *workflowStatus) IsTransactionFinalized() bool { + return wsT.flagTransactionFinalized +} + +func (wsT *workflowStatus) IsTransactionPosted() bool { + return wsT.flagTransactionPosted +} + +func (wsT *workflowStatus) IsTransactionSeen() bool { + return wsT.flagTransactionSeen +} + +func (wsT *workflowStatus) IsInProgress() bool { + return wsT.flagInProgress +} + +func (wsT *workflowStatus) GetBatchProposalSentTime() time.Time { + return wsT.timeBatchProposalSent +} + +func (wsT *workflowStatus) GetConsensusBatchKnownTime() time.Time { + return wsT.timeConsensusBatchKnown +} + +func (wsT *workflowStatus) GetVMStartedTime() time.Time { + return wsT.timeVMStarted +} + +func (wsT *workflowStatus) GetVMResultSignedTime() time.Time { + return wsT.timeVMResultSigned +} + +func (wsT *workflowStatus) GetTransactionFinalizedTime() time.Time { + return wsT.timeTransactionFinalized +} + +func (wsT *workflowStatus) GetTransactionPostedTime() time.Time { + return wsT.timeTransactionPosted +} + +func (wsT *workflowStatus) GetTransactionSeenTime() time.Time { + return wsT.timeTransactionSeen +} + +func (wsT *workflowStatus) GetCompletedTime() time.Time { + return wsT.timeCompleted +} diff --git a/packages/chain/messages/peer_block_msg.go b/packages/chain/messages/peer_block_msg.go index 452b0bdc34..e166565a76 100644 --- a/packages/chain/messages/peer_block_msg.go +++ b/packages/chain/messages/peer_block_msg.go @@ -7,6 +7,7 @@ import ( "bytes" "io" + "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/wasp/packages/util" ) @@ -18,7 +19,7 @@ type BlockMsg struct { type BlockMsgIn struct { BlockMsg - SenderNetID string + SenderPubKey *ed25519.PublicKey } func NewBlockMsg(data []byte) (*BlockMsg, error) { diff --git a/packages/chain/messages/peer_get_block_msg.go b/packages/chain/messages/peer_get_block_msg.go index 48d4a500c6..21aec929d2 100644 --- a/packages/chain/messages/peer_get_block_msg.go +++ b/packages/chain/messages/peer_get_block_msg.go @@ -7,6 +7,7 @@ import ( "bytes" "io" + "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/wasp/packages/util" ) @@ -18,7 +19,7 @@ type GetBlockMsg struct { type GetBlockMsgIn struct { GetBlockMsg - SenderNetID string + SenderPubKey *ed25519.PublicKey } func NewGetBlockMsg(data []byte) (*GetBlockMsg, error) { diff --git a/packages/chain/messages/peer_missing_request_ids_msg.go b/packages/chain/messages/peer_missing_request_ids_msg.go index ed32285b4e..265eef4dba 100644 --- a/packages/chain/messages/peer_missing_request_ids_msg.go +++ b/packages/chain/messages/peer_missing_request_ids_msg.go @@ -4,6 +4,7 @@ package messages import ( + "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/hive.go/marshalutil" "github.com/iotaledger/wasp/packages/iscp" ) @@ -14,7 +15,7 @@ type MissingRequestIDsMsg struct { type MissingRequestIDsMsgIn struct { MissingRequestIDsMsg - SenderNetID string + SenderPubKey *ed25519.PublicKey } func (msg *MissingRequestIDsMsg) Bytes() []byte { diff --git a/packages/chain/messages/peer_offledger_request_msg.go b/packages/chain/messages/peer_offledger_request_msg.go index 672a7e3414..ab1b3f965d 100644 --- a/packages/chain/messages/peer_offledger_request_msg.go +++ b/packages/chain/messages/peer_offledger_request_msg.go @@ -4,6 +4,7 @@ package messages import ( + "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/hive.go/marshalutil" "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/iscp/request" @@ -17,7 +18,7 @@ type OffLedgerRequestMsg struct { type OffLedgerRequestMsgIn struct { OffLedgerRequestMsg - SenderNetID string + SenderPubKey *ed25519.PublicKey } func NewOffLedgerRequestMsg(data []byte) (*OffLedgerRequestMsg, error) { diff --git a/packages/chain/messages/peer_request_ack_msg.go b/packages/chain/messages/peer_request_ack_msg.go index 35bbbba2a2..179ec8f2ab 100644 --- a/packages/chain/messages/peer_request_ack_msg.go +++ b/packages/chain/messages/peer_request_ack_msg.go @@ -7,6 +7,7 @@ import ( "bytes" "io" + "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/wasp/packages/iscp" "golang.org/x/xerrors" ) @@ -17,7 +18,7 @@ type RequestAckMsg struct { type RequestAckMsgIn struct { RequestAckMsg - SenderNetID string + SenderPubKey *ed25519.PublicKey } func NewRequestAckMsg(buf []byte) (*RequestAckMsg, error) { diff --git a/packages/chain/statemgr/domain_with_fallback.go b/packages/chain/statemgr/domain_with_fallback.go new file mode 100644 index 0000000000..e82a342503 --- /dev/null +++ b/packages/chain/statemgr/domain_with_fallback.go @@ -0,0 +1,135 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package statemgr + +import ( + "context" + "time" + + "github.com/iotaledger/hive.go/crypto/ed25519" + "github.com/iotaledger/hive.go/logger" + "github.com/iotaledger/wasp/packages/peering" + "golang.org/x/xerrors" +) + +// DomainWithFallback acts as a peering domain, but maintains 2 sets of peers, +// one for the normal operation (matches with the chain peers) and other for +// the fallback mode (include all the trusted peers). +type DomainWithFallback struct { + ctx context.Context + ctxCancel context.CancelFunc + net peering.NetworkProvider + dom peering.PeerDomainProvider + fallback bool + mainPeers []*ed25519.PublicKey + log *logger.Logger +} + +func NewDomainWithFallback(peeringID peering.PeeringID, net peering.NetworkProvider, log *logger.Logger) (*DomainWithFallback, error) { + dom, err := net.PeerDomain(peeringID, make([]*ed25519.PublicKey, 0)) + if err != nil { + return nil, xerrors.Errorf("unable to allocate peer domain: %w", err) + } + ctx, ctxCancel := context.WithCancel(context.Background()) + df := DomainWithFallback{ + ctx: ctx, + ctxCancel: ctxCancel, + net: net, + dom: dom, + fallback: false, + mainPeers: make([]*ed25519.PublicKey, 0), + log: log, + } + go df.run() + return &df, nil +} + +func (df *DomainWithFallback) run() { + for { + select { + case <-df.ctx.Done(): + return + case <-time.After(1 * time.Second): + if df.fallback { + // Some peers could be made trusted/untrusted. Some can go online/offline. + // Thus we need to update the list of peers periodically. + // That is only needed of the fallback list is in use. + df.updateDomainPeers() + } + } + } +} + +// SetMainPeers updates the peer list as it is reported by the chain. +// We exclude the self peer here, because we use this to send messages to other nodes. +func (df *DomainWithFallback) SetMainPeers(peers []*ed25519.PublicKey) { + selfPubKey := df.net.Self().PubKey() + otherPeers := make([]*ed25519.PublicKey, 0) + for i := range peers { + if *peers[i] != *selfPubKey { + otherPeers = append(otherPeers, peers[i]) + } + } + df.log.Debugf("SetMainPeers: number of other mainPeers: %v, self dropped=%v", len(otherPeers), len(peers) != len(otherPeers)) + df.mainPeers = otherPeers + if !df.fallback { + df.updateDomainPeers() + } +} + +func (df *DomainWithFallback) HaveMainPeers() bool { + return len(df.mainPeers) > 0 +} + +func (df *DomainWithFallback) SetFallbackMode(fallback bool) { + if df.fallback == fallback { + return + } + df.log.Debugf("SetFallbackMode: fallback=%v", fallback) + df.fallback = fallback + df.updateDomainPeers() +} + +func (df *DomainWithFallback) GetFallbackMode() bool { + return df.fallback +} + +func (df *DomainWithFallback) updateDomainPeers() { + var peers []*ed25519.PublicKey + if df.fallback { + selfPubKey := df.net.Self().PubKey() + allTrusted := make([]*ed25519.PublicKey, 0) + for _, n := range df.net.PeerStatus() { + if n.IsAlive() && *n.PubKey() != *selfPubKey { + allTrusted = append(allTrusted, n.PubKey()) + } + } + peers = allTrusted + } else { + peers = df.mainPeers + } + df.log.Debugf("updateDomainPeers: in fallback=%v mode will use %v nodes.", df.fallback, len(peers)) + df.dom.UpdatePeers(peers) +} + +func (df *DomainWithFallback) Attach(receiver byte, callback func(recv *peering.PeerMessageIn)) interface{} { + return df.dom.Attach(receiver, callback) +} + +func (df *DomainWithFallback) Detach(attachID interface{}) { + df.dom.Detach(attachID) +} + +func (df *DomainWithFallback) Close() { + df.dom.Close() + df.ctxCancel() +} + +func (df *DomainWithFallback) GetRandomOtherPeers(upToNumPeers int) []*ed25519.PublicKey { + return df.dom.GetRandomOtherPeers(upToNumPeers) +} + +func (df *DomainWithFallback) SendMsgByPubKey(pubKey *ed25519.PublicKey, msgReceiver, msgType byte, msgData []byte) { + df.dom.SendMsgByPubKey(pubKey, msgReceiver, msgType, msgData) +} diff --git a/packages/chain/statemgr/eventproc.go b/packages/chain/statemgr/eventproc.go index c3a5a4c2cf..afcc9c5bf0 100644 --- a/packages/chain/statemgr/eventproc.go +++ b/packages/chain/statemgr/eventproc.go @@ -20,7 +20,7 @@ func (sm *stateManager) EnqueueGetBlockMsg(msg *messages.GetBlockMsgIn) { func (sm *stateManager) handleGetBlockMsg(msg *messages.GetBlockMsgIn) { sm.log.Debugw("handleGetBlockMsg: ", - "sender", msg.SenderNetID, + "sender", msg.SenderPubKey.String(), "block index", msg.BlockIndex, ) if sm.stateOutput == nil { // Not a necessary check, only for optimization. @@ -43,10 +43,10 @@ func (sm *stateManager) handleGetBlockMsg(msg *messages.GetBlockMsgIn) { return } - sm.log.Debugf("handleGetBlockMsg: responding to peer %s by block %v", msg.SenderNetID, msg.BlockIndex) + sm.log.Debugf("handleGetBlockMsg: responding to peer %s by block %v", msg.SenderPubKey.String(), msg.BlockIndex) blockMsg := &messages.BlockMsg{BlockBytes: blockBytes} - sm.chainPeers.SendMsgByNetID(msg.SenderNetID, peering.PeerMessageReceiverStateManager, peerMsgTypeBlock, util.MustBytes(blockMsg)) + sm.domain.SendMsgByPubKey(msg.SenderPubKey, peering.PeerMessageReceiverStateManager, peerMsgTypeBlock, util.MustBytes(blockMsg)) } // EventBlockMsg @@ -55,8 +55,9 @@ func (sm *stateManager) EnqueueBlockMsg(msg *messages.BlockMsgIn) { } func (sm *stateManager) handleBlockMsg(msg *messages.BlockMsgIn) { + sm.syncingBlocks.blockReceived() sm.log.Debugw("handleBlockMsg: ", - "sender", msg.SenderNetID, + "sender", msg.SenderPubKey.String(), ) if sm.stateOutput == nil { sm.log.Debugf("handleBlockMsg: message ignored: stateOutput is nil") @@ -64,11 +65,11 @@ func (sm *stateManager) handleBlockMsg(msg *messages.BlockMsgIn) { } block, err := state.BlockFromBytes(msg.BlockBytes) if err != nil { - sm.log.Warnf("handleBlockMsg: message ignored: wrong block received from peer %s. Err: %v", msg.SenderNetID, err) + sm.log.Warnf("handleBlockMsg: message ignored: wrong block received from peer %s. Err: %v", msg.SenderPubKey.String(), err) return } sm.log.Debugw("handleBlockMsg: adding block from peer ", - "sender", msg.SenderNetID, + "sender", msg.SenderPubKey.String(), "block index", block.BlockIndex(), "approving output", iscp.OID(block.ApprovingOutputID()), ) @@ -104,6 +105,7 @@ func (sm *stateManager) handleStateMsg(msg *messages.StateMsg) { "state index", msg.ChainOutput.GetStateIndex(), "chainOutput", iscp.OID(msg.ChainOutput.ID()), ) + sm.stateManagerMetrics.LastSeenStateIndex(msg.ChainOutput.GetStateIndex()) stateHash, err := hashing.HashValueFromBytes(msg.ChainOutput.GetStateData()) if err != nil { sm.log.Errorf("EventStateMsg ignored: failed to parse state hash: %v", err) diff --git a/packages/chain/statemgr/setup_test.go b/packages/chain/statemgr/setup_test.go index 66c0fc142c..5ee1257571 100644 --- a/packages/chain/statemgr/setup_test.go +++ b/packages/chain/statemgr/setup_test.go @@ -10,6 +10,7 @@ import ( "time" "github.com/iotaledger/wasp/packages/iscp/colored" + "github.com/iotaledger/wasp/packages/wal" "github.com/iotaledger/goshimmer/packages/ledgerstate" "github.com/iotaledger/goshimmer/packages/ledgerstate/utxodb" @@ -39,18 +40,18 @@ type MockedEnv struct { Ledger *utxodb.UtxoDB OriginatorKeyPair *ed25519.KeyPair OriginatorAddress ledgerstate.Address - NodeIDs []string + NodePubKeys []*ed25519.PublicKey NetworkProviders []peering.NetworkProvider NetworkBehaviour *testutil.PeeringNetDynamic NetworkCloser io.Closer ChainID *iscp.ChainID mutex sync.Mutex - Nodes map[string]*MockedNode + Nodes map[ed25519.PublicKey]*MockedNode push bool } type MockedNode struct { - NetID string + PubKey *ed25519.PublicKey Env *MockedEnv store kvstore.KVStore NodeConn *testchain.MockedNodeConn @@ -67,6 +68,8 @@ type MockedStateManagerMetrics struct{} func (c *MockedStateManagerMetrics) RecordBlockSize(_ uint32, _ float64) {} +func (c *MockedStateManagerMetrics) LastSeenStateIndex(_ uint32) {} + func NewMockedEnv(nodeCount int, t *testing.T, debug bool) (*MockedEnv, *ledgerstate.Transaction) { level := zapcore.InfoLevel if debug { @@ -79,7 +82,7 @@ func NewMockedEnv(nodeCount int, t *testing.T, debug bool) (*MockedEnv, *ledgers Ledger: utxodb.New(), OriginatorKeyPair: nil, OriginatorAddress: nil, - Nodes: make(map[string]*MockedNode), + Nodes: make(map[ed25519.PublicKey]*MockedNode), } ret.OriginatorKeyPair, ret.OriginatorAddress = ret.Ledger.NewKeyPairByIndex(0) _, err := ret.Ledger.RequestFunds(ret.OriginatorAddress) @@ -107,9 +110,9 @@ func NewMockedEnv(nodeCount int, t *testing.T, debug bool) (*MockedEnv, *ledgers ret.NetworkBehaviour = testutil.NewPeeringNetDynamic(log) - nodeIDs, identities := testpeers.SetupKeys(uint16(nodeCount)) - ret.NodeIDs = nodeIDs - ret.NetworkProviders, ret.NetworkCloser = testpeers.SetupNet(ret.NodeIDs, identities, ret.NetworkBehaviour, log) + nodeIDs, nodeIdentities := testpeers.SetupKeys(uint16(nodeCount)) + ret.NodePubKeys = testpeers.PublicKeys(nodeIdentities) + ret.NetworkProviders, ret.NetworkCloser = testpeers.SetupNet(nodeIDs, nodeIdentities, ret.NetworkBehaviour, log) return ret, originTx } @@ -185,14 +188,17 @@ func (env *MockedEnv) PullConfirmedOutputFromLedger(outputID ledgerstate.OutputI } func (env *MockedEnv) NewMockedNode(nodeIndex int, timers StateManagerTimers) *MockedNode { - nodeID := env.NodeIDs[nodeIndex] - log := env.Log.Named(nodeID) - peers, err := env.NetworkProviders[nodeIndex].PeerDomain(env.ChainID.Array(), env.NodeIDs) + nodePubKey := env.NodePubKeys[nodeIndex] + nodePubKeyStr := nodePubKey.String()[0:10] + log := env.Log.Named(nodePubKeyStr) + peers, err := env.NetworkProviders[nodeIndex].PeerDomain(env.ChainID.Array(), env.NodePubKeys) + require.NoError(env.T, err) + stateMgrDomain, err := NewDomainWithFallback(env.ChainID.Array(), env.NetworkProviders[nodeIndex], log) require.NoError(env.T, err) ret := &MockedNode{ - NetID: nodeID, + PubKey: nodePubKey, Env: env, - NodeConn: testchain.NewMockedNodeConnection("Node_" + nodeID), + NodeConn: testchain.NewMockedNodeConnection("Node_" + nodePubKeyStr), store: mapdb.NewMapDB(), stateSync: coreutil.NewChainStateSync(), ChainCore: testchain.NewMockedChainCore(env.T, env.ChainID, log), @@ -209,7 +215,7 @@ func (env *MockedEnv) NewMockedNode(nodeIndex int, timers StateManagerTimers) *M return state.NewOptimisticStateReader(ret.store, ret.stateSync) }) ret.ChainPeers.Attach(peering.PeerMessageReceiverStateManager, func(peerMsg *peering.PeerMessageIn) { - log.Debugf("State manager recvEvent from %v of type %v", peerMsg.SenderNetID, peerMsg.MsgType) + log.Debugf("State manager recvEvent from %v of type %v", peerMsg.SenderPubKey.String(), peerMsg.MsgType) switch peerMsg.MsgType { case peerMsgTypeGetBlock: msg, err := messages.NewGetBlockMsg(peerMsg.MsgData) @@ -218,8 +224,8 @@ func (env *MockedEnv) NewMockedNode(nodeIndex int, timers StateManagerTimers) *M return } ret.StateManager.EnqueueGetBlockMsg(&messages.GetBlockMsgIn{ - GetBlockMsg: *msg, - SenderNetID: peerMsg.SenderNetID, + GetBlockMsg: *msg, + SenderPubKey: peerMsg.SenderPubKey, }) case peerMsgTypeBlock: msg, err := messages.NewBlockMsg(peerMsg.MsgData) @@ -228,12 +234,12 @@ func (env *MockedEnv) NewMockedNode(nodeIndex int, timers StateManagerTimers) *M return } ret.StateManager.EnqueueBlockMsg(&messages.BlockMsgIn{ - BlockMsg: *msg, - SenderNetID: peerMsg.SenderNetID, + BlockMsg: *msg, + SenderPubKey: peerMsg.SenderPubKey, }) } }) - ret.StateManager = New(ret.store, ret.ChainCore, ret.ChainPeers, ret.NodeConn, stateMgrMetrics, timers) + ret.StateManager = New(ret.store, ret.ChainCore, stateMgrDomain, ret.NodeConn, stateMgrMetrics, wal.NewDefault(), timers) ret.StateTransition = testchain.NewMockedStateTransition(env.T, env.OriginatorKeyPair) ret.StateTransition.OnNextState(func(vstate state.VirtualStateAccess, tx *ledgerstate.Transaction) { log.Debugf("MockedEnv.onNextState: state index %d", vstate.BlockIndex()) @@ -310,14 +316,14 @@ func (env *MockedEnv) AddNode(node *MockedNode) { env.mutex.Lock() defer env.mutex.Unlock() - if _, ok := env.Nodes[node.NetID]; ok { - env.Log.Panicf("AddNode: duplicate node index %s", node.NetID) + if _, ok := env.Nodes[*node.PubKey]; ok { + env.Log.Panicf("AddNode: duplicate node index %s", node.PubKey.String()) } - env.Nodes[node.NetID] = node + env.Nodes[*node.PubKey] = node } func (env *MockedEnv) RemoveNode(node *MockedNode) { env.mutex.Lock() defer env.mutex.Unlock() - delete(env.Nodes, node.NetID) + delete(env.Nodes, *node.PubKey) } diff --git a/packages/chain/statemgr/statemgr.go b/packages/chain/statemgr/statemgr.go index af97409e56..9af59c0d91 100644 --- a/packages/chain/statemgr/statemgr.go +++ b/packages/chain/statemgr/statemgr.go @@ -10,6 +10,7 @@ import ( "time" "github.com/iotaledger/goshimmer/packages/ledgerstate" + "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/hive.go/kvstore" "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/wasp/packages/chain" @@ -26,7 +27,7 @@ type stateManager struct { ready *ready.Ready store kvstore.KVStore chain chain.ChainCore - chainPeers peering.PeerDomainProvider + domain *DomainWithFallback nodeConn chain.ChainNodeConnection pullStateRetryTime time.Time solidState state.VirtualStateAccess @@ -47,6 +48,7 @@ type stateManager struct { eventStateCandidateMsgPipe pipe.Pipe eventTimerMsgPipe pipe.Pipe stateManagerMetrics metrics.StateManagerMetrics + wal chain.WAL } var _ chain.StateManager = &stateManager{} @@ -60,7 +62,15 @@ const ( peerMsgTypeBlock ) -func New(store kvstore.KVStore, c chain.ChainCore, peers peering.PeerDomainProvider, nodeconn chain.ChainNodeConnection, stateManagerMetrics metrics.StateManagerMetrics, timersOpt ...StateManagerTimers) chain.StateManager { +func New( + store kvstore.KVStore, + c chain.ChainCore, + domain *DomainWithFallback, + nodeconn chain.ChainNodeConnection, + stateManagerMetrics metrics.StateManagerMetrics, + wal chain.WAL, + timersOpt ...StateManagerTimers, +) chain.StateManager { var timers StateManagerTimers if len(timersOpt) > 0 { timers = timersOpt[0] @@ -72,7 +82,7 @@ func New(store kvstore.KVStore, c chain.ChainCore, peers peering.PeerDomainProvi store: store, chain: c, nodeConn: nodeconn, - chainPeers: peers, + domain: domain, syncingBlocks: newSyncingBlocks(c.Log(), timers.GetBlockRetry), timers: timers, log: c.Log().Named("s"), @@ -84,8 +94,9 @@ func New(store kvstore.KVStore, c chain.ChainCore, peers peering.PeerDomainProvi eventStateCandidateMsgPipe: pipe.NewLimitInfinitePipe(maxMsgBuffer), eventTimerMsgPipe: pipe.NewLimitInfinitePipe(1), stateManagerMetrics: stateManagerMetrics, + wal: wal, } - ret.receivePeerMessagesAttachID = ret.chainPeers.Attach(peering.PeerMessageReceiverStateManager, ret.receiveChainPeerMessages) + ret.receivePeerMessagesAttachID = ret.domain.Attach(peering.PeerMessageReceiverStateManager, ret.receiveChainPeerMessages) ret.nodeConn.AttachToOutputReceived(ret.EnqueueOutputMsg) go ret.initLoadState() @@ -101,8 +112,8 @@ func (sm *stateManager) receiveChainPeerMessages(peerMsg *peering.PeerMessageIn) return } sm.EnqueueGetBlockMsg(&messages.GetBlockMsgIn{ - GetBlockMsg: *msg, - SenderNetID: peerMsg.SenderNetID, + GetBlockMsg: *msg, + SenderPubKey: peerMsg.SenderPubKey, }) case peerMsgTypeBlock: msg, err := messages.NewBlockMsg(peerMsg.MsgData) @@ -111,17 +122,22 @@ func (sm *stateManager) receiveChainPeerMessages(peerMsg *peering.PeerMessageIn) return } sm.EnqueueBlockMsg(&messages.BlockMsgIn{ - BlockMsg: *msg, - SenderNetID: peerMsg.SenderNetID, + BlockMsg: *msg, + SenderPubKey: peerMsg.SenderPubKey, }) default: sm.log.Warnf("Wrong type of state manager message: %v, ignoring it", peerMsg.MsgType) } } +func (sm *stateManager) SetChainPeers(peers []*ed25519.PublicKey) { + sm.domain.SetMainPeers(peers) +} + func (sm *stateManager) Close() { sm.nodeConn.DetachFromOutputReceived() - sm.chainPeers.Detach(sm.receivePeerMessagesAttachID) + sm.domain.Detach(sm.receivePeerMessagesAttachID) + sm.domain.Close() sm.eventGetBlockMsgPipe.Close() sm.eventBlockMsgPipe.Close() diff --git a/packages/chain/statemgr/statemgr_test.go b/packages/chain/statemgr/statemgr_test.go index 9447c27ec4..59878b6a6d 100644 --- a/packages/chain/statemgr/statemgr_test.go +++ b/packages/chain/statemgr/statemgr_test.go @@ -11,6 +11,7 @@ import ( "github.com/iotaledger/goshimmer/packages/ledgerstate" "github.com/iotaledger/goshimmer/packages/ledgerstate/utxoutil" + "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/wasp/packages/chain" "github.com/iotaledger/wasp/packages/state" "github.com/stretchr/testify/require" @@ -155,20 +156,24 @@ func TestManyStateTransitionsSeveralNodes(t *testing.T) { env, _ := NewMockedEnv(2, t, true) env.SetPushStateToNodesOption(true) - node := env.NewMockedNode(0, NewStateManagerTimers()) - node.StateManager.Ready().MustWait() - node.StartTimer() - - env.AddNode(node) + node0 := env.NewMockedNode(0, NewStateManagerTimers()) + node0.StateManager.Ready().MustWait() + node0.StartTimer() + node0.StateManager.SetChainPeers([]*ed25519.PublicKey{node0.PubKey}) + env.AddNode(node0) + env.Log.Infof("TestManyStateTransitionsSeveralNodes: node0.PubKey=%v", node0.PubKey.String()) const targetBlockIndex = 10 - node.OnStateTransitionMakeNewStateTransition(targetBlockIndex) - waitSyncBlockIndexAndCheck(10*time.Second, t, node, targetBlockIndex) + node0.OnStateTransitionMakeNewStateTransition(targetBlockIndex) + waitSyncBlockIndexAndCheck(10*time.Second, t, node0, targetBlockIndex) node1 := env.NewMockedNode(1, NewStateManagerTimers()) node1.StateManager.Ready().MustWait() node1.StartTimer() + node1.StateManager.SetChainPeers([]*ed25519.PublicKey{node0.PubKey, node1.PubKey}) + node0.StateManager.SetChainPeers([]*ed25519.PublicKey{node0.PubKey, node1.PubKey}) env.AddNode(node1) + env.Log.Infof("TestManyStateTransitionsSeveralNodes: node1.PubKey=%v", node1.PubKey.String()) waitSyncBlockIndexAndCheck(10*time.Second, t, node1, targetBlockIndex) } @@ -178,15 +183,19 @@ func TestManyStateTransitionsManyNodes(t *testing.T) { env, _ := NewMockedEnv(numberOfCatchingPeers+1, t, true) env.SetPushStateToNodesOption(true) - node := env.NewMockedNode(0, NewStateManagerTimers()) - node.StateManager.Ready().MustWait() - node.StartTimer() + allPubKeys := make([]*ed25519.PublicKey, 0) - env.AddNode(node) + node0 := env.NewMockedNode(0, NewStateManagerTimers()) + node0.StateManager.Ready().MustWait() + node0.StartTimer() + allPubKeys = append(allPubKeys, node0.PubKey) + + env.AddNode(node0) + node0.StateManager.SetChainPeers(allPubKeys) const targetBlockIndex = 5 - node.OnStateTransitionMakeNewStateTransition(targetBlockIndex) - waitSyncBlockIndexAndCheck(10*time.Second, t, node, targetBlockIndex) + node0.OnStateTransitionMakeNewStateTransition(targetBlockIndex) + waitSyncBlockIndexAndCheck(10*time.Second, t, node0, targetBlockIndex) catchingNodes := make([]*MockedNode, numberOfCatchingPeers) for i := 0; i < numberOfCatchingPeers; i++ { @@ -194,8 +203,11 @@ func TestManyStateTransitionsManyNodes(t *testing.T) { timers.GetBlockRetry = 200 * time.Millisecond catchingNodes[i] = env.NewMockedNode(i+1, timers) catchingNodes[i].StateManager.Ready().MustWait() + allPubKeys = append(allPubKeys, catchingNodes[i].PubKey) } + node0.StateManager.SetChainPeers(allPubKeys) for i := 0; i < numberOfCatchingPeers; i++ { + catchingNodes[i].StateManager.SetChainPeers(allPubKeys) catchingNodes[i].StartTimer() } for i := 0; i < numberOfCatchingPeers; i++ { @@ -212,20 +224,22 @@ func TestCatchUpNoConfirmedOutput(t *testing.T) { env, _ := NewMockedEnv(2, t, true) env.SetPushStateToNodesOption(true) - node := env.NewMockedNode(0, NewStateManagerTimers()) - node.StateManager.Ready().MustWait() - node.StartTimer() - - env.AddNode(node) + node0 := env.NewMockedNode(0, NewStateManagerTimers()) + node0.StateManager.Ready().MustWait() + node0.StartTimer() + node0.StateManager.SetChainPeers([]*ed25519.PublicKey{node0.PubKey}) + env.AddNode(node0) const targetBlockIndex = 10 - node.OnStateTransitionMakeNewStateTransition(targetBlockIndex) - node.NodeConn.OnPullConfirmedOutput(func(outputID ledgerstate.OutputID) {}) - waitSyncBlockIndexAndCheck(10*time.Second, t, node, targetBlockIndex) + node0.OnStateTransitionMakeNewStateTransition(targetBlockIndex) + node0.NodeConn.OnPullConfirmedOutput(func(outputID ledgerstate.OutputID) {}) + waitSyncBlockIndexAndCheck(10*time.Second, t, node0, targetBlockIndex) node1 := env.NewMockedNode(1, NewStateManagerTimers()) node1.StateManager.Ready().MustWait() node1.StartTimer() + node1.StateManager.SetChainPeers([]*ed25519.PublicKey{node0.PubKey, node1.PubKey}) + node0.StateManager.SetChainPeers([]*ed25519.PublicKey{node0.PubKey, node1.PubKey}) env.AddNode(node1) waitSyncBlockIndexAndCheck(10*time.Second, t, node1, targetBlockIndex) @@ -266,7 +280,7 @@ func TestNodeDisconnected(t *testing.T) { // Single node gets disconnected until state 6 handlerName := "DisconnectedPeer" - env.NetworkBehaviour.WithPeerDisconnected(&handlerName, disconnectedNode.NetID) + env.NetworkBehaviour.WithPeerDisconnected(&handlerName, disconnectedNode.PubKey) const targetBlockIndex2 = 6 connectedNodes[0].OnStateTransitionMakeNewStateTransition(targetBlockIndex2) connectedNodes[0].MakeNewStateTransition() @@ -285,7 +299,7 @@ func TestNodeDisconnected(t *testing.T) { waitSyncBlockIndexAndCheck(10*time.Second, t, disconnectedNode, targetBlockIndex3) // Node, producing transitions, gets disconnected until state 12 - env.NetworkBehaviour.WithPeerDisconnected(&handlerName, disconnectedNode.NetID) + env.NetworkBehaviour.WithPeerDisconnected(&handlerName, disconnectedNode.PubKey) const targetBlockIndex4 = 12 connectedNodes[0].OnStateTransitionDoNothing() disconnectedNode.OnStateTransitionMakeNewStateTransition(targetBlockIndex4) @@ -333,19 +347,21 @@ func TestCruelWorld(t *testing.T) { nodes[i] = env.NewMockedNode(i, timers) nodes[i].StateManager.Ready().MustWait() nodes[i].StartTimer() + nodes[i].StateManager.SetChainPeers(env.NodePubKeys) env.AddNode(nodes[i]) } - var disconnectedNodes []string + var disconnectedNodes []*ed25519.PublicKey var mutex sync.Mutex go func() { // Connection cutter for { time.Sleep(randFromIntervalFun(1000, 3000) * time.Millisecond) mutex.Lock() - nodeName := nodes[rand.Intn(numberOfPeers)].NetID - env.NetworkBehaviour.WithPeerDisconnected(&nodeName, nodeName) - env.Log.Debugf("Connection to node %v lost", nodeName) - disconnectedNodes = append(disconnectedNodes, nodeName) + nodePubkey := nodes[rand.Intn(numberOfPeers)].PubKey + handlerID := nodePubkey.String() + env.NetworkBehaviour.WithPeerDisconnected(&handlerID, nodePubkey) + env.Log.Debugf("Connection to node %v lost", nodePubkey.String()) + disconnectedNodes = append(disconnectedNodes, nodePubkey) mutex.Unlock() } }() @@ -355,9 +371,9 @@ func TestCruelWorld(t *testing.T) { time.Sleep(randFromIntervalFun(500, 2000) * time.Millisecond) mutex.Lock() if len(disconnectedNodes) > 0 { - env.NetworkBehaviour.RemoveHandler(disconnectedNodes[0]) + env.NetworkBehaviour.RemoveHandler(disconnectedNodes[0].String()) env.Log.Debugf("Connection to node %v restored", disconnectedNodes[0]) - disconnectedNodes[0] = "" + disconnectedNodes[0] = nil disconnectedNodes = disconnectedNodes[1:] } } diff --git a/packages/chain/statemgr/syncing_block.go b/packages/chain/statemgr/syncing_block.go index 2760024a01..85ea617733 100644 --- a/packages/chain/statemgr/syncing_block.go +++ b/packages/chain/statemgr/syncing_block.go @@ -13,15 +13,22 @@ import ( "github.com/iotaledger/wasp/packages/state" ) +const ( + pollFallbackDelay = 5 * time.Second +) + type syncingBlocks struct { blocks map[uint32]*syncingBlock // StateIndex -> BlockCandidates log *logger.Logger initialBlockRetry time.Duration + lastPullTime time.Time // Time, when we pulled for some block last time. + lastRecvTime time.Time // Time, when we received any block we pulled. Used to determine, if fallback nodes should be used. } type syncingBlock struct { requestBlockRetryTime time.Time blockCandidates map[hashing.HashValue]*candidateBlock + receivedFromWAL bool } func newSyncingBlocks(log *logger.Logger, initialBlockRetry time.Duration) *syncingBlocks { @@ -183,3 +190,37 @@ func (syncsT *syncingBlocks) restartSyncing() { func (syncsT *syncingBlocks) deleteSyncingBlock(stateIndex uint32) { delete(syncsT.blocks, stateIndex) } + +// +// Track poll/reception times, to determine, if no one responds to our polls. +// + +func (syncsT *syncingBlocks) blocksPulled() { + syncsT.lastPullTime = time.Now() +} + +func (syncsT *syncingBlocks) blockReceived() { + syncsT.lastRecvTime = time.Now() +} + +func (syncsT *syncingBlocks) blockPollFallbackNeeded() bool { + if len(syncsT.blocks) == 0 { + return false + } + return syncsT.lastPullTime.Sub(syncsT.lastRecvTime) >= pollFallbackDelay +} + +func (syncsT *syncingBlocks) setReceivedFromWAL(i uint32) { + block, ok := syncsT.blocks[i] + if ok { + block.receivedFromWAL = true + } +} + +func (syncsT *syncingBlocks) isObtainedFromWAL(i uint32) bool { + block, ok := syncsT.blocks[i] + if ok { + return block.receivedFromWAL + } + return false +} diff --git a/packages/chain/statemgr/syncmgr.go b/packages/chain/statemgr/syncmgr.go index aa0d023c94..795e403841 100644 --- a/packages/chain/statemgr/syncmgr.go +++ b/packages/chain/statemgr/syncmgr.go @@ -64,6 +64,9 @@ func (sm *stateManager) doSyncActionIfNeeded() { switch { case sm.solidState.BlockIndex() == sm.stateOutput.GetStateIndex(): sm.log.Debugf("doSyncAction not needed: state is already synced at index #%d", sm.stateOutput.GetStateIndex()) + if sm.domain.HaveMainPeers() { + sm.domain.SetFallbackMode(false) + } return case sm.solidState.BlockIndex() > sm.stateOutput.GetStateIndex(): sm.log.Debugf("BlockIndex=%v, StateIndex=%v", sm.solidState.BlockIndex(), sm.stateOutput.GetStateIndex()) @@ -72,9 +75,18 @@ func (sm *stateManager) doSyncActionIfNeeded() { // not synced startSyncFromIndex := sm.solidState.BlockIndex() + 1 sm.log.Debugf("doSyncAction: trying to sync state from index %v to %v", startSyncFromIndex, sm.stateOutput.GetStateIndex()) + if !sm.domain.HaveMainPeers() || sm.syncingBlocks.blockPollFallbackNeeded() { + sm.domain.SetFallbackMode(true) + } for i := startSyncFromIndex; i <= sm.stateOutput.GetStateIndex(); i++ { requestBlockRetryTime := sm.syncingBlocks.getRequestBlockRetryTime(i) blockCandidatesCount := sm.syncingBlocks.getBlockCandidatesCount(i) + if blockCandidatesCount == 0 { + if sm.candidateBlockInWAL(i) { + blockCandidatesCount++ + sm.syncingBlocks.setReceivedFromWAL(i) + } + } approvedBlockCandidatesCount := sm.syncingBlocks.getApprovedBlockCandidatesCount(i) sm.log.Debugf("doSyncAction: trying to sync state for index %v; requestBlockRetryTime %v, blockCandidates count %v, approved blockCandidates count %v", i, requestBlockRetryTime, blockCandidatesCount, approvedBlockCandidatesCount) @@ -84,11 +96,15 @@ func (sm *stateManager) doSyncActionIfNeeded() { return } nowis := time.Now() - if nowis.After(requestBlockRetryTime) { + if !sm.syncingBlocks.isObtainedFromWAL(i) && nowis.After(requestBlockRetryTime) { // have to pull - sm.log.Debugf("doSyncAction: requesting block index %v from %v random peers", i, numberOfNodesToRequestBlockFromConst) + sm.log.Debugf("doSyncAction: requesting block index %v, fallback=%v from %v random peers.", i, sm.domain.GetFallbackMode(), numberOfNodesToRequestBlockFromConst) getBlockMsg := &messages.GetBlockMsg{BlockIndex: i} - sm.chainPeers.SendPeerMsgToRandomPeers(numberOfNodesToRequestBlockFromConst, peering.PeerMessageReceiverStateManager, peerMsgTypeGetBlock, util.MustBytes(getBlockMsg)) + for _, p := range sm.domain.GetRandomOtherPeers(numberOfNodesToRequestBlockFromConst) { + sm.domain.SendMsgByPubKey(p, peering.PeerMessageReceiverStateManager, peerMsgTypeGetBlock, util.MustBytes(getBlockMsg)) + sm.syncingBlocks.blocksPulled() + sm.log.Debugf("doSyncAction: requesting block index %v,from %v", i, p.String()) + } sm.syncingBlocks.startSyncingIfNeeded(i) sm.syncingBlocks.setRequestBlockRetryTime(i, nowis.Add(sm.timers.GetBlockRetry)) if blockCandidatesCount == 0 { @@ -108,6 +124,35 @@ func (sm *stateManager) doSyncActionIfNeeded() { } } +func (sm *stateManager) candidateBlockInWAL(i uint32) bool { + if !sm.wal.Contains(i) { + sm.log.Debugf("candidateBlockInWAL: block with index %d not found in wal.", i) + return false + } + blockBytes, err := sm.wal.Read(i) + if err != nil { + sm.log.Debugf("candidateBlockInWAL: error reading block bytes for %d. %v", i, err) + return false + } + block, err := state.BlockFromBytes(blockBytes) + if err != nil { + sm.log.Debugf("candidateBlockInWAL: error reading block bytes for %d. %v", i, err) + return false + } + nextState := sm.solidState.Copy() + err = nextState.ApplyBlock(block) + if err != nil { + sm.log.Debugf("candidateBlockInWAL: error applying block %d. %v", i, err) + return false + } + _, candidate := sm.syncingBlocks.addBlockCandidate(block, nextState) + if candidate == nil { + return false + } + candidate.approveIfRightOutput(sm.stateOutput) + return true +} + func (sm *stateManager) getCandidatesToCommit(candidateAcc []*candidateBlock, calculatedPrevState state.VirtualStateAccess, fromStateIndex, toStateIndex uint32) ([]*candidateBlock, state.VirtualStateAccess, bool) { sm.log.Debugf("getCandidatesToCommit from %v to %v", fromStateIndex, toStateIndex) if fromStateIndex > toStateIndex { diff --git a/packages/chains/chains.go b/packages/chains/chains.go index ca40a77ab7..f55a84a65e 100644 --- a/packages/chains/chains.go +++ b/packages/chains/chains.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package chains import ( @@ -12,10 +15,10 @@ import ( "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/metrics" "github.com/iotaledger/wasp/packages/metrics/nodeconnmetrics" - "github.com/iotaledger/wasp/packages/parameters" "github.com/iotaledger/wasp/packages/peering" "github.com/iotaledger/wasp/packages/registry" "github.com/iotaledger/wasp/packages/vm/processors" + "github.com/iotaledger/wasp/packages/wal" "golang.org/x/xerrors" ) @@ -81,7 +84,7 @@ func (c *Chains) SetNodeConn(nodeConn chain.NodeConnection) { c.nodeConn = nodeConn } -func (c *Chains) ActivateAllFromRegistry(registryProvider registry.Provider, allMetrics *metrics.Metrics) error { +func (c *Chains) ActivateAllFromRegistry(registryProvider registry.Provider, allMetrics *metrics.Metrics, w *wal.WAL) error { chainRecords, err := registryProvider().GetChainRecords() if err != nil { return err @@ -95,7 +98,7 @@ func (c *Chains) ActivateAllFromRegistry(registryProvider registry.Provider, all for _, chr := range chainRecords { if chr.Active { - if err := c.Activate(chr, registryProvider, allMetrics); err != nil { + if err := c.Activate(chr, registryProvider, allMetrics, w); err != nil { c.log.Errorf("cannot activate chain %s: %v", chr.ChainID, err) } } @@ -107,7 +110,7 @@ func (c *Chains) ActivateAllFromRegistry(registryProvider registry.Provider, all // - creates chain object // - insert it into the runtime registry // - subscribes for related transactions in he IOTA node -func (c *Chains) Activate(chr *registry.ChainRecord, registryProvider registry.Provider, allMetrics *metrics.Metrics) error { +func (c *Chains) Activate(chr *registry.ChainRecord, registryProvider registry.Provider, allMetrics *metrics.Metrics, w *wal.WAL) error { c.mutex.Lock() defer c.mutex.Unlock() @@ -121,33 +124,28 @@ func (c *Chains) Activate(chr *registry.ChainRecord, registryProvider registry.P return nil } // create new chain object - peerNetworkConfig, err := peering.NewStaticPeerNetworkConfigProvider( - parameters.GetString(parameters.PeeringMyNetID), - parameters.GetInt(parameters.PeeringPort), - chr.Peers..., - ) - if err != nil { - return xerrors.Errorf("cannot create peer network config provider") - } - defaultRegistry := registryProvider() chainKVStore := c.getOrCreateKVStore(chr.ChainID) chainMetrics := allMetrics.NewChainMetrics(chr.ChainID) + chainWAL, err := w.NewChainWAL(chr.ChainID) + if err != nil { + c.log.Debugf("Error creating wal object: %v", err) + chainWAL = wal.NewDefault() + } newChain := chainimpl.NewChain( chr.ChainID, c.log, c.nodeConn, - peerNetworkConfig, chainKVStore, c.networkProvider, defaultRegistry, defaultRegistry, - defaultRegistry, c.processorConfig, c.offledgerBroadcastUpToNPeers, c.offledgerBroadcastInterval, c.pullMissingRequestsFromCommittee, chainMetrics, + chainWAL, ) if newChain == nil { return xerrors.New("Chains.Activate: failed to create chain object") diff --git a/packages/chains/chains_test.go b/packages/chains/chains_test.go index c89076a039..30c897cad6 100644 --- a/packages/chains/chains_test.go +++ b/packages/chains/chains_test.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package chains import ( diff --git a/packages/dashboard/base.go b/packages/dashboard/base.go index 7e2b41737d..0248348832 100644 --- a/packages/dashboard/base.go +++ b/packages/dashboard/base.go @@ -48,6 +48,7 @@ type WaspServices interface { CallView(chainID *iscp.ChainID, scName, fname string, params dict.Dict) (dict.Dict, error) GetChainNodeConnectionMetrics(*iscp.ChainID) (nodeconnmetrics.NodeConnectionMessagesMetrics, error) GetNodeConnectionMetrics() (nodeconnmetrics.NodeConnectionMetrics, error) + GetChainConsensusWorkflowStatus(*iscp.ChainID) (chain.ConsensusWorkflowStatus, error) } type Dashboard struct { @@ -108,6 +109,7 @@ func (d *Dashboard) makeTemplate(e *echo.Echo, parts ...string) *template.Templa "decUint32": decUint32, "bytesToString": bytesToString, "keyToString": keyToString, + "anythingToString": anythingToString, "base58": base58.Encode, "replace": strings.Replace, "uri": func(s string, p ...interface{}) string { return e.Reverse(s, p...) }, diff --git a/packages/dashboard/chainlist.go b/packages/dashboard/chainlist.go index 468c935a90..75ba816a10 100644 --- a/packages/dashboard/chainlist.go +++ b/packages/dashboard/chainlist.go @@ -1,10 +1,13 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package dashboard import ( _ "embed" "net/http" - "github.com/iotaledger/wasp/packages/registry" + "github.com/iotaledger/wasp/packages/iscp" "github.com/labstack/echo/v4" ) @@ -42,11 +45,20 @@ func (d *Dashboard) fetchChains() ([]*ChainOverview, error) { } r := make([]*ChainOverview, len(crs)) for i, cr := range crs { - info, err := d.fetchRootInfo(cr.ChainID) + rootInfo, err := d.fetchRootInfo(cr.ChainID) + if err != nil { + return nil, err + } + cmtInfo, err := d.wasp.GetChainCommitteeInfo(cr.ChainID) + if err != nil { + return nil, err + } r[i] = &ChainOverview{ - ChainRecord: cr, - RootInfo: info, - Error: err, + ChainID: cr.ChainID, + Active: cr.Active, + RootInfo: rootInfo, + CommitteeSize: len(cmtInfo.PeerStatus), + Error: err, } } return r, nil @@ -58,7 +70,9 @@ type ChainListTemplateParams struct { } type ChainOverview struct { - ChainRecord *registry.ChainRecord - RootInfo RootInfo - Error error + ChainID *iscp.ChainID + Active bool + RootInfo RootInfo + CommitteeSize int + Error error } diff --git a/packages/dashboard/metrics.go b/packages/dashboard/metrics.go index c160cde263..acb2546b60 100644 --- a/packages/dashboard/metrics.go +++ b/packages/dashboard/metrics.go @@ -13,7 +13,9 @@ var tplMetrics string func (d *Dashboard) metricsInit(e *echo.Echo, r renderer) Tab { ret := d.initMetrics(e, r) d.initMetricsNodeconn(e, r) - d.initMetricsNodeconnMessages(e, r) + d.initMetricsChain(e, r) + d.initMetricsChainNodeconn(e, r) + d.initMetricsChainConsensus(e, r) return ret } @@ -21,7 +23,7 @@ func (d *Dashboard) initMetrics(e *echo.Echo, r renderer) Tab { route := e.GET("/metrics", d.handleMetrics) route.Name = "metrics" - r[route.Path] = d.makeTemplate(e, tplMetrics) + r[route.Path] = d.makeTemplate(e, tplMetricsChain, tplMetrics) return Tab{ Path: route.Path, @@ -31,11 +33,17 @@ func (d *Dashboard) initMetrics(e *echo.Echo, r renderer) Tab { } func (d *Dashboard) handleMetrics(c echo.Context) error { + chains, err := d.fetchChains() + if err != nil { + return err + } return c.Render(http.StatusOK, c.Path(), &MetricsTemplateParams{ BaseTemplateParams: d.BaseParams(c), + Chains: chains, }) } type MetricsTemplateParams struct { BaseTemplateParams + Chains []*ChainOverview } diff --git a/packages/dashboard/metrics_chain.go b/packages/dashboard/metrics_chain.go new file mode 100644 index 0000000000..5252ece1ac --- /dev/null +++ b/packages/dashboard/metrics_chain.go @@ -0,0 +1,44 @@ +package dashboard + +import ( + _ "embed" + "fmt" + "net/http" + + "github.com/iotaledger/wasp/packages/iscp" + "github.com/labstack/echo/v4" +) + +//go:embed templates/metrics_chain.tmpl +var tplMetricsChain string + +func metricsChainBreadcrumb(e *echo.Echo, chainID *iscp.ChainID) Tab { + return Tab{ + Path: e.Reverse("metricsChain"), + Title: fmt.Sprintf("Metrics: %.8s", chainID.Base58()), + Href: e.Reverse("metricsChain", chainID.Base58()), + } +} + +func (d *Dashboard) initMetricsChain(e *echo.Echo, r renderer) { + route := e.GET("/metrics/:chainid", d.handleMetricsChain) + route.Name = "metricsChain" + r[route.Path] = d.makeTemplate(e, tplMetricsChain) +} + +func (d *Dashboard) handleMetricsChain(c echo.Context) error { + chainID, err := iscp.ChainIDFromBase58(c.Param("chainid")) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, err) + } + tab := metricsChainBreadcrumb(c.Echo(), chainID) + return c.Render(http.StatusOK, c.Path(), &MetricsChainTemplateParams{ + BaseTemplateParams: d.BaseParams(c, tab), + ChainID: chainID.Base58(), + }) +} + +type MetricsChainTemplateParams struct { + BaseTemplateParams + ChainID string +} diff --git a/packages/dashboard/metrics_chain_consensus.go b/packages/dashboard/metrics_chain_consensus.go new file mode 100644 index 0000000000..41c5ab7127 --- /dev/null +++ b/packages/dashboard/metrics_chain_consensus.go @@ -0,0 +1,52 @@ +//nolint:dupl +package dashboard + +import ( + _ "embed" + "fmt" + "net/http" + + "github.com/iotaledger/wasp/packages/chain" + "github.com/iotaledger/wasp/packages/iscp" + "github.com/labstack/echo/v4" +) + +//go:embed templates/metrics_chain_consensus.tmpl +var tplMetricsChainConsensus string + +func metricsChainConsensusBreadcrumb(e *echo.Echo, chainID *iscp.ChainID) Tab { + return Tab{ + Path: e.Reverse("metricsChainConsensus"), + Title: fmt.Sprintf("Metrics: %.8s: Consensus", chainID.Base58()), + Href: e.Reverse("metricsChainConsensus", chainID.Base58()), + } +} + +func (d *Dashboard) initMetricsChainConsensus(e *echo.Echo, r renderer) { + route := e.GET("/metrics/:chainid/consensus", d.handleMetricsChainConsensus) + route.Name = "metricsChainConsensus" + r[route.Path] = d.makeTemplate(e, tplMetricsChainConsensus) +} + +func (d *Dashboard) handleMetricsChainConsensus(c echo.Context) error { + chainID, err := iscp.ChainIDFromBase58(c.Param("chainid")) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, err) + } + tab := metricsChainConsensusBreadcrumb(c.Echo(), chainID) + status, err := d.wasp.GetChainConsensusWorkflowStatus(chainID) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, err) + } + return c.Render(http.StatusOK, c.Path(), &MetricsChainConsensusTemplateParams{ + BaseTemplateParams: d.BaseParams(c, metricsChainBreadcrumb(c.Echo(), chainID), tab), + ChainID: chainID.Base58(), + Status: status, + }) +} + +type MetricsChainConsensusTemplateParams struct { + BaseTemplateParams + ChainID string + Status chain.ConsensusWorkflowStatus +} diff --git a/packages/dashboard/metrics_chain_nodeconn.go b/packages/dashboard/metrics_chain_nodeconn.go new file mode 100644 index 0000000000..b1c0cd88bc --- /dev/null +++ b/packages/dashboard/metrics_chain_nodeconn.go @@ -0,0 +1,52 @@ +//nolint:dupl +package dashboard + +import ( + _ "embed" + "fmt" + "net/http" + + "github.com/iotaledger/wasp/packages/iscp" + "github.com/iotaledger/wasp/packages/metrics/nodeconnmetrics" + "github.com/labstack/echo/v4" +) + +//go:embed templates/metrics_chain_nodeconn.tmpl +var tplMetricsChainNodeconn string + +func metricsChainNodeconnBreadcrumb(e *echo.Echo, chainID *iscp.ChainID) Tab { + return Tab{ + Path: e.Reverse("metricsChainNodeconn"), + Title: fmt.Sprintf("Metrics: %.8s: Connection to L1", chainID.Base58()), + Href: e.Reverse("metricsChainNodeconn", chainID.Base58()), + } +} + +func (d *Dashboard) initMetricsChainNodeconn(e *echo.Echo, r renderer) { + route := e.GET("/metrics/:chainid/nodeconn", d.handleMetricsChainNodeconn) + route.Name = "metricsChainNodeconn" + r[route.Path] = d.makeTemplate(e, tplMetricsChainNodeconn) +} + +func (d *Dashboard) handleMetricsChainNodeconn(c echo.Context) error { + chainID, err := iscp.ChainIDFromBase58(c.Param("chainid")) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, err) + } + tab := metricsChainNodeconnBreadcrumb(c.Echo(), chainID) + metrics, err := d.wasp.GetChainNodeConnectionMetrics(chainID) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, err) + } + return c.Render(http.StatusOK, c.Path(), &MetricsChainNodeconnTemplateParams{ + BaseTemplateParams: d.BaseParams(c, metricsChainBreadcrumb(c.Echo(), chainID), tab), + ChainID: chainID.Base58(), + Metrics: metrics, + }) +} + +type MetricsChainNodeconnTemplateParams struct { + BaseTemplateParams + ChainID string + Metrics nodeconnmetrics.NodeConnectionMessagesMetrics +} diff --git a/packages/dashboard/metrics_nodeconn.go b/packages/dashboard/metrics_nodeconn.go index 8c1b0b5ace..ffbbf9eb03 100644 --- a/packages/dashboard/metrics_nodeconn.go +++ b/packages/dashboard/metrics_nodeconn.go @@ -22,14 +22,10 @@ func metricsNodeconnBreadcrumb(e *echo.Echo) Tab { func (d *Dashboard) initMetricsNodeconn(e *echo.Echo, r renderer) { route := e.GET("/metrics/nodeconn", d.handleMetricsNodeconn) route.Name = "metricsNodeconn" - r[route.Path] = d.makeTemplate(e, tplMetricsNodeconnMessages, tplMetricsNodeconn) + r[route.Path] = d.makeTemplate(e, tplMetricsChainNodeconn, tplMetricsNodeconn) } func (d *Dashboard) handleMetricsNodeconn(c echo.Context) error { - chains, err := d.fetchChains() - if err != nil { - return err - } metrics, err := d.wasp.GetNodeConnectionMetrics() if err != nil { return echo.NewHTTPError(http.StatusBadRequest, err) @@ -37,13 +33,11 @@ func (d *Dashboard) handleMetricsNodeconn(c echo.Context) error { tab := metricsNodeconnBreadcrumb(c.Echo()) return c.Render(http.StatusOK, c.Path(), &MetricsNodeconnTemplateParams{ BaseTemplateParams: d.BaseParams(c, tab), - Chains: chains, Metrics: metrics, }) } type MetricsNodeconnTemplateParams struct { BaseTemplateParams - Chains []*ChainOverview Metrics nodeconnmetrics.NodeConnectionMetrics } diff --git a/packages/dashboard/metrics_nodeconn_messages.go b/packages/dashboard/metrics_nodeconn_messages.go deleted file mode 100644 index b4691b26b2..0000000000 --- a/packages/dashboard/metrics_nodeconn_messages.go +++ /dev/null @@ -1,49 +0,0 @@ -package dashboard - -import ( - _ "embed" - "fmt" - "net/http" - - "github.com/iotaledger/wasp/packages/iscp" - "github.com/iotaledger/wasp/packages/metrics/nodeconnmetrics" - "github.com/labstack/echo/v4" -) - -//go:embed templates/metrics_nodeconn_messages.tmpl -var tplMetricsNodeconnMessages string - -func metricsNodeconnMessagesBreadcrumb(e *echo.Echo, chainID *iscp.ChainID) Tab { - return Tab{ - Path: e.Reverse("metricsNodeconnMessages"), - Title: fmt.Sprintf("Metrics: Connection to L1: %.8s", chainID.Base58()), - Href: e.Reverse("metricsNodeconnMessages", chainID.Base58()), - } -} - -func (d *Dashboard) initMetricsNodeconnMessages(e *echo.Echo, r renderer) { - route := e.GET("/metrics/nodeconn/:chainid", d.handleMetricsNodeconnMessages) - route.Name = "metricsNodeconnMessages" - r[route.Path] = d.makeTemplate(e, tplMetricsNodeconnMessages) -} - -func (d *Dashboard) handleMetricsNodeconnMessages(c echo.Context) error { - chainID, err := iscp.ChainIDFromBase58(c.Param("chainid")) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, err) - } - tab := metricsNodeconnMessagesBreadcrumb(c.Echo(), chainID) - metrics, err := d.wasp.GetChainNodeConnectionMetrics(chainID) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, err) - } - return c.Render(http.StatusOK, c.Path(), &MetricsNodeconnMessagesTemplateParams{ - BaseTemplateParams: d.BaseParams(c, metricsNodeconnBreadcrumb(c.Echo()), tab), - Metrics: metrics, - }) -} - -type MetricsNodeconnMessagesTemplateParams struct { - BaseTemplateParams - Metrics nodeconnmetrics.NodeConnectionMessagesMetrics -} diff --git a/packages/dashboard/mock_test.go b/packages/dashboard/mock_test.go index 6a67a13cc4..7c274c7efe 100644 --- a/packages/dashboard/mock_test.go +++ b/packages/dashboard/mock_test.go @@ -26,6 +26,8 @@ type waspServicesMock struct { chains map[[ledgerstate.AddressLength]byte]*solo.Chain } +var _ WaspServices = &waspServicesMock{} + func (w *waspServicesMock) ConfigDump() map[string]interface{} { return map[string]interface{}{ "foo": "bar", @@ -104,6 +106,14 @@ func (w *waspServicesMock) GetChainCommitteeInfo(chainID *iscp.ChainID) (*chain. if !ok { return nil, xerrors.Errorf("chain not found") } + pubKey0, err := ed25519.PublicKeyFromString("AaKwV3ezdM8DcGKwJ6eRaJ2946D1yghqfpBDatGip1dX") + if err != nil { + return nil, err + } + pubKey1, err := ed25519.PublicKeyFromString("AaKwV3ezdM8DcGKwJ6eRaJ2946D1yghqfpBDatGip1dX") + if err != nil { + return nil, err + } return &chain.CommitteeInfo{ Address: ledgerstate.NewED25519Address(ed25519.PublicKey{}), Size: 2, @@ -112,14 +122,14 @@ func (w *waspServicesMock) GetChainCommitteeInfo(chainID *iscp.ChainID) (*chain. PeerStatus: []*chain.PeerStatus{ { Index: 0, - PeeringID: "0", - IsSelf: true, + NetID: "localhost:2000", + PubKey: &pubKey0, Connected: true, }, { Index: 1, - PeeringID: "1", - IsSelf: false, + NetID: "localhost:2001", + PubKey: &pubKey1, Connected: true, }, }, @@ -134,6 +144,10 @@ func (w *waspServicesMock) GetNodeConnectionMetrics() (nodeconnmetrics.NodeConne panic("Not implemented") } +func (w *waspServicesMock) GetChainConsensusWorkflowStatus(chainID *iscp.ChainID) (chain.ConsensusWorkflowStatus, error) { + panic("Not implemented") +} + type dashboardTestEnv struct { wasp *waspServicesMock echo *echo.Echo diff --git a/packages/dashboard/templates/base.tmpl b/packages/dashboard/templates/base.tmpl index a8b2cb3297..608c1f6975 100644 --- a/packages/dashboard/templates/base.tmpl +++ b/packages/dashboard/templates/base.tmpl @@ -39,6 +39,19 @@ {{end}} +{{define "longStringCell"}} + {{ $longString := anythingToString . }} + {{ trim 100 (replace $longString "\n" "" -1) }} +{{end}} + +{{define "booleanValue"}} + +{{end}} + {{define "base"}} diff --git a/packages/dashboard/templates/chain.tmpl b/packages/dashboard/templates/chain.tmpl index aeec2d65ed..5638d6af0f 100644 --- a/packages/dashboard/templates/chain.tmpl +++ b/packages/dashboard/templates/chain.tmpl @@ -88,16 +88,17 @@

Committee

Address
{{template "address" .Committee.Address}}
-
Size
{{.Committee.Size}}
-
Quorum
{{.Committee.Quorum}}
-
Quorum status
{{if .Committee.QuorumIsAlive}}up{{else}}down{{end}}
+
Size
{{.Committee.Size}}
+
Quorum
{{.Committee.Quorum}}
+
Quorum status
{{if .Committee.QuorumIsAlive}}up{{else}}down{{end}}

Peer status

- + + @@ -105,7 +106,8 @@ {{range $_, $s := .Committee.PeerStatus}} - + + {{end}} diff --git a/packages/dashboard/templates/chainlist.tmpl b/packages/dashboard/templates/chainlist.tmpl index ca835a5ffb..df232753b4 100644 --- a/packages/dashboard/templates/chainlist.tmpl +++ b/packages/dashboard/templates/chainlist.tmpl @@ -15,14 +15,14 @@ {{range $_, $c := .Chains}} - {{ $id := $c.ChainRecord.ChainID.Base58 }} + {{ $id := $c.ChainID.Base58 }} - + - + {{end}} diff --git a/packages/dashboard/templates/metrics.tmpl b/packages/dashboard/templates/metrics.tmpl index ccf0dca056..8c5c429eb5 100644 --- a/packages/dashboard/templates/metrics.tmpl +++ b/packages/dashboard/templates/metrics.tmpl @@ -2,10 +2,20 @@ {{define "body"}}
-

Metrics

- +

Global metrics

+ +

Chain metrics

+
    + {{range $_, $c := .Chains}} + {{ $id := $c.ChainRecord.ChainID.Base58 }} +
  • + {{ $id }} + {{template "metricsChainAll" (args $id)}} +
  • + {{end}} +
{{end}} diff --git a/packages/dashboard/templates/metrics_chain.tmpl b/packages/dashboard/templates/metrics_chain.tmpl new file mode 100644 index 0000000000..0fc3de64be --- /dev/null +++ b/packages/dashboard/templates/metrics_chain.tmpl @@ -0,0 +1,16 @@ +{{define "metricsChainAll"}} + {{ $id := (index . 0) }} + +{{end}} + +{{define "title"}}Chain metrics{{end}} + +{{define "body"}} +
+

{{.ChainID}}

+ {{template "metricsChainAll" (args .ChainID)}} +
+{{end}} diff --git a/packages/dashboard/templates/metrics_chain_consensus.tmpl b/packages/dashboard/templates/metrics_chain_consensus.tmpl new file mode 100644 index 0000000000..ca40c2d5c7 --- /dev/null +++ b/packages/dashboard/templates/metrics_chain_consensus.tmpl @@ -0,0 +1,63 @@ +{{define "title"}}Consensus status{{end}} + +{{define "body"}} +
+

Workflow

+
IndexIDPubKeyNetID Status
{{$s.Index}}{{$s.PeeringID}}{{$s.PubKey.String}}{{$s.NetID}} {{if $s.Connected}}up{{else}}down{{end}}
{{ if not $c.Error }}{{ $id }}{{ else }}{{ $id }}{{ end }} {{ trim 50 $c.RootInfo.Description }} {{- if $c.Error }}
{{ $c.Error }}
{{ end }}
{{if not $c.Error}}{{ len $c.ChainRecord.Peers }}{{ end }}{{if not $c.Error}}{{ $c.CommitteeSize }}{{ end }} {{if not $c.Error}}{{ len $c.RootInfo.Contracts }}{{ end }}{{ if $c.ChainRecord.Active }} yes {{ else }} no {{ end }}{{ if $c.Active }} yes {{ else }} no {{ end }}
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Flag nameStatusTriger time
State received{{ template "booleanValue" (.Status.IsStateReceived) }}
Batch proposal sent{{ template "booleanValue" (.Status.IsBatchProposalSent) }}{{ (formatTimestampOrNever (.Status.GetBatchProposalSentTime)) }}
Consensus on batch reached{{ template "booleanValue" (.Status.IsConsensusBatchKnown) }}{{ (formatTimestampOrNever (.Status.GetConsensusBatchKnownTime)) }}
Virtual machine started{{ template "booleanValue" (.Status.IsVMStarted) }}{{ (formatTimestampOrNever (.Status.GetVMStartedTime)) }}
Virtual machine result signed{{ template "booleanValue" (.Status.IsVMResultSigned) }}{{ (formatTimestampOrNever (.Status.GetVMResultSignedTime)) }}
Transaction finalized{{ template "booleanValue" (.Status.IsTransactionFinalized) }}{{ (formatTimestampOrNever (.Status.GetTransactionFinalizedTime)) }}
Transaction posted to L1{{ template "booleanValue" (.Status.IsTransactionPosted) }}{{ (formatTimestampOrNever (.Status.GetTransactionPostedTime)) }}
Transaction seen by L1{{ template "booleanValue" (.Status.IsTransactionSeen) }}{{ (formatTimestampOrNever (.Status.GetTransactionSeenTime)) }}
Consensus is completed{{ template "booleanValue" (not (.Status.IsInProgress)) }}{{ (formatTimestampOrNever (.Status.GetCompletedTime)) }}
+ +{{end}} diff --git a/packages/dashboard/templates/metrics_nodeconn_messages.tmpl b/packages/dashboard/templates/metrics_chain_nodeconn.tmpl similarity index 75% rename from packages/dashboard/templates/metrics_nodeconn_messages.tmpl rename to packages/dashboard/templates/metrics_chain_nodeconn.tmpl index b3115cdae5..93b32e73e5 100644 --- a/packages/dashboard/templates/metrics_nodeconn_messages.tmpl +++ b/packages/dashboard/templates/metrics_chain_nodeconn.tmpl @@ -16,62 +16,62 @@ OUT {{ (($metrics.GetOutPullState).GetMessageTotal) }} {{ (formatTimestampOrNever (($metrics.GetOutPullState).GetLastEvent)) }} - {{ (($metrics.GetOutPullState).GetLastMessage) }} + {{ template "longStringCell" (($metrics.GetOutPullState).GetLastMessage)}} Pull tx inclusion state OUT {{ (($metrics.GetOutPullTransactionInclusionState).GetMessageTotal) }} {{ (formatTimestampOrNever (($metrics.GetOutPullTransactionInclusionState).GetLastEvent)) }} - {{ (($metrics.GetOutPullTransactionInclusionState).GetLastMessage) }} + {{ template "longStringCell" (($metrics.GetOutPullTransactionInclusionState).GetLastMessage)}} Pull confirmed output OUT {{ (($metrics.GetOutPullConfirmedOutput).GetMessageTotal) }} {{ (formatTimestampOrNever (($metrics.GetOutPullConfirmedOutput).GetLastEvent)) }} - {{ (($metrics.GetOutPullConfirmedOutput).GetLastMessage) }} + {{ template "longStringCell" (($metrics.GetOutPullConfirmedOutput).GetLastMessage)}} Post transaction OUT {{ (($metrics.GetOutPostTransaction).GetMessageTotal) }} {{ (formatTimestampOrNever (($metrics.GetOutPostTransaction).GetLastEvent)) }} - {{ (($metrics.GetOutPostTransaction).GetLastMessage) }} + {{ template "longStringCell" (($metrics.GetOutPostTransaction).GetLastMessage)}} Transaction IN {{ (($metrics.GetInTransaction).GetMessageTotal) }} {{ (formatTimestampOrNever (($metrics.GetInTransaction).GetLastEvent)) }} - {{ (($metrics.GetInTransaction).GetLastMessage) }} + {{ template "longStringCell" (($metrics.GetInTransaction).GetLastMessage)}} Inclusion state IN {{ (($metrics.GetInInclusionState).GetMessageTotal) }} {{ (formatTimestampOrNever (($metrics.GetInInclusionState).GetLastEvent)) }} - {{ (($metrics.GetInInclusionState).GetLastMessage) }} + {{ template "longStringCell" (($metrics.GetInInclusionState).GetLastMessage)}} Output IN {{ (($metrics.GetInOutput).GetMessageTotal) }} {{ (formatTimestampOrNever (($metrics.GetInOutput).GetLastEvent)) }} - {{ (($metrics.GetInOutput).GetLastMessage) }} + {{ template "longStringCell" (($metrics.GetInOutput).GetLastMessage)}} Unspent alias output IN {{ (($metrics.GetInUnspentAliasOutput).GetMessageTotal) }} {{ (formatTimestampOrNever (($metrics.GetInUnspentAliasOutput).GetLastEvent)) }} - {{ (($metrics.GetInUnspentAliasOutput).GetLastMessage) }} + {{ template "longStringCell" (($metrics.GetInUnspentAliasOutput).GetLastMessage)}} {{end}} -{{define "title"}}Kažkas{{end}} +{{define "title"}}Connection to L1 metrics{{end}} {{define "body"}}
diff --git a/packages/dashboard/templates/metrics_nodeconn.tmpl b/packages/dashboard/templates/metrics_nodeconn.tmpl index 6c74a95966..e4f8d75086 100644 --- a/packages/dashboard/templates/metrics_nodeconn.tmpl +++ b/packages/dashboard/templates/metrics_nodeconn.tmpl @@ -2,19 +2,11 @@ {{define "body"}}
-

All the chains

-
    - {{range $_, $c := .Chains}} - {{ $id := $c.ChainRecord.ChainID.Base58 }} -
  • {{ $id }}
  • - {{end}} -
-

Chains, subscribed to L1

    {{range $_, $addr := (.Metrics.GetSubscribed)}} {{ $id := $addr.Base58 }} -
  • {{ $id }}
  • +
  • {{ $id }}
  • {{end}}
diff --git a/packages/dashboard/util.go b/packages/dashboard/util.go index a646869c80..0b9282e724 100644 --- a/packages/dashboard/util.go +++ b/packages/dashboard/util.go @@ -48,6 +48,13 @@ func bytesToString(b []byte) string { return string(b) } +func anythingToString(i interface{}) string { + if i == nil { + return "" + } + return fmt.Sprintf("%v", i) +} + func formatTimestamp(ts interface{}) string { t, ok := ts.(time.Time) if !ok { @@ -57,8 +64,8 @@ func formatTimestamp(ts interface{}) string { } func formatTimestampOrNever(t time.Time) string { - bla := time.Time{} - if t == bla { + timestampNever := time.Time{} + if t == timestampNever { return "NEVER" } return formatTimestamp(t) diff --git a/packages/dkg/messages.go b/packages/dkg/messages.go index a5372b1c46..9b1a9ea33b 100644 --- a/packages/dkg/messages.go +++ b/packages/dkg/messages.go @@ -183,9 +183,8 @@ type initiatorInitMsg struct { step byte dkgRef string // Some unique string to identify duplicate initialization. peeringID peering.PeeringID - peerNetIDs []string - peerPubs []ed25519.PublicKey - initiatorPub ed25519.PublicKey + peerPubs []*ed25519.PublicKey + initiatorPub *ed25519.PublicKey threshold uint16 timeout time.Duration roundRetry time.Duration @@ -193,7 +192,7 @@ type initiatorInitMsg struct { type initiatorInitMsgIn struct { initiatorInitMsg - SenderNetID string + SenderPubKey *ed25519.PublicKey } func (m *initiatorInitMsg) MsgType() byte { @@ -220,9 +219,6 @@ func (m *initiatorInitMsg) Write(w io.Writer) error { if _, err = w.Write(m.peeringID[:]); err != nil { return err } - if err = util.WriteStrings16(w, m.peerNetIDs); err != nil { - return err - } if err = util.WriteUint16(w, uint16(len(m.peerPubs))); err != nil { return err } @@ -260,30 +256,31 @@ func (m *initiatorInitMsg) Read(r io.Reader) error { return fmt.Errorf("error while reading peering ID: read %v bytes, expected %v bytes", n, ledgerstate.AddressLength) } - if m.peerNetIDs, err = util.ReadStrings16(r); err != nil { - return err - } var arrLen uint16 if err = util.ReadUint16(r, &arrLen); err != nil { return err } - m.peerPubs = make([]ed25519.PublicKey, arrLen) + m.peerPubs = make([]*ed25519.PublicKey, arrLen) for i := range m.peerPubs { var peerPubBytes []byte if peerPubBytes, err = util.ReadBytes16(r); err != nil { return err } - if m.peerPubs[i], _, err = ed25519.PublicKeyFromBytes(peerPubBytes); err != nil { + peerPubKey, _, err := ed25519.PublicKeyFromBytes(peerPubBytes) + if err != nil { return err } + m.peerPubs[i] = &peerPubKey } var initiatorPubBytes []byte if initiatorPubBytes, err = util.ReadBytes16(r); err != nil { return err } - if m.initiatorPub, _, err = ed25519.PublicKeyFromBytes(initiatorPubBytes); err != nil { + initiatorPub, _, err := ed25519.PublicKeyFromBytes(initiatorPubBytes) + if err != nil { return err } + m.initiatorPub = &initiatorPub if err = util.ReadUint16(r, &m.threshold); err != nil { return err } diff --git a/packages/dkg/node.go b/packages/dkg/node.go index 75fd0dfbed..39fb8ae680 100644 --- a/packages/dkg/node.go +++ b/packages/dkg/node.go @@ -86,7 +86,7 @@ func (n *Node) receiveInitMessage(peerMsg *peering.PeerMessageIn) { } n.initMsgQueue <- &initiatorInitMsgIn{ initiatorInitMsg: *msg, - SenderNetID: peerMsg.SenderNetID, + SenderPubKey: peerMsg.SenderPubKey, } } @@ -99,16 +99,15 @@ func (n *Node) Close() { // This function is executed on the DKG initiator node (a chosen leader for this DKG instance). //nolint:funlen,gocritic func (n *Node) GenerateDistributedKey( - peerNetIDs []string, - peerPubs []ed25519.PublicKey, + peerPubs []*ed25519.PublicKey, threshold uint16, roundRetry time.Duration, // Retry for Peer <-> Peer communication. stepRetry time.Duration, // Retry for Initiator -> Peer communication. timeout time.Duration, // Timeout for the entire procedure. ) (*tcrypto.DKShare, error) { - n.log.Infof("Starting new DKG procedure, initiator=%v, peers=%+v", n.netProvider.Self().NetID(), peerNetIDs) + n.log.Infof("Starting new DKG procedure, initiator=%v, peers=%+v", n.netProvider.Self().NetID(), peerPubs) var err error - peerCount := uint16(len(peerNetIDs)) + peerCount := uint16(len(peerPubs)) // // Some validationfor the parameters. if peerCount < 1 || threshold < 1 || threshold > peerCount { @@ -123,7 +122,7 @@ func (n *Node) GenerateDistributedKey( // Setup network connections. dkgID := peering.RandomPeeringID() var netGroup peering.GroupProvider - if netGroup, err = n.netProvider.PeerGroup(dkgID, peerNetIDs); err != nil { + if netGroup, err = n.netProvider.PeerGroup(dkgID, peerPubs); err != nil { return nil, err } defer netGroup.Close() @@ -136,7 +135,7 @@ func (n *Node) GenerateDistributedKey( gTimeout := timeout if peerPubs == nil { // Take the public keys from the peering network, if they were not specified. - peerPubs = make([]ed25519.PublicKey, peerCount) + peerPubs = make([]*ed25519.PublicKey, peerCount) for i, n := range netGroup.AllNodes() { if err = n.Await(timeout); err != nil { return nil, err @@ -145,7 +144,7 @@ func (n *Node) GenerateDistributedKey( if nPub == nil { return nil, fmt.Errorf("Have no public key for %v", n.NetID()) } - peerPubs[i] = *nPub + peerPubs[i] = nPub } } // @@ -156,9 +155,8 @@ func (n *Node) GenerateDistributedKey( peer.SendMsg(makePeerMessage(initPeeringID, peering.PeerMessageReceiverDkgInit, rabinStep0Initialize, &initiatorInitMsg{ dkgRef: dkgID.String(), // It could be some other identifier. peeringID: dkgID, - peerNetIDs: peerNetIDs, peerPubs: peerPubs, - initiatorPub: n.identity.PublicKey, + initiatorPub: &n.identity.PublicKey, threshold: threshold, timeout: timeout, roundRetry: roundRetry, @@ -278,7 +276,7 @@ func (n *Node) onInitMsg(msg *initiatorInitMsgIn) { // To have idempotence for retries, we need to consider duplicate // messages as success, if process is already created. n.procLock.RUnlock() - n.netProvider.SendMsgByNetID(msg.SenderNetID, makePeerMessage(msg.peeringID, peering.PeerMessageReceiverDkg, msg.step, &initiatorStatusMsg{ + n.netProvider.SendMsgByPubKey(msg.SenderPubKey, makePeerMessage(msg.peeringID, peering.PeerMessageReceiverDkg, msg.step, &initiatorStatusMsg{ error: nil, })) return @@ -292,7 +290,7 @@ func (n *Node) onInitMsg(msg *initiatorInitMsgIn) { n.processes[p.dkgRef] = p } n.procLock.Unlock() - n.netProvider.SendMsgByNetID(msg.SenderNetID, makePeerMessage(msg.peeringID, peering.PeerMessageReceiverDkg, msg.step, &initiatorStatusMsg{ + n.netProvider.SendMsgByPubKey(msg.SenderPubKey, makePeerMessage(msg.peeringID, peering.PeerMessageReceiverDkg, msg.step, &initiatorStatusMsg{ error: err, })) }() @@ -335,7 +333,7 @@ func (n *Node) exchangeInitiatorAcks( sendCB func(peerIdx uint16, peer peering.PeerSender), ) error { recvCB := func(recv *peering.PeerMessageGroupIn, msg initiatorMsg) (bool, error) { - n.log.Debugf("Initiator recv. step=%v response %v from %v", step, msg, recv.SenderNetID) + n.log.Debugf("Initiator recv. step=%v response %v from %v", step, msg, recv.SenderPubKey.String()) return true, nil } return n.exchangeInitiatorMsgs(netGroup, peers, recvCh, retryTimeout, giveUpTimeout, step, sendCB, recvCB) @@ -360,7 +358,7 @@ func (n *Node) exchangeInitiatorMsgs( return false, nil } if err != nil { - n.log.Warnf("Failed to read message from %v: %v", recv.SenderNetID, recv.PeerMessageData) + n.log.Warnf("Failed to read message from %v: %v", recv.SenderPubKey.String(), recv.PeerMessageData) return false, err } if !initMsg.IsResponse() { diff --git a/packages/dkg/node_test.go b/packages/dkg/node_test.go index 766bb6f409..093d2e9983 100644 --- a/packages/dkg/node_test.go +++ b/packages/dkg/node_test.go @@ -52,7 +52,6 @@ func TestBasic(t *testing.T) { // // Initiate the key generation from some client node. dkShare, err := dkgNodes[0].GenerateDistributedKey( - peerNetIDs, testpeers.PublicKeys(peerIdentities), threshold, 1*time.Second, @@ -64,50 +63,6 @@ func TestBasic(t *testing.T) { require.NotNil(t, dkShare.SharedPublic) } -// TestNoPubs checks, if public keys are taken from the peering network successfully. -// See a NOTE in the test case bellow. -func TestNoPubs(t *testing.T) { - log := testlogger.NewLogger(t) - defer log.Sync() - // - // Create a fake network and keys for the tests. - timeout := 100 * time.Second - var threshold uint16 = 10 - var peerCount uint16 = 10 - peerNetIDs, peerIdentities := testpeers.SetupKeys(peerCount) - var peeringNetwork *testutil.PeeringNetwork = testutil.NewPeeringNetwork( - peerNetIDs, peerIdentities, 10000, - testutil.NewPeeringNetReliable(log), - testlogger.WithLevel(log, logger.LevelWarn, false), - ) - var networkProviders []peering.NetworkProvider = peeringNetwork.NetworkProviders() - // - // Initialize the DKG subsystem in each node. - var dkgNodes []*dkg.Node = make([]*dkg.Node, len(peerNetIDs)) - for i := range peerNetIDs { - registry := testutil.NewDkgRegistryProvider(tcrypto.DefaultSuite()) - dkgNode, err := dkg.NewNode( - peerIdentities[i], networkProviders[i], registry, - testlogger.WithLevel(log.With("NetID", peerNetIDs[i]), logger.LevelDebug, false), - ) - require.NoError(t, err) - dkgNodes[i] = dkgNode - } - // - // Initiate the key generation from some client node. - dkShare, err := dkgNodes[0].GenerateDistributedKey( - peerNetIDs, - nil, // NOTE: Should be taken from the peering node. - threshold, - 1*time.Second, - 2*time.Second, - timeout, - ) - require.Nil(t, err) - require.NotNil(t, dkShare.Address) - require.NotNil(t, dkShare.SharedPublic) -} - // TestUnreliableNet checks, if DKG runs on an unreliable network. // See a NOTE in the test case bellow. func TestUnreliableNet(t *testing.T) { @@ -148,8 +103,7 @@ func TestUnreliableNet(t *testing.T) { // // Initiate the key generation from some client node. dkShare, err := dkgNodes[0].GenerateDistributedKey( - peerNetIDs, - nil, // NOTE: Should be taken from the peering node. + testpeers.PublicKeys(peerIdentities), threshold, 100*time.Millisecond, // Round retry. 500*time.Millisecond, // Step retry. @@ -192,7 +146,6 @@ func TestLowN(t *testing.T) { // // Initiate the key generation from some client node. dkShare, err := dkgNodes[0].GenerateDistributedKey( - peerNetIDs, testpeers.PublicKeys(peerIdentities), threshold, 1*time.Second, diff --git a/packages/dkg/proc.go b/packages/dkg/proc.go index cfd19fb98d..95bcfd344f 100644 --- a/packages/dkg/proc.go +++ b/packages/dkg/proc.go @@ -44,7 +44,7 @@ type proc struct { dkShare *tcrypto.DKShare // This will be generated as a result of this procedure. node *Node // DKG node we are running in. nodeIndex uint16 // Index of this node. - initiatorPub ed25519.PublicKey + initiatorPub *ed25519.PublicKey threshold uint16 roundRetry time.Duration // Retry period for the Peer <-> Peer communication. netGroup peering.GroupProvider // A group for which the distributed key is generated. @@ -53,7 +53,7 @@ type proc struct { attachID interface{} // We keep it here to be able to detach from the network. peerMsgCh chan *peering.PeerMessageGroupIn // A buffer for the received peer messages. log *logger.Logger // A logger to use. - myNetID string // Just to make logging easier. + myPubKey *ed25519.PublicKey // Just to make logging easier. steps map[byte]*procStep // All the steps for the procedure. } @@ -62,7 +62,7 @@ func onInitiatorInit(dkgID peering.PeeringID, msg *initiatorInitMsg, node *Node) var err error var netGroup peering.GroupProvider - if netGroup, err = node.netProvider.PeerGroup(dkgID, msg.peerNetIDs); err != nil { + if netGroup, err = node.netProvider.PeerGroup(dkgID, msg.peerPubs); err != nil { return nil, err } var dkgImpl *rabin_dkg.DistKeyGenerator @@ -92,9 +92,9 @@ func onInitiatorInit(dkgID peering.PeeringID, msg *initiatorInitMsg, node *Node) dkgLock: &sync.RWMutex{}, peerMsgCh: make(chan *peering.PeerMessageGroupIn, len(msg.peerPubs)), log: log, - myNetID: node.netProvider.Self().NetID(), + myPubKey: node.netProvider.Self().PubKey(), } - p.log.Infof("Starting DKG Peer process at %v for DkgID=%v", p.myNetID, p.dkgID.String()) + p.log.Infof("Starting DKG Peer process at %v for DkgID=%v", p.myPubKey.String(), p.dkgID.String()) stepsStart := make(chan map[uint16]*peering.PeerMessageData) p.steps = make(map[byte]*procStep) if p.dkgImpl == nil { @@ -253,7 +253,7 @@ func (p *proc) rabinStep2R22SendResponsesMakeSent(step byte, initRecv *peering.P return nil, err } p.dkgLock.Unlock() - p.log.Debugf("RabinDKG[%v] DealResponse[%v|%v]=%v", p.myNetID, r.Index, r.Response.Index, base58.Encode(r.Response.SessionID)) + p.log.Debugf("RabinDKG[%v] DealResponse[%v|%v]=%v", p.myPubKey.String(), r.Index, r.Response.Index, base58.Encode(r.Response.SessionID)) ourResponses = append(ourResponses, r) } // @@ -297,7 +297,7 @@ func (p *proc) rabinStep3R23SendJustificationsMakeSent(step byte, initRecv *peer for _, r := range recvResponses[i].responses { p.dkgLock.Lock() var j *rabin_dkg.Justification - p.log.Debugf("RabinDKG[%v] ProcResponse[%v|%v]=%v", p.myNetID, r.Index, r.Response.Index, base58.Encode(r.Response.SessionID)) + p.log.Debugf("RabinDKG[%v] ProcResponse[%v|%v]=%v", p.myPubKey.String(), r.Index, r.Response.Index, base58.Encode(r.Response.SessionID)) if j, err = p.dkgImpl.ProcessResponse(r); err != nil { p.dkgLock.Unlock() p.log.Errorf("ProcessResponse(%v) -> %+v, resp.SessionID=%v", i, err, base58.Encode(r.Response.SessionID)) @@ -522,6 +522,7 @@ func (p *proc) rabinStep6R6SendReconstructCommitsMakeResp(step byte, initRecv *p make([]kyber.Point, 0), // PublicCommits []kyber.Point{keyPair.Public}, // PublicShares keyPair.Private, // PrivateShare + p.nodePubKeys(), // NodePubKeys ) if err != nil { return nil, err @@ -570,6 +571,7 @@ func (p *proc) rabinStep6R6SendReconstructCommitsMakeResp(step byte, initRecv *p distKeyShare.Commits, // PublicCommits publicShares, // PublicShares distKeyShare.PriShare().V, // PrivateShare + p.nodePubKeys(), // NodePubKeys ) if err != nil { return nil, err @@ -644,6 +646,16 @@ func (p *proc) makeInitiatorPubShareMsg(step byte) (*initiatorPubShareMsg, error }, nil } +func (p *proc) nodePubKeys() []*ed25519.PublicKey { + allNodes := p.netGroup.AllNodes() + nodeCount := len(allNodes) + pubKeys := make([]*ed25519.PublicKey, nodeCount) + for i := 0; i < nodeCount; i++ { + pubKeys[i] = allNodes[uint16(i)].PubKey() + } + return pubKeys +} + type procStep struct { step byte startCh <-chan map[uint16]*peering.PeerMessageData // Gives a signal to start the current step. @@ -725,7 +737,7 @@ func (s *procStep) run() { // messages from others. Maybe our messages were lost, so we just resend the same messages. if s.initResp != nil { if isDkgInitProcRecvMsg(recv.MsgType) { - s.log.Debugf("[%v -%v-> %v] Resending initiator response.", s.proc.myNetID, s.initResp.MsgType, recv.SenderNetID) + s.log.Debugf("[%v -%v-> %v] Resending initiator response.", s.proc.myPubKey.String(), s.initResp.MsgType, recv.SenderPubKey.String()) s.proc.netGroup.SendMsgByIndex(recv.SenderIndex, s.initResp.MsgReceiver, s.initResp.MsgType, s.initResp.MsgData) continue } @@ -738,7 +750,7 @@ func (s *procStep) run() { s.sendEcho(recv) continue } - s.log.Warnf("[%v -%v-> %v] Dropping unknown message.", recv.SenderNetID, recv.MsgType, s.proc.myNetID) + s.log.Warnf("[%v -%v-> %v] Dropping unknown message.", recv.SenderPubKey.String(), recv.MsgType, s.proc.node.pubKey.String()) continue } // @@ -753,8 +765,8 @@ func (s *procStep) run() { s.markDone(makePeerMessage(s.proc.dkgID, peering.PeerMessageReceiverDkg, s.step, &initiatorStatusMsg{error: err})) } for i := range s.sentMsgs { - netID, _ := s.proc.netGroup.NetIDByIndex(i) - s.log.Debugf("[%v -%v-> %v] Sending peer message (first).", s.proc.myNetID, s.sentMsgs[i].MsgType, netID) + pubKey, _ := s.proc.netGroup.PubKeyByIndex(i) + s.log.Debugf("[%v -%v-> %v] Sending peer message (first).", s.proc.myPubKey.String(), s.sentMsgs[i].MsgType, pubKey.String()) s.proc.netGroup.SendMsgByIndex(i, s.sentMsgs[i].MsgReceiver, s.sentMsgs[i].MsgType, s.sentMsgs[i].MsgData) } if s.haveAll() { @@ -778,15 +790,15 @@ func (s *procStep) run() { } continue } - s.log.Warnf("[%v -%v-> %v] Dropping unknown message.", recv.SenderNetID, recv.MsgType, s.proc.myNetID) + s.log.Warnf("[%v -%v-> %v] Dropping unknown message.", recv.SenderPubKey.String(), recv.MsgType, s.proc.myPubKey.String()) continue case <-s.retryCh: // Resend all the messages, from who we haven't received. s.retryCh = time.After(s.proc.roundRetry) // Repeat the timer. for i := range s.sentMsgs { if s.recvMsgs[i] == nil { - netID, _ := s.proc.netGroup.NetIDByIndex(i) - s.log.Debugf("[%v -%v-> %v] Resending peer message (retry).", s.proc.myNetID, s.sentMsgs[i].MsgType, netID) + pubKey, _ := s.proc.netGroup.PubKeyByIndex(i) + s.log.Debugf("[%v -%v-> %v] Resending peer message (retry).", s.proc.myPubKey.String(), s.sentMsgs[i].MsgType, pubKey.String()) s.proc.netGroup.SendMsgByIndex(i, s.sentMsgs[i].MsgReceiver, s.sentMsgs[i].MsgType, s.sentMsgs[i].MsgData) } } @@ -802,14 +814,14 @@ func (s *procStep) sendEcho(recv *peering.PeerMessageGroupIn) { if sentMsg, sentMsgOK := s.sentMsgs[recv.SenderIndex]; sentMsgOK { echoMsg := *sentMsg // Make a copy. if echoMsg.MsgType, err = makeDkgRoundEchoMsg(echoMsg.MsgType); err != nil { - s.log.Warnf("[%v -%v-> %v] Unable to send echo message, reason=%v", s.proc.myNetID, recv.MsgType, recv.SenderNetID, err) + s.log.Warnf("[%v -%v-> %v] Unable to send echo message, reason=%v", s.proc.myPubKey.String(), recv.MsgType, recv.SenderPubKey.String(), err) return } - s.log.Debugf("[%v -%v-> %v] Resending peer message (echo).", s.proc.myNetID, echoMsg.MsgType, recv.SenderNetID) + s.log.Debugf("[%v -%v-> %v] Resending peer message (echo).", s.proc.myPubKey.String(), echoMsg.MsgType, recv.SenderPubKey.String()) s.proc.netGroup.SendMsgByIndex(recv.SenderIndex, echoMsg.MsgReceiver, echoMsg.MsgType, echoMsg.MsgData) return } - s.log.Warnf("[%v -%v-> %v] Unable to send echo message, is was not produced yet.", s.proc.myNetID, recv.MsgType, recv.SenderNetID) + s.log.Warnf("[%v -%v-> %v] Unable to send echo message, is was not produced yet.", s.proc.myPubKey.String(), recv.MsgType, recv.SenderPubKey.String()) } func (s *procStep) haveAll() bool { @@ -840,8 +852,8 @@ func (s *procStep) markDone(initResp *peering.PeerMessageData) { if s.initRecv != nil { s.proc.netGroup.SendMsgByIndex(s.initRecv.SenderIndex, initResp.MsgReceiver, initResp.MsgType, initResp.MsgData) // Send response to the initiator. } else { - s.log.Panicf("Step %v/%v closed with no initiator message.", s.proc.myNetID, s.step) + s.log.Panicf("Step %v/%v closed with no initiator message.", s.proc.myPubKey.String(), s.step) } s.retryCh = nil // Cancel the retry timer. - s.log.Debugf("Step %v/%v marked as completed.", s.proc.myNetID, s.step) + s.log.Debugf("Step %v/%v marked as completed.", s.proc.myPubKey.String(), s.step) } diff --git a/packages/kv/kv.go b/packages/kv/kv.go index 935e3dbbc8..2c11987fff 100644 --- a/packages/kv/kv.go +++ b/packages/kv/kv.go @@ -43,7 +43,6 @@ type KVWriter interface { type KVIterator interface { Iterate(prefix Key, f func(key Key, value []byte) bool) error IterateKeys(prefix Key, f func(key Key) bool) error - IterateSorted(prefix Key, f func(key Key, value []byte) bool) error IterateKeysSorted(prefix Key, f func(key Key) bool) error } @@ -57,7 +56,6 @@ type KVMustReader interface { type KVMustIterator interface { MustIterate(prefix Key, f func(key Key, value []byte) bool) MustIterateKeys(prefix Key, f func(key Key) bool) - MustIterateSorted(prefix Key, f func(key Key, value []byte) bool) MustIterateKeysSorted(prefix Key, f func(key Key) bool) } diff --git a/packages/metrics/chain.go b/packages/metrics/chain.go index 338d627c14..32ec40e271 100644 --- a/packages/metrics/chain.go +++ b/packages/metrics/chain.go @@ -10,11 +10,13 @@ import ( type StateManagerMetrics interface { RecordBlockSize(blockIndex uint32, size float64) + LastSeenStateIndex(stateIndex uint32) } type ChainMetrics interface { CountMessages() CountRequestAckMessages() + CurrentStateIndex(stateIndex uint32) MempoolMetrics ConsensusMetrics StateManagerMetrics @@ -63,6 +65,10 @@ func (c *chainMetricsObj) CountRequestAckMessages() { c.metrics.requestAckMessages.With(prometheus.Labels{"chain": c.chainID.String()}).Inc() } +func (c *chainMetricsObj) CurrentStateIndex(stateIndex uint32) { + c.metrics.currentStateIndex.With(prometheus.Labels{"chain": c.chainID.String()}).Set(float64(stateIndex)) +} + func (c *chainMetricsObj) RecordRequestProcessingTime(reqID iscp.RequestID, elapse time.Duration) { c.metrics.requestProcessingTime.With(prometheus.Labels{"chain": c.chainID.String(), "request": reqID.String()}).Set(elapse.Seconds()) } @@ -83,6 +89,14 @@ func (c *chainMetricsObj) RecordBlockSize(blockIndex uint32, blockSize float64) c.metrics.blockSizes.With(prometheus.Labels{"chain": c.chainID.String(), "block_index": fmt.Sprintf("%d", blockIndex)}).Set(blockSize) } +func (c *chainMetricsObj) LastSeenStateIndex(stateIndex uint32) { + if c.metrics.lastSeenStateIndexVal >= stateIndex { + return + } + c.metrics.lastSeenStateIndexVal = stateIndex + c.metrics.lastSeenStateIndex.With(prometheus.Labels{"chain": c.chainID.String()}).Set(float64(stateIndex)) +} + type defaultChainMetrics struct{} func DefaultChainMetrics() ChainMetrics { @@ -99,6 +113,8 @@ func (m *defaultChainMetrics) CountMessages() {} func (m *defaultChainMetrics) CountRequestAckMessages() {} +func (m *defaultChainMetrics) CurrentStateIndex(stateIndex uint32) {} + func (m *defaultChainMetrics) RecordRequestProcessingTime(_ iscp.RequestID, _ time.Duration) {} func (m *defaultChainMetrics) RecordVMRunTime(_ time.Duration) {} @@ -108,3 +124,5 @@ func (m *defaultChainMetrics) CountVMRuns() {} func (m *defaultChainMetrics) CountBlocksPerChain() {} func (m *defaultChainMetrics) RecordBlockSize(_ uint32, _ float64) {} + +func (m *defaultChainMetrics) LastSeenStateIndex(stateIndex uint32) {} diff --git a/packages/metrics/metrics.go b/packages/metrics/metrics.go index a40f1e6bf6..c5b6de6cfd 100644 --- a/packages/metrics/metrics.go +++ b/packages/metrics/metrics.go @@ -23,11 +23,14 @@ type Metrics struct { processedRequestCounter *prometheus.CounterVec messagesReceived *prometheus.CounterVec requestAckMessages *prometheus.CounterVec + currentStateIndex *prometheus.GaugeVec requestProcessingTime *prometheus.GaugeVec vmRunTime *prometheus.GaugeVec vmRunCounter *prometheus.CounterVec blocksPerChain *prometheus.CounterVec blockSizes *prometheus.GaugeVec + lastSeenStateIndex *prometheus.GaugeVec + lastSeenStateIndexVal uint32 nodeconnMetrics nodeconnmetrics.NodeConnectionMetrics } @@ -109,6 +112,12 @@ func (m *Metrics) registerMetrics() { }, []string{"chain"}) prometheus.MustRegister(m.requestAckMessages) + m.currentStateIndex = prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Name: "current_state_index", + Help: "The current chain state index.", + }, []string{"chain"}) + prometheus.MustRegister(m.currentStateIndex) + m.requestProcessingTime = prometheus.NewGaugeVec(prometheus.GaugeOpts{ Name: "request_processing_time", Help: "Time to process request", @@ -138,6 +147,12 @@ func (m *Metrics) registerMetrics() { Help: "Block sizes", }, []string{"block_index", "chain"}) prometheus.MustRegister(m.blockSizes) + + m.lastSeenStateIndex = prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Name: "last_seen_state_index", + Help: "Last seen state index", + }, []string{"chain"}) + prometheus.MustRegister(m.lastSeenStateIndex) } func (m *Metrics) GetNodeConnectionMetrics() nodeconnmetrics.NodeConnectionMetrics { diff --git a/packages/metrics/nodeconnmetrics/interface.go b/packages/metrics/nodeconnmetrics/interface.go index bf073bcbbe..53021cbf06 100644 --- a/packages/metrics/nodeconnmetrics/interface.go +++ b/packages/metrics/nodeconnmetrics/interface.go @@ -9,7 +9,6 @@ import ( type NodeConnectionMessageMetrics interface { CountLastMessage(interface{}) - GetMessageTotal() uint32 GetLastEvent() time.Time GetLastMessage() interface{} @@ -20,7 +19,6 @@ type NodeConnectionMessagesMetrics interface { GetOutPullTransactionInclusionState() NodeConnectionMessageMetrics GetOutPullConfirmedOutput() NodeConnectionMessageMetrics GetOutPostTransaction() NodeConnectionMessageMetrics - GetInTransaction() NodeConnectionMessageMetrics GetInInclusionState() NodeConnectionMessageMetrics GetInOutput() NodeConnectionMessageMetrics @@ -29,11 +27,9 @@ type NodeConnectionMessagesMetrics interface { type NodeConnectionMetrics interface { NodeConnectionMessagesMetrics - SetSubscribed(ledgerstate.Address) SetUnsubscribed(ledgerstate.Address) GetSubscribed() []ledgerstate.Address - RegisterMetrics() NewMessagesMetrics(chainID *iscp.ChainID) NodeConnectionMessagesMetrics } diff --git a/packages/parameters/parameters.go b/packages/parameters/parameters.go index 549b70ec13..a97a6461da 100644 --- a/packages/parameters/parameters.go +++ b/packages/parameters/parameters.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package parameters import ( @@ -12,6 +15,8 @@ import ( var all *configuration.Configuration const ( + NodeOwnerAddresses = "node.ownerAddresses" + LoggerLevel = "logger.level" LoggerDisableCaller = "logger.disableCaller" LoggerDisableStacktrace = "logger.disableStacktrace" @@ -35,7 +40,6 @@ const ( PeeringMyNetID = "peering.netid" PeeringPort = "peering.port" - PeeringNeighbors = "peering.neighbors" PullMissingRequestsFromCommittee = "peering.pullMissingRequests" NanomsgPublisherPort = "nanomsg.port" @@ -52,12 +56,17 @@ const ( MetricsBindAddress = "metrics.bindAddress" MetricsEnabled = "metrics.enabled" + + WALEnabled = "wal.enabled" + WALDirectory = "wal.directory" ) func Init() *configuration.Configuration { // set the default logger config all = configuration.New() + flag.StringSlice(NodeOwnerAddresses, []string{}, "A list of node owner addresses.") + flag.String(LoggerLevel, "info", "log level") flag.Bool(LoggerDisableCaller, false, "disable caller info in log") flag.Bool(LoggerDisableStacktrace, false, "disable stack trace in log") @@ -81,7 +90,7 @@ func Init() *configuration.Configuration { flag.Int(PeeringPort, 4000, "port for Wasp committee connection/peering") flag.String(PeeringMyNetID, "127.0.0.1:4000", "node host address as it is recognized by other peers") - flag.StringSlice(PeeringNeighbors, []string{}, "list of neighbors: known peer netIDs") + flag.Bool(PullMissingRequestsFromCommittee, true, "whether or not to pull missing requests from other committee members") flag.Int(NanomsgPublisherPort, 5550, "the port for nanomsg even publisher") @@ -99,6 +108,9 @@ func Init() *configuration.Configuration { flag.String(MetricsBindAddress, "127.0.0.1:2112", "prometheus metrics http server address") flag.Bool(MetricsEnabled, false, "disable and enable prometheus metrics") + flag.Bool(WALEnabled, true, "enabled wal") + flag.String(WALDirectory, "wal", "path to logs folder") + return all } diff --git a/packages/peering/config.go b/packages/peering/config.go index 6c06489d8a..b0ce78565f 100644 --- a/packages/peering/config.go +++ b/packages/peering/config.go @@ -8,56 +8,9 @@ import ( "net" "strconv" - "github.com/iotaledger/wasp/packages/util" "golang.org/x/xerrors" ) -// StaticPeerNetworkConfig in an implementation of registry.PeerNetworkConfigProvider. It does not change -// Alternatively, the configuration of peers behind could change and be dependent on chain -type StaticPeerNetworkConfig struct { - ownNetID string - peeringPort int - neighbors []string -} - -// NewStaticPeerNetworkConfigProvider is a configuration of the peer environment which does not change -func NewStaticPeerNetworkConfigProvider(ownNetID string, peeringPort int, neighbors ...string) (*StaticPeerNetworkConfig, error) { - if err := CheckMyNetID(ownNetID, peeringPort); err != nil { - return nil, xerrors.Errorf("NewStaticPeerNetworkConfigProvider: %w", err) - } - if !util.AllDifferentStrings(neighbors) { - return nil, xerrors.Errorf("NewStaticPeerNetworkConfigProvider: neighbors must all be different") - } - neigh := make([]string, 0, len(neighbors)) - // eliminate own id from the list - for _, n := range neighbors { - if n != ownNetID { - neigh = append(neigh, n) - } - } - return &StaticPeerNetworkConfig{ - ownNetID: ownNetID, - peeringPort: peeringPort, - neighbors: neigh, - }, nil -} - -func (p *StaticPeerNetworkConfig) OwnNetID() string { - return p.ownNetID -} - -func (p *StaticPeerNetworkConfig) PeeringPort() int { - return p.peeringPort -} - -func (p *StaticPeerNetworkConfig) Neighbors() []string { - return p.neighbors -} - -func (p *StaticPeerNetworkConfig) String() string { - return fmt.Sprintf("PeerConfig( ownNetID: %s, peeringPort: %d, neighbors: %+v )", p.OwnNetID(), p.PeeringPort(), p.Neighbors()) -} - // Check, if NetID is of proper format. func CheckNetID(netID string) error { sHost, sPort, err := net.SplitHostPort(netID) diff --git a/packages/peering/config_test.go b/packages/peering/config_test.go deleted file mode 100644 index 5529fb2181..0000000000 --- a/packages/peering/config_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package peering - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestConfigBasic(t *testing.T) { - peers := []string{"localhost:4000", "localhost:4001", "localhost:4002", "localhost:4003"} - t.Run("happy path", func(t *testing.T) { - c, err := NewStaticPeerNetworkConfigProvider(peers[0], 4000, peers[1:]...) - require.NoError(t, err) - require.EqualValues(t, peers[0], c.OwnNetID()) - }) - t.Run("eliminate own netid", func(t *testing.T) { - c, err := NewStaticPeerNetworkConfigProvider(peers[1], 4001, peers...) - require.NoError(t, err) - require.EqualValues(t, len(peers)-1, len(c.Neighbors())) - }) - t.Run("wrong port", func(t *testing.T) { - _, err := NewStaticPeerNetworkConfigProvider(peers[0], 4001, peers...) - require.Error(t, err) - }) - t.Run("duplicates", func(t *testing.T) { - _, err := NewStaticPeerNetworkConfigProvider(peers[0], 4000, peers[1], peers[2], peers[1]) - require.Error(t, err) - }) -} diff --git a/packages/peering/domain/domain.go b/packages/peering/domain/domain.go index 14bbc71cae..c3395158a5 100644 --- a/packages/peering/domain/domain.go +++ b/packages/peering/domain/domain.go @@ -1,10 +1,13 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package domain import ( "crypto/rand" - "sort" "sync" + "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/wasp/packages/peering" "github.com/iotaledger/wasp/packages/util" @@ -12,9 +15,9 @@ import ( type DomainImpl struct { netProvider peering.NetworkProvider - nodes map[string]peering.PeerSender + nodes map[ed25519.PublicKey]peering.PeerSender permutation *util.Permutation16 - netIDs []string + permPubKeys []*ed25519.PublicKey peeringID peering.PeeringID attachIDs []interface{} log *logger.Logger @@ -27,42 +30,27 @@ var _ peering.PeerDomainProvider = &DomainImpl{} func NewPeerDomain(netProvider peering.NetworkProvider, peeringID peering.PeeringID, initialNodes []peering.PeerSender, log *logger.Logger) *DomainImpl { ret := &DomainImpl{ netProvider: netProvider, - nodes: make(map[string]peering.PeerSender), - permutation: util.NewPermutation16(uint16(len(initialNodes)), nil), - netIDs: make([]string, 0, len(initialNodes)), + nodes: make(map[ed25519.PublicKey]peering.PeerSender), + permutation: nil, // Will be set in ret.reshufflePeers(). + permPubKeys: nil, // Will be set in ret.reshufflePeers(). peeringID: peeringID, attachIDs: make([]interface{}, 0), log: log, mutex: &sync.RWMutex{}, } for _, sender := range initialNodes { - ret.nodes[sender.NetID()] = sender + ret.nodes[*sender.PubKey()] = sender } ret.reshufflePeers() return ret } -func NewPeerDomainByNetIDs(netProvider peering.NetworkProvider, peeringID peering.PeeringID, peerNetIDs []string, log *logger.Logger) (*DomainImpl, error) { - peers := make([]peering.PeerSender, 0, len(peerNetIDs)) - for _, nid := range peerNetIDs { - if nid == netProvider.Self().NetID() { - continue - } - peer, err := netProvider.PeerByNetID(nid) - if err != nil { - return nil, err - } - peers = append(peers, peer) - } - return NewPeerDomain(netProvider, peeringID, peers, log), nil -} - -func (d *DomainImpl) SendMsgByNetID(netID string, msgReceiver, msgType byte, msgData []byte) { +func (d *DomainImpl) SendMsgByPubKey(pubKey *ed25519.PublicKey, msgReceiver, msgType byte, msgData []byte) { d.mutex.RLock() defer d.mutex.RUnlock() - peer, ok := d.nodes[netID] + peer, ok := d.nodes[*pubKey] if !ok { - d.log.Warnf("SendMsgByNetID: NetID %v is not in the domain", netID) + d.log.Warnf("SendMsgByPubKey: PubKey %v is not in the domain", pubKey.String()) return } peer.SendMsg(&peering.PeerMessageData{ @@ -73,50 +61,71 @@ func (d *DomainImpl) SendMsgByNetID(netID string, msgReceiver, msgType byte, msg }) } -func (d *DomainImpl) SendPeerMsgToRandomPeers(upToNumPeers int, msgReceiver, msgType byte, msgData []byte) { - for _, netID := range d.GetRandomPeers(upToNumPeers) { - d.SendMsgByNetID(netID, msgReceiver, msgType, msgData) - } -} - -func (d *DomainImpl) GetRandomPeers(upToNumPeers int) []string { +func (d *DomainImpl) GetRandomOtherPeers(upToNumPeers int) []*ed25519.PublicKey { d.mutex.RLock() defer d.mutex.RUnlock() - if upToNumPeers > len(d.netIDs) { - upToNumPeers = len(d.netIDs) + if upToNumPeers > len(d.permPubKeys) { + upToNumPeers = len(d.permPubKeys) } - ret := make([]string, upToNumPeers) + ret := make([]*ed25519.PublicKey, upToNumPeers) for i := range ret { - ret[i] = d.netIDs[d.permutation.Next()] + ret[i] = d.permPubKeys[d.permutation.Next()] } return ret } -func (d *DomainImpl) AddPeer(netID string) error { - d.mutex.Lock() - defer d.mutex.Unlock() - - if _, ok := d.nodes[netID]; ok { - return nil +func (d *DomainImpl) UpdatePeers(newPeerPubKeys []*ed25519.PublicKey) { + d.mutex.RLock() + oldPeers := make(map[ed25519.PublicKey]peering.PeerSender) // A copy, to avoid keeping the lock. + for k, v := range d.nodes { + oldPeers[k] = v } - if netID == d.netProvider.Self().NetID() { - return nil + d.mutex.RUnlock() + nodes := make(map[ed25519.PublicKey]peering.PeerSender) // Will collect the new set of nodes. + changed := false + // + // Add new peers. + for _, newPeerPubKey := range newPeerPubKeys { + if _, isOldPeer := oldPeers[*newPeerPubKey]; isOldPeer { + continue // Old peers will be retained bellow. + } + newPeerSender, err := d.netProvider.PeerByPubKey(newPeerPubKey) + if err != nil { + d.log.Warnf("Domain peer skipped for now, pubKey=%v not found, reason: %v", newPeerPubKey.String(), err) + continue + } + changed = true + nodes[*newPeerSender.PubKey()] = newPeerSender + d.log.Infof("Domain peer added, pubKey=%v, netID=%v", newPeerSender.PubKey().String(), newPeerSender.NetID()) } - peer, err := d.netProvider.PeerByNetID(netID) - if err != nil { - return err + // + // Remove peers that are not needed anymore and retain others. + for _, oldPeer := range oldPeers { + oldPeerDropped := true + if *oldPeer.PubKey() == *d.netProvider.Self().PubKey() { + // We retain the current node in the domain all the time. + nodes[*oldPeer.PubKey()] = oldPeer + oldPeerDropped = false + } else { + for _, newPeerPubKey := range newPeerPubKeys { + if *oldPeer.PubKey() == *newPeerPubKey { + nodes[*oldPeer.PubKey()] = oldPeer + oldPeerDropped = false + break + } + } + } + if oldPeerDropped { + changed = true + d.log.Infof("Domain peer removed, pubKey=%v, netID=%v", oldPeer.PubKey().String(), oldPeer.NetID()) + } + } + if changed { + d.mutex.Lock() + d.nodes = nodes + d.reshufflePeers() + d.mutex.Unlock() } - d.nodes[netID] = peer - d.reshufflePeers() - - return nil -} - -func (d *DomainImpl) RemovePeer(netID string) { - d.mutex.Lock() - defer d.mutex.Unlock() - delete(d.nodes, netID) - d.reshufflePeers() } func (d *DomainImpl) ReshufflePeers(seedBytes ...[]byte) { @@ -126,11 +135,13 @@ func (d *DomainImpl) ReshufflePeers(seedBytes ...[]byte) { } func (d *DomainImpl) reshufflePeers(seedBytes ...[]byte) { - d.netIDs = make([]string, 0, len(d.nodes)) - for netID := range d.nodes { - d.netIDs = append(d.netIDs, netID) + d.permPubKeys = make([]*ed25519.PublicKey, 0, len(d.nodes)) + for pubKey := range d.nodes { + peerPubKey := pubKey + if peerPubKey != *d.netProvider.Self().PubKey() { // Do not include self to the permutation. + d.permPubKeys = append(d.permPubKeys, &peerPubKey) + } } - sort.Strings(d.netIDs) var seedB []byte if len(seedBytes) == 0 { var b [8]byte @@ -139,20 +150,20 @@ func (d *DomainImpl) reshufflePeers(seedBytes ...[]byte) { } else { seedB = seedBytes[0] } - d.permutation.Shuffle(seedB) + d.permutation = util.NewPermutation16(uint16(len(d.permPubKeys)), seedB) } func (d *DomainImpl) Attach(receiver byte, callback func(recv *peering.PeerMessageIn)) interface{} { attachID := d.netProvider.Attach(&d.peeringID, receiver, func(recv *peering.PeerMessageIn) { - if recv.SenderNetID == d.netProvider.Self().NetID() { + if *recv.SenderPubKey == *d.netProvider.Self().PubKey() { d.log.Warnf("dropping message for receiver=%v MsgType=%v from %v: message from self.", - recv.MsgReceiver, recv.MsgType, recv.SenderNetID) + recv.MsgReceiver, recv.MsgType, recv.SenderPubKey.String()) return } - _, ok := d.nodes[recv.SenderNetID] + _, ok := d.nodes[*recv.SenderPubKey] if !ok { d.log.Warnf("dropping message for receiver=%v MsgType=%v from %v: it does not belong to the peer domain.", - recv.MsgReceiver, recv.MsgType, recv.SenderNetID) + recv.MsgReceiver, recv.MsgType, recv.SenderPubKey.String()) return } callback(recv) @@ -161,6 +172,14 @@ func (d *DomainImpl) Attach(receiver byte, callback func(recv *peering.PeerMessa return attachID } +func (d *DomainImpl) PeerStatus() []peering.PeerStatusProvider { + res := make([]peering.PeerStatusProvider, 0) + for _, v := range d.nodes { + res = append(res, v.Status()) + } + return res +} + func (d *DomainImpl) Detach(attachID interface{}) { d.netProvider.Detach(attachID) } diff --git a/packages/peering/domain/domain_test.go b/packages/peering/domain/domain_test.go index c5f1611808..34ea878012 100644 --- a/packages/peering/domain/domain_test.go +++ b/packages/peering/domain/domain_test.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package domain_test import ( @@ -18,6 +21,7 @@ func TestDomainProvider(t *testing.T) { nodeCount := 3 netIDs, nodeIdentities := testpeers.SetupKeys(uint16(nodeCount)) nodes, netCloser := testpeers.SetupNet(netIDs, nodeIdentities, testutil.NewPeeringNetReliable(log), log) + nodePubKeys := testpeers.PublicKeys(nodeIdentities) for i := range nodes { go nodes[i].Run(make(<-chan struct{})) } @@ -44,12 +48,12 @@ func TestDomainProvider(t *testing.T) { // // Create a group on one of nodes. var d peering.PeerDomainProvider - d, err := nodes[1].PeerDomain(peeringID, netIDs) + d, err := nodes[1].PeerDomain(peeringID, nodePubKeys) require.Nil(t, err) require.NotNil(t, d) - d.SendMsgByNetID(netIDs[0], receiver, 125, []byte{}) - d.SendMsgByNetID(netIDs[2], receiver, 125, []byte{}) + d.SendMsgByPubKey(nodePubKeys[0], receiver, 125, []byte{}) + d.SendMsgByPubKey(nodePubKeys[2], receiver, 125, []byte{}) <-doneCh0 <-doneCh2 // @@ -65,17 +69,18 @@ func TestRandom(t *testing.T) { nodeCount := 5 netIDs, nodeIdentities := testpeers.SetupKeys(uint16(nodeCount)) nodes, netCloser := testpeers.SetupNet(netIDs, nodeIdentities, testutil.NewPeeringNetReliable(log), log) + nodePubKeys := testpeers.PublicKeys(nodeIdentities) for i := range nodes { go nodes[i].Run(make(<-chan struct{})) } peeringID := peering.RandomPeeringID() // Create a group on 2 of nodes. - d1, err := nodes[1].PeerDomain(peeringID, netIDs) + d1, err := nodes[1].PeerDomain(peeringID, nodePubKeys) require.NoError(t, err) require.NotNil(t, d1) - d2, err := nodes[2].PeerDomain(peeringID, netIDs) + d2, err := nodes[2].PeerDomain(peeringID, nodePubKeys) require.NoError(t, err) require.NotNil(t, d1) @@ -88,10 +93,10 @@ func TestRandom(t *testing.T) { ii := i nodes[i].Attach(&peeringID, receiver, func(recv *peering.PeerMessageIn) { t.Logf("%d received", ii) - if netIDs[1] == recv.SenderNetID { + if nodePubKeys[1] == recv.SenderPubKey { r1++ } - if netIDs[2] == recv.SenderNetID { + if nodePubKeys[2] == recv.SenderPubKey { r2++ } wg.Done() @@ -102,11 +107,11 @@ func TestRandom(t *testing.T) { for i := 0; i < 5; i++ { wg.Add(sendTo * 2) t.Log("----------------------------------") - for _, netID := range d1.GetRandomPeers(sendTo) { - d1.SendMsgByNetID(netID, receiver, 125, []byte{}) + for _, pubKey := range d1.GetRandomOtherPeers(sendTo) { + d1.SendMsgByPubKey(pubKey, receiver, 125, []byte{}) } - for _, netID := range d2.GetRandomPeers(sendTo) { - d2.SendMsgByNetID(netID, receiver, 125, []byte{}) + for _, pubKey := range d2.GetRandomOtherPeers(sendTo) { + d2.SendMsgByPubKey(pubKey, receiver, 125, []byte{}) } wg.Wait() } diff --git a/packages/peering/group/group.go b/packages/peering/group/group.go index b931e34ba2..6f85c90891 100644 --- a/packages/peering/group/group.go +++ b/packages/peering/group/group.go @@ -9,6 +9,7 @@ import ( "fmt" "time" + "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/wasp/packages/peering" "golang.org/x/xerrors" @@ -66,24 +67,24 @@ func (g *groupImpl) SelfIndex() uint16 { // PeerIndex implements peering.GroupProvider. func (g *groupImpl) PeerIndex(peer peering.PeerSender) (uint16, error) { - return g.PeerIndexByNetID(peer.NetID()) + return g.PeerIndexByPubKey(peer.PubKey()) } // PeerIndexByNetID implements peering.GroupProvider. -func (g *groupImpl) PeerIndexByNetID(peerNetID string) (uint16, error) { +func (g *groupImpl) PeerIndexByPubKey(peerPubKey *ed25519.PublicKey) (uint16, error) { for i := range g.nodes { - if g.nodes[i].NetID() == peerNetID { + if *g.nodes[i].PubKey() == *peerPubKey { return uint16(i), nil } } - return NotInGroup, errors.New("peer_not_found_by_net_id") + return NotInGroup, errors.New("peer not found by pubKey") } -func (g *groupImpl) NetIDByIndex(index uint16) (string, error) { +func (g *groupImpl) PubKeyByIndex(index uint16) (*ed25519.PublicKey, error) { if index < uint16(len(g.nodes)) { - return g.nodes[index].NetID(), nil + return g.nodes[index].PubKey(), nil } - return "", errors.New("peer_index_out_of_scope") + return nil, errors.New("peer index out of scope") } // SendMsgByIndex implements peering.GroupProvider. @@ -135,11 +136,11 @@ func (g *groupImpl) ExchangeRound( if !ok { return errors.New("recv_channel_closed") } - senderIndex, err := g.PeerIndexByNetID(recvMsgNoIndex.SenderNetID) + senderIndex, err := g.PeerIndexByPubKey(recvMsgNoIndex.SenderPubKey) if err != nil { g.log.Warnf( "Dropping message %v -> %v, MsgType=%v because of %v", - recvMsgNoIndex.SenderNetID, g.netProvider.Self().NetID(), + recvMsgNoIndex.SenderPubKey.String(), g.netProvider.Self().PubKey().String(), recvMsgNoIndex.MsgType, err, ) continue @@ -151,7 +152,7 @@ func (g *groupImpl) ExchangeRound( if acks[recvMsg.SenderIndex] { // Only consider first successful message. g.log.Warnf( "Dropping duplicate message %v -> %v, receiver=%v, MsgType=%v", - recvMsg.SenderNetID, g.netProvider.Self().NetID(), + recvMsg.SenderPubKey.String(), g.netProvider.Self().PubKey().String(), recvMsg.MsgReceiver, recvMsg.MsgType, ) continue @@ -234,13 +235,13 @@ func (g *groupImpl) OtherNodes(except ...uint16) map[uint16]peering.PeerSender { // for the messages according to the message source. func (g *groupImpl) Attach(receiver byte, callback func(recv *peering.PeerMessageGroupIn)) interface{} { attachID := g.netProvider.Attach(&g.peeringID, receiver, func(recv *peering.PeerMessageIn) { - idx, err := g.PeerIndexByNetID(recv.SenderNetID) + idx, err := g.PeerIndexByPubKey(recv.SenderPubKey) if idx == NotInGroup { err = xerrors.Errorf("sender does not belong to the group") } if err != nil { g.log.Warnf("dropping message for receiver=%v MsgType=%v from %v: %v.", - recv.MsgReceiver, recv.MsgType, recv.SenderNetID, err) + recv.MsgReceiver, recv.MsgType, recv.SenderPubKey.String(), err) return } gRecv := &peering.PeerMessageGroupIn{ diff --git a/packages/peering/group/group_test.go b/packages/peering/group/group_test.go index 02659f5359..0c7fa61567 100644 --- a/packages/peering/group/group_test.go +++ b/packages/peering/group/group_test.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package group_test import ( @@ -40,7 +43,7 @@ func TestGroupProvider(t *testing.T) { // // Create a group on one of nodes. var g peering.GroupProvider - g, err := nodes[0].PeerGroup(peeringID, netIDs) + g, err := nodes[0].PeerGroup(peeringID, testpeers.PublicKeys(nodeIdentities)) require.Nil(t, err) // // Broadcast a message and wait until it will be received on all the nodes. diff --git a/packages/peering/lpp/lppNetImpl.go b/packages/peering/lpp/lppNetImpl.go index 6cd4faf086..78dbd60bab 100644 --- a/packages/peering/lpp/lppNetImpl.go +++ b/packages/peering/lpp/lppNetImpl.go @@ -21,7 +21,6 @@ package lpp import ( "context" "encoding/binary" - "errors" "fmt" "io" "net" @@ -319,11 +318,11 @@ func (n *netImpl) Self() peering.PeerSender { } // Group creates peering.GroupProvider. -func (n *netImpl) PeerGroup(peeringID peering.PeeringID, peerNetIDs []string) (peering.GroupProvider, error) { +func (n *netImpl) PeerGroup(peeringID peering.PeeringID, peerPubKeys []*ed25519.PublicKey) (peering.GroupProvider, error) { var err error - groupPeers := make([]peering.PeerSender, len(peerNetIDs)) - for i := range peerNetIDs { - if groupPeers[i], err = n.usePeer(peerNetIDs[i]); err != nil { + groupPeers := make([]peering.PeerSender, len(peerPubKeys)) + for i := range peerPubKeys { + if groupPeers[i], err = n.usePeer(peerPubKeys[i]); err != nil { return nil, err } } @@ -331,13 +330,13 @@ func (n *netImpl) PeerGroup(peeringID peering.PeeringID, peerNetIDs []string) (p } // Domain creates peering.PeerDomainProvider. -func (n *netImpl) PeerDomain(peeringID peering.PeeringID, peerNetIDs []string) (peering.PeerDomainProvider, error) { - peers := make([]peering.PeerSender, 0, len(peerNetIDs)) - for _, nid := range peerNetIDs { - if nid == n.Self().NetID() { +func (n *netImpl) PeerDomain(peeringID peering.PeeringID, peerPubKeys []*ed25519.PublicKey) (peering.PeerDomainProvider, error) { + peers := make([]peering.PeerSender, 0, len(peerPubKeys)) + for _, peerPubKey := range peerPubKeys { + if *peerPubKey == *n.Self().PubKey() { continue } - p, err := n.usePeer(nid) + p, err := n.usePeer(peerPubKey) if err != nil { return nil, err } @@ -346,13 +345,15 @@ func (n *netImpl) PeerDomain(peeringID peering.PeeringID, peerNetIDs []string) ( return domain.NewPeerDomain(n, peeringID, peers, n.log), nil } -func (n *netImpl) SendMsgByNetID(netID string, msg *peering.PeerMessageData) { - peer, err := n.PeerByNetID(netID) +// SendMsgByPubKey sends a message to the specified peer. +func (n *netImpl) SendMsgByPubKey(pubKey *ed25519.PublicKey, msg *peering.PeerMessageData) { + peer, err := n.PeerByPubKey(pubKey) if err != nil { - n.log.Warnf("SendMsgByNetID: NetID %v is not in the network", netID) + n.log.Warnf("SendMsgByPubKey: PubKey %v is not in the network", pubKey.String()) return } peer.SendMsg(msg) + peer.Close() } // Attach implements peering.NetworkProvider. @@ -372,23 +373,10 @@ func (n *netImpl) Detach(attachID interface{}) { n.recvEvents.Detach(closure) } -// PeerByNetID implements peering.NetworkProvider. -func (n *netImpl) PeerByNetID(peerNetID string) (peering.PeerSender, error) { - return n.usePeer(peerNetID) -} - // PeerByPubKey implements peering.NetworkProvider. // NOTE: For now, only known nodes can be looked up by PubKey. -func (n *netImpl) PeerByPubKey(peerPub *ed25519.PublicKey) (peering.PeerSender, error) { - n.peersLock.RLock() - defer n.peersLock.RUnlock() - for i := range n.peers { - pk := n.peers[i].PubKey() - if pk != nil && *pk == *peerPub { // Compared as binaries. - return n.PeerByNetID(n.peers[i].NetID()) - } - } - return nil, errors.New("known peer not found by pubKey") +func (n *netImpl) PeerByPubKey(peerPubKey *ed25519.PublicKey) (peering.PeerSender, error) { + return n.usePeer(peerPubKey) } // PeerStatus implements peering.NetworkProvider. @@ -415,13 +403,13 @@ func (n *netImpl) PubKey() *ed25519.PublicKey { // SendMsg implements peering.PeerSender for the Self() node. func (n *netImpl) SendMsg(msg *peering.PeerMessageData) { // Don't go via the network, if sending a message to self. - n.triggerRecvEvents(n.Self().NetID(), &peering.PeerMessageNet{PeerMessageData: *msg}) + n.triggerRecvEvents(n.Self().PubKey(), &peering.PeerMessageNet{PeerMessageData: *msg}) } -func (n *netImpl) triggerRecvEvents(from string, msg *peering.PeerMessageNet) { +func (n *netImpl) triggerRecvEvents(from *ed25519.PublicKey, msg *peering.PeerMessageNet) { n.recvEvents.Trigger(&peering.PeerMessageIn{ PeerMessageData: msg.PeerMessageData, - SenderNetID: from, + SenderPubKey: from, }) } @@ -430,11 +418,21 @@ func (n *netImpl) IsAlive() bool { return true // This node is alive. } +// NumUsers implements peering.PeerStatusProvider for the Self() node. +func (n *netImpl) NumUsers() int { + return 1 +} + // Await implements peering.PeerSender for the Self() node. func (n *netImpl) Await(timeout time.Duration) error { return nil // This node is alive immediately. } +// Status implements peering.PeerSender interface for the remote peers. +func (n *netImpl) Status() peering.PeerStatusProvider { + return n +} + // Close implements peering.PeerSender for the Self() node. func (n *netImpl) Close() { // We will con close the connection of the own node. @@ -474,19 +472,19 @@ func (n *netImpl) TrustedPeers() ([]*peering.TrustedPeer, error) { return n.trusted.TrustedPeers() } -func (n *netImpl) usePeer(remoteNetID string) (peering.PeerSender, error) { - if remoteNetID == n.myNetID { +func (n *netImpl) usePeer(remotePubKey *ed25519.PublicKey) (peering.PeerSender, error) { + if *remotePubKey == n.nodeKeyPair.PublicKey { return n, nil } n.peersLock.Lock() defer n.peersLock.Unlock() for _, p := range n.peers { - if p.remoteNetID == remoteNetID { + if *p.remotePubKey == *remotePubKey { p.usePeer() return p, nil } } - return nil, xerrors.Errorf("peer %v is not trusted", remoteNetID) + return nil, xerrors.Errorf("peer %v is not trusted", remotePubKey) } func (n *netImpl) maintenanceLoop(stopCh chan bool) { diff --git a/packages/peering/lpp/lppNetImpl_test.go b/packages/peering/lpp/lppNetImpl_test.go index 02e5294146..1dfe44b146 100644 --- a/packages/peering/lpp/lppNetImpl_test.go +++ b/packages/peering/lpp/lppNetImpl_test.go @@ -46,11 +46,11 @@ func TestLPPPeeringImpl(t *testing.T) { go nodes[i].Run(make(<-chan struct{})) } - n0p2, err := nodes[0].PeerByNetID(netIDs[2]) + n0p2, err := nodes[0].PeerByPubKey(&keys[2].PublicKey) require.NoError(t, err) - n1p1, err := nodes[1].PeerByNetID(netIDs[1]) + n1p1, err := nodes[1].PeerByPubKey(&keys[1].PublicKey) require.NoError(t, err) - n2p0, err := nodes[2].PeerByNetID(netIDs[0]) + n2p0, err := nodes[2].PeerByPubKey(&keys[0].PublicKey) require.NoError(t, err) chain1 := peering.RandomPeeringID() diff --git a/packages/peering/lpp/lppPeer.go b/packages/peering/lpp/lppPeer.go index b5dbf946c9..a1235f6b5f 100644 --- a/packages/peering/lpp/lppPeer.go +++ b/packages/peering/lpp/lppPeer.go @@ -147,7 +147,7 @@ func (p *peer) recvLoop() { for msg := range p.recvPipe.Out() { peerMsg, ok := msg.(*peering.PeerMessageNet) if ok { - p.net.triggerRecvEvents(p.NetID(), peerMsg) + p.net.triggerRecvEvents(p.PubKey(), peerMsg) } } } @@ -211,7 +211,7 @@ func (p *peer) IsInbound() bool { return p.remoteNetID < p.net.myNetID } -// IsInbound implements peering.PeerStatusProvider. +// NumUsers implements peering.PeerStatusProvider. // It is used in the dashboard. func (p *peer) NumUsers() int { p.accessLock.RLock() @@ -219,6 +219,11 @@ func (p *peer) NumUsers() int { return p.numUsers } +// Status implements peering.PeerSender interface for the remote peers. +func (p *peer) Status() peering.PeerStatusProvider { + return p +} + // SendMsg implements peering.PeerSender interface for the remote peers. func (p *peer) Close() { p.accessLock.Lock() diff --git a/packages/peering/peer_message.go b/packages/peering/peer_message.go index 11f9851e29..f80a0999f9 100644 --- a/packages/peering/peer_message.go +++ b/packages/peering/peer_message.go @@ -13,6 +13,7 @@ package peering import ( "bytes" + "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/wasp/packages/hashing" "github.com/iotaledger/wasp/packages/util" "github.com/iotaledger/wasp/packages/util/pipe" @@ -34,7 +35,7 @@ type PeerMessageNet struct { type PeerMessageIn struct { PeerMessageData - SenderNetID string + SenderPubKey *ed25519.PublicKey } type PeerMessageGroupIn struct { diff --git a/packages/peering/peering.go b/packages/peering/peering.go index 0b4005136f..0ca2003356 100644 --- a/packages/peering/peering.go +++ b/packages/peering/peering.go @@ -23,8 +23,7 @@ const ( // FirstUserMsgCode is the first committee message type. // All the equal and larger msg types are committee messages. // those with smaller are reserved by the package for heartbeat and handshake messages - FirstUserMsgCode = byte(0x10) - + FirstUserMsgCode = byte(0x10) PeerMessageReceiverStateManager = byte(iota) PeerMessageReceiverConsensus PeerMessageReceiverCommonSubset @@ -38,14 +37,13 @@ const ( type NetworkProvider interface { Run(stopCh <-chan struct{}) Self() PeerSender - PeerGroup(peeringID PeeringID, peerAddrs []string) (GroupProvider, error) - PeerDomain(peeringID PeeringID, peerAddrs []string) (PeerDomainProvider, error) - PeerByNetID(peerNetID string) (PeerSender, error) + PeerGroup(peeringID PeeringID, peerPubKeys []*ed25519.PublicKey) (GroupProvider, error) + PeerDomain(peeringID PeeringID, peerAddrs []*ed25519.PublicKey) (PeerDomainProvider, error) PeerByPubKey(peerPub *ed25519.PublicKey) (PeerSender, error) + SendMsgByPubKey(pubKey *ed25519.PublicKey, msg *PeerMessageData) PeerStatus() []PeerStatusProvider Attach(peeringID *PeeringID, receiver byte, callback func(recv *PeerMessageIn)) interface{} Detach(attachID interface{}) - SendMsgByNetID(netID string, msg *PeerMessageData) } // TrustedNetworkManager is used maintain a configuration which peers are trusted. @@ -68,8 +66,8 @@ type TrustedNetworkManager interface { type GroupProvider interface { SelfIndex() uint16 PeerIndex(peer PeerSender) (uint16, error) - PeerIndexByNetID(peerNetID string) (uint16, error) - NetIDByIndex(index uint16) (string, error) + PeerIndexByPubKey(peerPubKey *ed25519.PublicKey) (uint16, error) + PubKeyByIndex(index uint16) (*ed25519.PublicKey, error) Attach(receiver byte, callback func(recv *PeerMessageGroupIn)) interface{} Detach(attachID interface{}) SendMsgByIndex(peerIdx uint16, msgReceiver byte, msgType byte, msgData []byte) @@ -91,17 +89,17 @@ type GroupProvider interface { // All peers in the domain shares same peeringID. Each peer within domain is identified via its netID type PeerDomainProvider interface { ReshufflePeers(seedBytes ...[]byte) - GetRandomPeers(upToNumPeers int) []string + GetRandomOtherPeers(upToNumPeers int) []*ed25519.PublicKey + UpdatePeers(newPeerPubKeys []*ed25519.PublicKey) Attach(receiver byte, callback func(recv *PeerMessageIn)) interface{} Detach(attachID interface{}) - SendMsgByNetID(netID string, msgReceiver byte, msgType byte, msgData []byte) - SendPeerMsgToRandomPeers(upToNumPeers int, msgReceiver byte, msgType byte, msgData []byte) + SendMsgByPubKey(pubKey *ed25519.PublicKey, msgReceiver byte, msgType byte, msgData []byte) + PeerStatus() []PeerStatusProvider Close() } // PeerSender represents an interface to some remote peer. type PeerSender interface { - // NetID identifies the peer. NetID() string @@ -123,6 +121,9 @@ type PeerSender interface { // public key resolved. Await(timeout time.Duration) error + // Provides a read-only representation of this sender. + Status() PeerStatusProvider + // Close releases the reference to the peer, this informs the network // implementation, that it can disconnect, cleanup resources, etc. // You need to get new reference to the peer (PeerSender) to use it again. diff --git a/packages/registry/chainrecord.go b/packages/registry/chainrecord.go index f05051ff85..f56be1403d 100644 --- a/packages/registry/chainrecord.go +++ b/packages/registry/chainrecord.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package registry import ( @@ -12,7 +15,6 @@ import ( // TODO optimize, no need for a persistent structure, simple activity tag is enough type ChainRecord struct { ChainID *iscp.ChainID - Peers []string Active bool } @@ -28,22 +30,6 @@ func FromMarshalUtil(mu *marshalutil.MarshalUtil) (*ChainRecord, error) { if err != nil { return nil, err } - numPeers, err := mu.ReadUint16() - if err != nil { - return nil, err - } - ret.Peers = make([]string, numPeers) - for i := uint16(0); i < numPeers; i++ { - strSize, err := mu.ReadUint16() - if err != nil { - return nil, err - } - d, err := mu.ReadBytes(int(strSize)) - if err != nil { - return nil, err - } - ret.Peers[i] = string(d) - } return ret, nil } @@ -54,19 +40,12 @@ func ChainRecordFromBytes(data []byte) (*ChainRecord, error) { func (rec *ChainRecord) Bytes() []byte { mu := marshalutil.New().WriteBytes(rec.ChainID.Bytes()). - WriteBool(rec.Active). - WriteUint16(uint16(len(rec.Peers))) - for _, s := range rec.Peers { - b := []byte(s) - mu.WriteUint16(uint16(len(b))). - WriteBytes(b) - } + WriteBool(rec.Active) return mu.Bytes() } func (rec *ChainRecord) String() string { ret := "ChainID: " + rec.ChainID.String() + "\n" - ret += fmt.Sprintf(" Peers: %+v\n", rec.Peers) ret += fmt.Sprintf(" Active: %v\n", rec.Active) return ret } diff --git a/packages/registry/chainrecord_test.go b/packages/registry/chainrecord_test.go index 836a2452e3..20ee7ca132 100644 --- a/packages/registry/chainrecord_test.go +++ b/packages/registry/chainrecord_test.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package registry import ( @@ -12,7 +15,6 @@ func TestChainRecord(t *testing.T) { rec := ChainRecord{ ChainID: chainID, - Peers: []string{"a", "b", "c"}, Active: false, } recBack, err := ChainRecordFromBytes(rec.Bytes()) @@ -25,7 +27,6 @@ func TestChainRecord(t *testing.T) { rec = ChainRecord{ ChainID: chainID, - Peers: []string{"k", "l"}, Active: true, } require.True(t, rec.Active) diff --git a/packages/registry/committe_record_test.go b/packages/registry/committe_record_test.go deleted file mode 100644 index 2350ed6f67..0000000000 --- a/packages/registry/committe_record_test.go +++ /dev/null @@ -1,21 +0,0 @@ -package registry - -import ( - "testing" - - "github.com/iotaledger/goshimmer/packages/ledgerstate" - "github.com/iotaledger/hive.go/crypto/ed25519" - "github.com/stretchr/testify/require" -) - -func TestCommitteeRecord(t *testing.T) { - keyPair := ed25519.GenerateKeyPair() - addr := ledgerstate.NewED25519Address(keyPair.PublicKey) - rec := NewCommitteeRecord(addr, "node:111", "node:333") - recBack, err := CommitteeRecordFromBytes(rec.Bytes()) - require.NoError(t, err) - require.True(t, rec.Address.Equals(recBack.Address)) - require.EqualValues(t, rec.Nodes, recBack.Nodes) - - t.Logf("%s", rec) -} diff --git a/packages/registry/committee_record.go b/packages/registry/committee_record.go deleted file mode 100644 index fd0109bcca..0000000000 --- a/packages/registry/committee_record.go +++ /dev/null @@ -1,72 +0,0 @@ -package registry - -import ( - "fmt" - - "github.com/iotaledger/goshimmer/packages/ledgerstate" - "github.com/iotaledger/hive.go/marshalutil" -) - -// CommitteeRecord represents committee information -// TODO optimize: no need to persists address in the structure -type CommitteeRecord struct { - Address ledgerstate.Address - Nodes []string // "host_addr:port" -} - -// NewCommitteeRecord -func NewCommitteeRecord(addr ledgerstate.Address, nodes ...string) *CommitteeRecord { - ret := &CommitteeRecord{ - Address: addr, - Nodes: make([]string, len(nodes)), - } - copy(ret.Nodes, nodes) - return ret -} - -// CommitteeRecordFromMarshalUtil -func CommitteeRecordFromMarshalUtil(mu *marshalutil.MarshalUtil) (*CommitteeRecord, error) { - ret := &CommitteeRecord{} - var err error - ret.Address, err = ledgerstate.AddressFromMarshalUtil(mu) - if err != nil { - return nil, err - } - numNodes, err := mu.ReadUint16() - if err != nil { - return nil, err - } - ret.Nodes = make([]string, numNodes) - for i := uint16(0); i < numNodes; i++ { - strSize, err := mu.ReadUint16() - if err != nil { - return nil, err - } - d, err := mu.ReadBytes(int(strSize)) - if err != nil { - return nil, err - } - ret.Nodes[i] = string(d) - } - return ret, nil -} - -// CommitteeRecordFromBytes -func CommitteeRecordFromBytes(data []byte) (*CommitteeRecord, error) { - return CommitteeRecordFromMarshalUtil(marshalutil.New(data)) -} - -func (rec *CommitteeRecord) Bytes() []byte { - mu := marshalutil.New(). - WriteBytes(rec.Address.Bytes()). - WriteUint16(uint16(len(rec.Nodes))) - for _, s := range rec.Nodes { - b := []byte(s) - mu.WriteUint16(uint16(len(b))).WriteBytes(b) - } - return mu.Bytes() -} - -func (rec *CommitteeRecord) String() string { - return fmt.Sprintf("Committee(Address: %s Nodes:%+v)", rec.Address.Base58(), rec.Nodes) -} diff --git a/packages/registry/providers.go b/packages/registry/providers.go index 3278d90983..5992085d00 100644 --- a/packages/registry/providers.go +++ b/packages/registry/providers.go @@ -4,6 +4,7 @@ package registry import ( + "errors" "time" "github.com/iotaledger/goshimmer/packages/ledgerstate" @@ -28,14 +29,6 @@ type NodeIdentityProvider interface { GetNodePublicKey() (*ed25519.PublicKey, error) } -// PeerNetworkConfigProvider access to node and chain configuration: a list of netIDs of potential peers -type PeerNetworkConfigProvider interface { // TODO: KP: Remove or redesign. - OwnNetID() string - PeeringPort() int - Neighbors() []string - String() string -} - // DKShareRegistryProvider stands for a partial registry interface, needed for this package. // It should be implemented by registry.impl type DKShareRegistryProvider interface { @@ -43,10 +36,7 @@ type DKShareRegistryProvider interface { LoadDKShare(sharedAddress ledgerstate.Address) (*tcrypto.DKShare, error) } -type CommitteeRegistryProvider interface { - GetCommitteeRecord(addr ledgerstate.Address) (*CommitteeRecord, error) - SaveCommitteeRecord(rec *CommitteeRecord) error -} +var ErrDKShareNotFound = errors.New("dkShare not found") // ChainRecordRegistryProvider stands for a partial registry interface, needed for this package. type ChainRecordRegistryProvider interface { diff --git a/packages/registry/registry_impl.go b/packages/registry/registry_impl.go index df426972ef..f7f894659a 100644 --- a/packages/registry/registry_impl.go +++ b/packages/registry/registry_impl.go @@ -112,29 +112,6 @@ func (r *Impl) SaveChainRecord(rec *ChainRecord) error { // endregion /////////////////////////////////////////////////////////////// -// region CommitteeRegistryProvider /////////////////////////////////////////////////////////// - -func dbKeyCommitteeRecord(addr ledgerstate.Address) []byte { - return dbkeys.MakeKey(dbkeys.ObjectTypeCommitteeRecord, addr.Bytes()) -} - -func (r *Impl) GetCommitteeRecord(addr ledgerstate.Address) (*CommitteeRecord, error) { - data, err := r.store.Get(dbKeyCommitteeRecord(addr)) - if errors.Is(err, kvstore.ErrKeyNotFound) { - return nil, nil - } - if err != nil { - return nil, err - } - return CommitteeRecordFromBytes(data) -} - -func (r *Impl) SaveCommitteeRecord(rec *CommitteeRecord) error { - return r.store.Set(dbKeyCommitteeRecord(rec.Address), rec.Bytes()) -} - -// endregion ////////////////////////////////////////////////////////////////////// - // region DKShareRegistryProvider //////////////////////////////////////////////////// // SaveDKShare implements dkg.DKShareRegistryProvider. @@ -156,6 +133,9 @@ func (r *Impl) SaveDKShare(dkShare *tcrypto.DKShare) error { func (r *Impl) LoadDKShare(sharedAddress ledgerstate.Address) (*tcrypto.DKShare, error) { data, err := r.store.Get(dbKeyForDKShare(sharedAddress)) if err != nil { + if errors.Is(err, kvstore.ErrKeyNotFound) { + return nil, ErrDKShareNotFound + } return nil, err } return tcrypto.DKShareFromBytes(data, tcrypto.DefaultSuite()) diff --git a/packages/tcrypto/dkshare.go b/packages/tcrypto/dkshare.go index 686e3cd914..5ce9042255 100644 --- a/packages/tcrypto/dkshare.go +++ b/packages/tcrypto/dkshare.go @@ -11,6 +11,7 @@ import ( "github.com/iotaledger/goshimmer/packages/ledgerstate" "github.com/iotaledger/hive.go/crypto/bls" + "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/wasp/packages/util" "go.dedis.ch/kyber/v3" "go.dedis.ch/kyber/v3/share" @@ -29,6 +30,7 @@ type DKShare struct { PublicCommits []kyber.Point PublicShares []kyber.Point PrivateShare kyber.Scalar + NodePubKeys []*ed25519.PublicKey suite Suite // Transient, only needed for un-marshaling. } @@ -41,6 +43,7 @@ func NewDKShare( publicCommits []kyber.Point, publicShares []kyber.Point, privateShare kyber.Scalar, + nodePubKeys []*ed25519.PublicKey, ) (*DKShare, error) { var err error // @@ -61,6 +64,7 @@ func NewDKShare( PublicCommits: publicCommits, PublicShares: publicShares, PrivateShare: privateShare, + NodePubKeys: nodePubKeys, // NOTE: suite is not stored here. } return &dkShare, nil @@ -120,7 +124,18 @@ func (s *DKShare) Write(w io.Writer) error { return err } } - return util.WriteMarshaled(w, s.PrivateShare) + if err = util.WriteMarshaled(w, s.PrivateShare); err != nil { + return err + } + if err = util.WriteUint16(w, uint16(len(s.NodePubKeys))); err != nil { + return err + } + for _, nodePubKey := range s.NodePubKeys { + if err = util.WriteBytes16(w, nodePubKey[:]); err != nil { + return err + } + } + return nil } //nolint:gocritic @@ -176,7 +191,27 @@ func (s *DKShare) Read(r io.Reader) error { // // Private share. s.PrivateShare = s.suite.G2().Scalar() - return util.ReadMarshaled(r, s.PrivateShare) + if err = util.ReadMarshaled(r, s.PrivateShare); err != nil { + return err + } + // + // NodePubKeys + if err = util.ReadUint16(r, &arrLen); err != nil { + return err + } + s.NodePubKeys = make([]*ed25519.PublicKey, arrLen) + for i := range s.NodePubKeys { + var nodePubKeyBin []byte + var nodePubKey ed25519.PublicKey + if nodePubKeyBin, err = util.ReadBytes16(r); err != nil { + return err + } + if nodePubKey, _, err = ed25519.PublicKeyFromBytes(nodePubKeyBin); err != nil { + return err + } + s.NodePubKeys[i] = &nodePubKey + } + return nil } // SignShare signs the data with the own key share. diff --git a/packages/testutil/peeringNetBehaviour.go b/packages/testutil/peeringNetBehaviour.go index 5e1f52fb8c..2b8118be93 100644 --- a/packages/testutil/peeringNetBehaviour.go +++ b/packages/testutil/peeringNetBehaviour.go @@ -11,12 +11,13 @@ import ( "math/rand" "time" + "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/hive.go/logger" ) // An interface for all the network behaviors. type PeeringNetBehavior interface { - AddLink(inCh, outCh chan *peeringMsg, dstNetID string) + AddLink(inCh, outCh chan *peeringMsg, dstPubKey *ed25519.PublicKey) Close() } @@ -36,7 +37,7 @@ func NewPeeringNetReliable(log *logger.Logger) PeeringNetBehavior { } // Run implements PeeringNetBehavior. -func (n *peeringNetReliable) AddLink(inCh, outCh chan *peeringMsg, dstNetID string) { +func (n *peeringNetReliable) AddLink(inCh, outCh chan *peeringMsg, dstPubKey *ed25519.PublicKey) { closeCh := make(chan bool) n.closeChs = append(n.closeChs, closeCh) go n.recvLoop(inCh, outCh, closeCh) @@ -83,10 +84,10 @@ func NewPeeringNetUnreliable(deliverPct, repeatPct int, delayFrom, delayTill tim } // Run implements PeeringNetBehavior. -func (n *peeringNetUnreliable) AddLink(inCh, outCh chan *peeringMsg, dstNetID string) { +func (n *peeringNetUnreliable) AddLink(inCh, outCh chan *peeringMsg, dstPubKey *ed25519.PublicKey) { closeCh := make(chan bool) n.closeChs = append(n.closeChs, closeCh) - go n.recvLoop(inCh, outCh, closeCh, dstNetID) + go n.recvLoop(inCh, outCh, closeCh, dstPubKey) } // Close implements PeeringNetBehavior. @@ -96,7 +97,7 @@ func (n *peeringNetUnreliable) Close() { } } -func (n *peeringNetUnreliable) recvLoop(inCh, outCh chan *peeringMsg, closeCh chan bool, dstNetID string) { +func (n *peeringNetUnreliable) recvLoop(inCh, outCh chan *peeringMsg, closeCh chan bool, dstPubKey *ed25519.PublicKey) { for { select { case <-closeCh: @@ -106,7 +107,7 @@ func (n *peeringNetUnreliable) recvLoop(inCh, outCh chan *peeringMsg, closeCh ch return } if rand.Intn(100) > n.deliverPct { - n.log.Debugf("Network dropped message %v -%v-> %v", recv.from, recv.msg.MsgType, dstNetID) + n.log.Debugf("Network dropped message %v -%v-> %v", recv.from.String(), recv.msg.MsgType, dstPubKey.String()) continue // Drop the message. } // @@ -117,13 +118,13 @@ func (n *peeringNetUnreliable) recvLoop(inCh, outCh chan *peeringMsg, closeCh ch numRepeat++ } for i := 0; i < numRepeat; i++ { - go n.sendDelayed(recv, outCh, dstNetID, i+1, numRepeat) + go n.sendDelayed(recv, outCh, dstPubKey, i+1, numRepeat) } } } } -func (n *peeringNetUnreliable) sendDelayed(recv *peeringMsg, outCh chan *peeringMsg, dstNetID string, dupNum, dupCount int) { +func (n *peeringNetUnreliable) sendDelayed(recv *peeringMsg, outCh chan *peeringMsg, dstPubKey *ed25519.PublicKey, dupNum, dupCount int) { fromMS := int(n.delayFrom.Milliseconds()) tillMS := int(n.delayTill.Milliseconds()) var delay time.Duration @@ -137,7 +138,7 @@ func (n *peeringNetUnreliable) sendDelayed(recv *peeringMsg, outCh chan *peering } n.log.Debugf( "Network delivers message %v -%v-> %v (duplicate %v/%v, delay=%vms)", - recv.from, recv.msg.MsgType, dstNetID, dupNum, dupCount, delay.Milliseconds(), + recv.from.String(), recv.msg.MsgType, dstPubKey.String(), dupNum, dupCount, delay.Milliseconds(), ) safeSendPeeringMsg(outCh, recv, n.log) } diff --git a/packages/testutil/peeringNetBehaviourDynamic.go b/packages/testutil/peeringNetBehaviourDynamic.go index f3765d54c4..70acf6cc85 100644 --- a/packages/testutil/peeringNetBehaviourDynamic.go +++ b/packages/testutil/peeringNetBehaviourDynamic.go @@ -11,6 +11,7 @@ import ( "sync" "time" + "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/hive.go/logger" ) @@ -34,7 +35,7 @@ type peeringNetDynamicHandlerEntry struct { type peeringNetDynamicHandler interface { handleSendMessage( msg *peeringMsg, - dstNetID string, + dstPubKey *ed25519.PublicKey, nextHandlers []peeringNetDynamicHandlerEntry, callHandlersAndSendFun func(nextHandlers []peeringNetDynamicHandlerEntry), log *logger.Logger, @@ -81,11 +82,11 @@ func (pndT *PeeringNetDynamic) WithDelayingChannel(id *string, delayFrom, delayT return pndT } -func (pndT *PeeringNetDynamic) WithPeerDisconnected(id *string, peerName string) *PeeringNetDynamic { +func (pndT *PeeringNetDynamic) WithPeerDisconnected(id *string, peerPubKey *ed25519.PublicKey) *PeeringNetDynamic { pndT.addHandlerEntry(peeringNetDynamicHandlerEntry{ id, &peeringNetDynamicHandlerPeerDisconnected{ - peerName: peerName, + peerPubKey: peerPubKey, }, }) return pndT @@ -114,10 +115,10 @@ func (pndT *PeeringNetDynamic) RemoveHandler(id string) bool { } // Run implements PeeringNetBehavior. -func (pndT *PeeringNetDynamic) AddLink(inCh, outCh chan *peeringMsg, dstNetID string) { +func (pndT *PeeringNetDynamic) AddLink(inCh, outCh chan *peeringMsg, dstPubKey *ed25519.PublicKey) { closeCh := make(chan bool) pndT.closeChs = append(pndT.closeChs, closeCh) - go pndT.recvLoop(inCh, outCh, closeCh, dstNetID) + go pndT.recvLoop(inCh, outCh, closeCh, dstPubKey) } // Close implements PeeringNetBehavior. @@ -127,7 +128,7 @@ func (pndT *PeeringNetDynamic) Close() { } } -func (pndT *PeeringNetDynamic) recvLoop(inCh, outCh chan *peeringMsg, closeCh chan bool, dstNetID string) { +func (pndT *PeeringNetDynamic) recvLoop(inCh, outCh chan *peeringMsg, closeCh chan bool, dstPubKey *ed25519.PublicKey) { for { select { case <-closeCh: @@ -139,9 +140,9 @@ func (pndT *PeeringNetDynamic) recvLoop(inCh, outCh chan *peeringMsg, closeCh ch var callHandlersAndSendFun func(nextHandlers []peeringNetDynamicHandlerEntry) callHandlersAndSendFun = func(nextHandlers []peeringNetDynamicHandlerEntry) { if len(nextHandlers) > 0 { - nextHandlers[0].handleSendMessage(recv, dstNetID, nextHandlers[1:], callHandlersAndSendFun, pndT.log) + nextHandlers[0].handleSendMessage(recv, dstPubKey, nextHandlers[1:], callHandlersAndSendFun, pndT.log) } else { - pndT.log.Debugf("Network delivers message %v -%v-> %v", recv.from, recv.msg.MsgType, dstNetID) + pndT.log.Debugf("Network delivers message %v -%v-> %v", recv.from.String(), recv.msg.MsgType, dstPubKey.String()) safeSendPeeringMsg(outCh, recv, pndT.log) } } @@ -164,13 +165,13 @@ type peeringNetDynamicHandlerLosingChannel struct { func (lcT *peeringNetDynamicHandlerLosingChannel) handleSendMessage( msg *peeringMsg, - dstNetID string, + dstPubKey *ed25519.PublicKey, nextHandlers []peeringNetDynamicHandlerEntry, callHandlersAndSendFun func(nextHandlers []peeringNetDynamicHandlerEntry), log *logger.Logger, ) { if rand.Intn(100) > lcT.probability { - log.Debugf("Network dropped message %v -%v-> %v", msg.from, msg.msg.MsgType, dstNetID) + log.Debugf("Network dropped message %v -%v-> %v", msg.from.String(), msg.msg.MsgType, dstPubKey.String()) return } callHandlersAndSendFun(nextHandlers) @@ -182,7 +183,7 @@ type peeringNetDynamicHandlerRepeatingChannel struct { func (rcT *peeringNetDynamicHandlerRepeatingChannel) handleSendMessage( msg *peeringMsg, - dstNetID string, + dstPubKey *ed25519.PublicKey, nextHandlers []peeringNetDynamicHandlerEntry, callHandlersAndSendFun func(nextHandlers []peeringNetDynamicHandlerEntry), log *logger.Logger, @@ -191,7 +192,7 @@ func (rcT *peeringNetDynamicHandlerRepeatingChannel) handleSendMessage( if rand.Intn(100) < rcT.probability%100 { numRepeat++ } - log.Debugf("Network repeated message %v -%v-> %v %v times", msg.from, msg.msg.MsgType, dstNetID, numRepeat) + log.Debugf("Network repeated message %v -%v-> %v %v times", msg.from.String(), msg.msg.MsgType, dstPubKey.String(), numRepeat) for i := 0; i < numRepeat; i++ { callHandlersAndSendFun(nextHandlers) } @@ -204,7 +205,7 @@ type peeringNetDynamicHandlerDelayingChannel struct { func (dcT *peeringNetDynamicHandlerDelayingChannel) handleSendMessage( msg *peeringMsg, - dstNetID string, + dstPubKey *ed25519.PublicKey, nextHandlers []peeringNetDynamicHandlerEntry, callHandlersAndSendFun func(nextHandlers []peeringNetDynamicHandlerEntry), log *logger.Logger, @@ -219,7 +220,7 @@ func (dcT *peeringNetDynamicHandlerDelayingChannel) handleSendMessage( } else { delay = time.Duration(fromMS) * time.Millisecond } - log.Debugf("Network delayed message %v -%v-> %v for %v", msg.from, msg.msg.MsgType, dstNetID, delay) + log.Debugf("Network delayed message %v -%v-> %v for %v", msg.from.String(), msg.msg.MsgType, dstPubKey.String(), delay) <-time.After(delay) } callHandlersAndSendFun(nextHandlers) @@ -227,22 +228,22 @@ func (dcT *peeringNetDynamicHandlerDelayingChannel) handleSendMessage( } type peeringNetDynamicHandlerPeerDisconnected struct { - peerName string + peerPubKey *ed25519.PublicKey } func (pdT *peeringNetDynamicHandlerPeerDisconnected) handleSendMessage( msg *peeringMsg, - dstNetID string, + dstPubKey *ed25519.PublicKey, nextHandlers []peeringNetDynamicHandlerEntry, callHandlersAndSendFun func(nextHandlers []peeringNetDynamicHandlerEntry), log *logger.Logger, ) { - if dstNetID == pdT.peerName { - log.Debugf("Network dropped message %v -%v-> %v, because destination is disconnected", msg.from, msg.msg.MsgType, dstNetID) + if *dstPubKey == *pdT.peerPubKey { + log.Debugf("Network dropped message %v -%v-> %v, because destination is disconnected", msg.from.String(), msg.msg.MsgType, dstPubKey.String()) return } - if msg.from == pdT.peerName { - log.Debugf("Network dropped message %v -%v-> %v, because source is disconnected", msg.from, msg.msg.MsgType, dstNetID) + if *msg.from == *pdT.peerPubKey { + log.Debugf("Network dropped message %v -%v-> %v, because source is disconnected", msg.from.String(), msg.msg.MsgType, dstPubKey.String()) return } callHandlersAndSendFun(nextHandlers) diff --git a/packages/testutil/peeringNetBehaviourDynamic_test.go b/packages/testutil/peeringNetBehaviourDynamic_test.go index c54c10a920..f8504f8ce8 100644 --- a/packages/testutil/peeringNetBehaviourDynamic_test.go +++ b/packages/testutil/peeringNetBehaviourDynamic_test.go @@ -7,6 +7,7 @@ import ( "testing" "time" + "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/wasp/packages/testutil/testlogger" "github.com/stretchr/testify/require" @@ -22,11 +23,14 @@ func TestPeeringNetDynamicReliable(t *testing.T) { } doneCh <- true }() - someNode := peeringNode{netID: "src"} + // peerNetI, peerIdentities := testpeers.SetupKeys(2) + srcPeerIdentity := ed25519.GenerateKeyPair() + dstPeerIdentity := ed25519.GenerateKeyPair() + someNode := peeringNode{netID: "src", identity: &srcPeerIdentity} // // Run the test. behavior := NewPeeringNetDynamic(testlogger.WithLevel(testlogger.NewLogger(t), logger.LevelError, false)) - behavior.AddLink(inCh, outCh, "dst") + behavior.AddLink(inCh, outCh, &dstPeerIdentity.PublicKey) for i := 0; i < 10; i++ { sendMessage(&someNode, inCh) } @@ -42,14 +46,16 @@ func TestPeeringNetDynamicUnreliable(t *testing.T) { stopCh := make(chan bool) durations := make([]time.Duration, 0) go testRecvLoop(outCh, &durations, stopCh) - someNode := peeringNode{netID: "src"} + srcPeerIdentity := ed25519.GenerateKeyPair() + dstPeerIdentity := ed25519.GenerateKeyPair() + someNode := peeringNode{netID: "src", identity: &srcPeerIdentity} // // Run the test. behavior := NewPeeringNetDynamic(testlogger.WithLevel(testlogger.NewLogger(t), logger.LevelError, false)). WithLosingChannel(nil, 50). WithRepeatingChannel(nil, 50). WithDelayingChannel(nil, 50*time.Millisecond, 100*time.Millisecond) - behavior.AddLink(inCh, outCh, "dst") + behavior.AddLink(inCh, outCh, &dstPeerIdentity.PublicKey) for i := 0; i < 1000; i++ { sendMessage(&someNode, inCh) } @@ -77,11 +83,13 @@ func TestPeeringNetDynamicChanging(t *testing.T) { stopCh := make(chan bool) durations := make([]time.Duration, 0) go testRecvLoop(outCh, &durations, stopCh) - someNode := peeringNode{netID: "src"} + srcPeerIdentity := ed25519.GenerateKeyPair() + dstPeerIdentity := ed25519.GenerateKeyPair() + someNode := peeringNode{netID: "src", identity: &srcPeerIdentity} // // Run the test. behavior := NewPeeringNetDynamic(testlogger.WithLevel(testlogger.NewLogger(t), logger.LevelError, false)) - behavior.AddLink(inCh, outCh, "dst") + behavior.AddLink(inCh, outCh, &dstPeerIdentity.PublicKey) for i := 0; i < 100; i++ { sendMessage(&someNode, inCh) } @@ -134,17 +142,19 @@ func TestPeeringNetDynamicChanging(t *testing.T) { behavior.Close() } -func TestPeeringNetDynamicLosingChannel(t *testing.T) { +func TestPeeringNetDynamicLosingChannel(t *testing.T) { //nolint:dupl inCh := make(chan *peeringMsg) outCh := make(chan *peeringMsg, 1000) stopCh := make(chan bool) durations := make([]time.Duration, 0) go testRecvLoop(outCh, &durations, stopCh) - someNode := peeringNode{netID: "src"} + srcPeerIdentity := ed25519.GenerateKeyPair() + dstPeerIdentity := ed25519.GenerateKeyPair() + someNode := peeringNode{netID: "src", identity: &srcPeerIdentity} // // Run the test. behavior := NewPeeringNetDynamic(testlogger.WithLevel(testlogger.NewLogger(t), logger.LevelError, false)).WithLosingChannel(nil, 50) - behavior.AddLink(inCh, outCh, "dst") + behavior.AddLink(inCh, outCh, &dstPeerIdentity.PublicKey) for i := 0; i < 1000; i++ { sendMessage(&someNode, inCh) } @@ -157,17 +167,19 @@ func TestPeeringNetDynamicLosingChannel(t *testing.T) { behavior.Close() } -func TestPeeringNetDynamicRepeatingChannel(t *testing.T) { +func TestPeeringNetDynamicRepeatingChannel(t *testing.T) { //nolint:dupl inCh := make(chan *peeringMsg) outCh := make(chan *peeringMsg, 10000) stopCh := make(chan bool) durations := make([]time.Duration, 0) go testRecvLoop(outCh, &durations, stopCh) - someNode := peeringNode{netID: "src"} + srcPeerIdentity := ed25519.GenerateKeyPair() + dstPeerIdentity := ed25519.GenerateKeyPair() + someNode := peeringNode{netID: "src", identity: &srcPeerIdentity} // // Run the test. behavior := NewPeeringNetDynamic(testlogger.WithLevel(testlogger.NewLogger(t), logger.LevelError, false)).WithRepeatingChannel(nil, 150) - behavior.AddLink(inCh, outCh, "dst") + behavior.AddLink(inCh, outCh, &dstPeerIdentity.PublicKey) for i := 0; i < 1000; i++ { sendMessage(&someNode, inCh) } @@ -186,11 +198,13 @@ func TestPeeringNetDynamicDelayingChannel(t *testing.T) { stopCh := make(chan bool) durations := make([]time.Duration, 0) go testRecvLoop(outCh, &durations, stopCh) - someNode := peeringNode{netID: "src"} + srcPeerIdentity := ed25519.GenerateKeyPair() + dstPeerIdentity := ed25519.GenerateKeyPair() + someNode := peeringNode{netID: "src", identity: &srcPeerIdentity} // // Run the test. behavior := NewPeeringNetDynamic(testlogger.WithLevel(testlogger.NewLogger(t), logger.LevelError, false)).WithDelayingChannel(nil, 25*time.Millisecond, 75*time.Millisecond) - behavior.AddLink(inCh, outCh, "dst") + behavior.AddLink(inCh, outCh, &dstPeerIdentity.PublicKey) for i := 0; i < 100; i++ { sendMessage(&someNode, inCh) } @@ -213,13 +227,16 @@ func TestPeeringNetDynamicPeerDisconnected(t *testing.T) { durationsD := make([]time.Duration, 0) go testRecvLoop(outCh, &durations, stopCh) go testRecvLoop(outChD, &durationsD, stopCh) - connectedNode := peeringNode{netID: "src"} - disconnectedNode := peeringNode{netID: "disconnected"} + srcPeerIdentity := ed25519.GenerateKeyPair() + dstPeerIdentity := ed25519.GenerateKeyPair() + disPeerIdentity := ed25519.GenerateKeyPair() + connectedNode := peeringNode{netID: "src", identity: &srcPeerIdentity} + disconnectedNode := peeringNode{netID: "disconnected", identity: &disPeerIdentity} // // Run the test. - behavior := NewPeeringNetDynamic(testlogger.WithLevel(testlogger.NewLogger(t), logger.LevelError, false)).WithPeerDisconnected(nil, "disconnected") - behavior.AddLink(inCh, outCh, "dst") - behavior.AddLink(inChD, outChD, "disconnected") + behavior := NewPeeringNetDynamic(testlogger.WithLevel(testlogger.NewLogger(t), logger.LevelError, false)).WithPeerDisconnected(nil, &disPeerIdentity.PublicKey) + behavior.AddLink(inCh, outCh, &dstPeerIdentity.PublicKey) + behavior.AddLink(inChD, outChD, &disPeerIdentity.PublicKey) for i := 0; i < 100; i++ { sendMessage(&connectedNode, inCh) // Will be received sendMessage(&connectedNode, inChD) // Won't be received - destination is disconnected @@ -256,7 +273,7 @@ func averageDuration(durations []time.Duration) int64 { func sendMessage(from *peeringNode, inCh chan *peeringMsg) { inCh <- &peeringMsg{ - from: from.netID, + from: &from.identity.PublicKey, timestamp: time.Now().UnixNano(), } } diff --git a/packages/testutil/peeringNetBehaviour_test.go b/packages/testutil/peeringNetBehaviour_test.go index bd50d544a3..cf5d760f6d 100644 --- a/packages/testutil/peeringNetBehaviour_test.go +++ b/packages/testutil/peeringNetBehaviour_test.go @@ -7,6 +7,7 @@ import ( "testing" "time" + "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/wasp/packages/testutil/testlogger" "github.com/stretchr/testify/require" @@ -22,11 +23,13 @@ func TestPeeringNetReliable(t *testing.T) { } doneCh <- true }() - someNode := peeringNode{netID: "src"} + srcPeerIdentity := ed25519.GenerateKeyPair() + dstPeerIdentity := ed25519.GenerateKeyPair() + someNode := peeringNode{netID: "src", identity: &srcPeerIdentity} behavior := NewPeeringNetReliable(testlogger.WithLevel(testlogger.NewLogger(t), logger.LevelError, false)) - behavior.AddLink(inCh, outCh, "dst") + behavior.AddLink(inCh, outCh, &dstPeerIdentity.PublicKey) for i := 0; i < 10; i++ { - inCh <- &peeringMsg{from: someNode.netID} + inCh <- &peeringMsg{from: &someNode.identity.PublicKey} } <-doneCh behavior.Close() @@ -54,11 +57,13 @@ func TestPeeringNetUnreliable(t *testing.T) { }() // // Run the test. - someNode := peeringNode{netID: "src"} + srcPeerIdentity := ed25519.GenerateKeyPair() + dstPeerIdentity := ed25519.GenerateKeyPair() + someNode := peeringNode{netID: "src", identity: &srcPeerIdentity} behavior := NewPeeringNetUnreliable(50, 50, 50*time.Millisecond, 100*time.Millisecond, testlogger.WithLevel(testlogger.NewLogger(t), logger.LevelError, false)) - behavior.AddLink(inCh, outCh, "dst") + behavior.AddLink(inCh, outCh, &dstPeerIdentity.PublicKey) for i := 0; i < 1000; i++ { - inCh <- &peeringMsg{from: someNode.netID} + inCh <- &peeringMsg{from: &someNode.identity.PublicKey} } time.Sleep(500 * time.Millisecond) // @@ -102,11 +107,13 @@ func TestPeeringNetGoodQuality(t *testing.T) { }() // // Run the test. - someNode := peeringNode{netID: "src"} + srcPeerIdentity := ed25519.GenerateKeyPair() + dstPeerIdentity := ed25519.GenerateKeyPair() + someNode := peeringNode{netID: "src", identity: &srcPeerIdentity} behavior := NewPeeringNetUnreliable(100, 0, 0*time.Microsecond, 0*time.Millisecond, testlogger.WithLevel(testlogger.NewLogger(t), logger.LevelError, false)) // NOTE: No drops, duplicates, delays. - behavior.AddLink(inCh, outCh, "dst") + behavior.AddLink(inCh, outCh, &dstPeerIdentity.PublicKey) for i := 0; i < 1000; i++ { - inCh <- &peeringMsg{from: someNode.netID} + inCh <- &peeringMsg{from: &someNode.identity.PublicKey} } time.Sleep(500 * time.Millisecond) // diff --git a/packages/testutil/peeringNetworkProvider.go b/packages/testutil/peeringNetworkProvider.go index 2ad8e92466..395c341d8b 100644 --- a/packages/testutil/peeringNetworkProvider.go +++ b/packages/testutil/peeringNetworkProvider.go @@ -26,17 +26,6 @@ type PeeringNetwork struct { log *logger.Logger } -// NewPeeringNetworkForLocs creates a test network with new keys, etc. -func NewPeeringNetworkForLocs(peerNetIDs []string, bufSize int, log *logger.Logger) *PeeringNetwork { - identities := make([]*ed25519.KeyPair, len(peerNetIDs)) - for i := range identities { - nodeIdentity := ed25519.GenerateKeyPair() - identities[i] = &nodeIdentity - } - behavior := NewPeeringNetReliable(log) - return NewPeeringNetwork(peerNetIDs, identities, bufSize, behavior, log) -} - // NewPeeringNetwork creates new test network, it can then be used to create network nodes. func NewPeeringNetwork( netIDs []string, @@ -72,9 +61,9 @@ func (p *PeeringNetwork) NetworkProviders() []peering.NetworkProvider { return cp } -func (p *PeeringNetwork) nodeByNetID(nodeNetID string) *peeringNode { +func (p *PeeringNetwork) nodeByPubKey(nodePubKey *ed25519.PublicKey) *peeringNode { for i := range p.nodes { - if p.nodes[i].netID == nodeNetID { + if p.nodes[i].identity.PublicKey == *nodePubKey { return p.nodes[i] } } @@ -108,7 +97,7 @@ type peeringNode struct { } type peeringMsg struct { - from string + from *ed25519.PublicKey msg peering.PeerMessageData timestamp int64 } @@ -133,7 +122,7 @@ func newPeeringNode(netID string, identity *ed25519.KeyPair, network *PeeringNet network: network, log: network.log.With("loc", netID), } - network.behavior.AddLink(sendCh, recvCh, netID) + network.behavior.AddLink(sendCh, recvCh, &identity.PublicKey) go n.recvLoop() return &n } @@ -145,14 +134,14 @@ func (n *peeringNode) recvLoop() { if cb.peeringID.String() == msgPeeringID && cb.receiver == pm.msg.MsgReceiver { cb.callback(&peering.PeerMessageIn{ PeerMessageData: pm.msg, - SenderNetID: pm.from, + SenderPubKey: pm.from, }) } } } } -func (n *peeringNode) sendMsg(from string, msg *peering.PeerMessageData) { +func (n *peeringNode) sendMsg(from *ed25519.PublicKey, msg *peering.PeerMessageData) { n.sendCh <- &peeringMsg{ from: from, msg: *msg, @@ -199,22 +188,30 @@ func (p *peeringNetworkProvider) Self() peering.PeerSender { return newPeeringSender(p.self, p) } -// Group implements peering.NetworkProvider. -func (p *peeringNetworkProvider) PeerGroup(peeringID peering.PeeringID, peerAddrs []string) (peering.GroupProvider, error) { - peers := make([]peering.PeerSender, len(peerAddrs)) - for i := range peerAddrs { - n := p.network.nodeByNetID(peerAddrs[i]) +// PeerGroup implements peering.NetworkProvider. +func (p *peeringNetworkProvider) PeerGroup(peeringID peering.PeeringID, peerPubKeys []*ed25519.PublicKey) (peering.GroupProvider, error) { + peers := make([]peering.PeerSender, len(peerPubKeys)) + for i := range peerPubKeys { + n := p.network.nodeByPubKey(peerPubKeys[i]) if n == nil { - return nil, errors.New("unknown_node_location") + return nil, errors.New("unknown node location") } peers[i] = p.senders[i] } return group.NewPeeringGroupProvider(p, peeringID, peers, p.network.log) } -// Domain creates peering.PeerDomainProvider. -func (p *peeringNetworkProvider) PeerDomain(peeringID peering.PeeringID, peerNetIDs []string) (peering.PeerDomainProvider, error) { - return domain.NewPeerDomainByNetIDs(p, peeringID, peerNetIDs, p.network.log) +// PeerDomain creates peering.PeerDomainProvider. +func (p *peeringNetworkProvider) PeerDomain(peeringID peering.PeeringID, peerPubKeys []*ed25519.PublicKey) (peering.PeerDomainProvider, error) { + peers := make([]peering.PeerSender, len(peerPubKeys)) + for i := range peerPubKeys { + n := p.network.nodeByPubKey(peerPubKeys[i]) + if n == nil { + return nil, errors.New("unknown node pub key") + } + peers[i] = p.senders[i] + } + return domain.NewPeerDomain(p, peeringID, peers, p.network.log), nil } // Attach implements peering.NetworkProvider. @@ -237,8 +234,8 @@ func (p *peeringNetworkProvider) Detach(attachID interface{}) { // Detach is not important in tests. } -func (p *peeringNetworkProvider) SendMsgByNetID(netID string, msg *peering.PeerMessageData) { - s, err := p.PeerByNetID(netID) +func (p *peeringNetworkProvider) SendMsgByPubKey(peerPubKey *ed25519.PublicKey, msg *peering.PeerMessageData) { + s, err := p.PeerByPubKey(peerPubKey) if err == nil { s.SendMsg(msg) } @@ -310,7 +307,7 @@ func (p *peeringSender) PubKey() *ed25519.PublicKey { // Send implements peering.PeerSender. func (p *peeringSender) SendMsg(msg *peering.PeerMessageData) { - p.node.sendMsg(p.netProvider.self.netID, msg) + p.node.sendMsg(&p.netProvider.self.identity.PublicKey, msg) } // IsAlive implements peering.PeerSender. @@ -337,3 +334,8 @@ func (p *peeringSender) NumUsers() int { func (p *peeringSender) Close() { // Not needed in tests. } + +// Status implements peering.PeerSender. +func (p *peeringSender) Status() peering.PeerStatusProvider { + return p +} diff --git a/packages/testutil/peeringNetworkProvider_test.go b/packages/testutil/peeringNetworkProvider_test.go index 47229ac676..a609bb58a7 100644 --- a/packages/testutil/peeringNetworkProvider_test.go +++ b/packages/testutil/peeringNetworkProvider_test.go @@ -7,10 +7,10 @@ import ( "testing" "time" - "github.com/iotaledger/wasp/packages/testutil/testlogger" - "github.com/iotaledger/wasp/packages/peering" "github.com/iotaledger/wasp/packages/testutil" + "github.com/iotaledger/wasp/packages/testutil/testlogger" + "github.com/iotaledger/wasp/packages/testutil/testpeers" ) func TestFakeNetwork(t *testing.T) { @@ -20,7 +20,8 @@ func TestFakeNetwork(t *testing.T) { chain1 := peering.RandomPeeringID() chain2 := peering.RandomPeeringID() receiver := byte(0) - network := testutil.NewPeeringNetworkForLocs([]string{"a", "b", "c"}, 100, log) + peerNetIDs, nodeIdentities := testpeers.SetupKeys(3) + network := testutil.NewPeeringNetwork(peerNetIDs, nodeIdentities, 100, testutil.NewPeeringNetReliable(log), log) var netProviders []peering.NetworkProvider = network.NetworkProviders() // // Node "a" listens for chain1 messages. @@ -30,8 +31,8 @@ func TestFakeNetwork(t *testing.T) { // // Node "b" sends some messages. var a, c peering.PeerSender - a, _ = netProviders[1].PeerByNetID("a") - c, _ = netProviders[1].PeerByNetID("c") + a, _ = netProviders[1].PeerByPubKey(&nodeIdentities[0].PublicKey) + c, _ = netProviders[1].PeerByPubKey(&nodeIdentities[2].PublicKey) a.SendMsg(&peering.PeerMessageData{PeeringID: chain1, MsgReceiver: receiver, MsgType: 1}) // Will be delivered. a.SendMsg(&peering.PeerMessageData{PeeringID: chain2, MsgReceiver: receiver, MsgType: 2}) // Will be dropped. a.SendMsg(&peering.PeerMessageData{PeeringID: chain1, MsgReceiver: byte(5), MsgType: 3}) // Will be dropped. diff --git a/packages/testutil/testchain/mock_chain_core.go b/packages/testutil/testchain/mock_chain_core.go index 70833248d2..c22f928fd4 100644 --- a/packages/testutil/testchain/mock_chain_core.go +++ b/packages/testutil/testchain/mock_chain_core.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package testchain import ( @@ -14,6 +17,7 @@ import ( "github.com/iotaledger/wasp/packages/iscp/coreutil" "github.com/iotaledger/wasp/packages/peering" "github.com/iotaledger/wasp/packages/state" + "github.com/iotaledger/wasp/packages/vm/core/governance" "github.com/iotaledger/wasp/packages/vm/processors" ) @@ -206,3 +210,11 @@ func (m *MockedChainCore) OnMissingRequest(fun func(msg *messages.MissingRequest func (m *MockedChainCore) OnTimerTick(fun func(tick int)) { m.onTimerTick = fun } + +func (m *MockedChainCore) GetChainNodes() []peering.PeerStatusProvider { + panic("not implemented MockedChainCore::GetChainNodes") +} + +func (m *MockedChainCore) GetCandidateNodes() []*governance.AccessNodeInfo { + panic("not implemented MockedChainCore::GetCandidateNodes") +} diff --git a/packages/testutil/testchain/mock_registry.go b/packages/testutil/testchain/mock_registry.go deleted file mode 100644 index bc9eb83aaa..0000000000 --- a/packages/testutil/testchain/mock_registry.go +++ /dev/null @@ -1,25 +0,0 @@ -package testchain - -import ( - "github.com/iotaledger/goshimmer/packages/ledgerstate" - "github.com/iotaledger/wasp/packages/registry" -) - -type MockedCommitteeRegistry struct { - validators []string -} - -func NewMockedCommitteeRegistry(validators []string) *MockedCommitteeRegistry { - return &MockedCommitteeRegistry{validators} -} - -func (m *MockedCommitteeRegistry) GetCommitteeRecord(addr ledgerstate.Address) (*registry.CommitteeRecord, error) { - return ®istry.CommitteeRecord{ - Address: addr, - Nodes: m.validators, - }, nil -} - -func (m *MockedCommitteeRegistry) SaveCommitteeRecord(rec *registry.CommitteeRecord) error { - panic("implement me") -} diff --git a/packages/testutil/testpeers/testkeys.go b/packages/testutil/testpeers/testkeys.go index 240c1b6fdc..75ab0461f4 100644 --- a/packages/testutil/testpeers/testkeys.go +++ b/packages/testutil/testpeers/testkeys.go @@ -32,10 +32,10 @@ func SetupKeys(peerCount uint16) ([]string, []*ed25519.KeyPair) { return peerNetIDs, peerIdentities } -func PublicKeys(peerIdentities []*ed25519.KeyPair) []ed25519.PublicKey { - pubKeys := make([]ed25519.PublicKey, len(peerIdentities)) +func PublicKeys(peerIdentities []*ed25519.KeyPair) []*ed25519.PublicKey { + pubKeys := make([]*ed25519.PublicKey, len(peerIdentities)) for i := range pubKeys { - pubKeys[i] = peerIdentities[i].PublicKey + pubKeys[i] = &peerIdentities[i].PublicKey } return pubKeys } @@ -66,7 +66,6 @@ func SetupDkg( // // Initiate the key generation from some client node. dkShare, err := dkgNodes[0].GenerateDistributedKey( - peerNetIDs, PublicKeys(peerIdentities), threshold, 100*time.Second, @@ -83,15 +82,20 @@ func SetupDkg( func SetupDkgPregenerated( t *testing.T, threshold uint16, - peerNetIDs []string, + identities []*ed25519.KeyPair, suite tcrypto.Suite, ) (ledgerstate.Address, []registry.DKShareRegistryProvider) { var err error - var serializedDks [][]byte = pregeneratedDksRead(uint16(len(peerNetIDs)), threshold) + var serializedDks [][]byte = pregeneratedDksRead(uint16(len(identities)), threshold) + nodePubKeys := make([]*ed25519.PublicKey, len(identities)) + for i := range nodePubKeys { + nodePubKeys[i] = &identities[i].PublicKey + } dks := make([]*tcrypto.DKShare, len(serializedDks)) - registries := make([]registry.DKShareRegistryProvider, len(peerNetIDs)) + registries := make([]registry.DKShareRegistryProvider, len(identities)) for i := range dks { dks[i], err = tcrypto.DKShareFromBytes(serializedDks[i], suite) + dks[i].NodePubKeys = nodePubKeys if i > 0 { // It was removed to decrease the serialized size. dks[i].PublicCommits = dks[0].PublicCommits @@ -101,7 +105,7 @@ func SetupDkgPregenerated( registries[i] = testutil.NewDkgRegistryProvider(suite) require.Nil(t, registries[i].SaveDKShare(dks[i])) } - require.Equal(t, dks[0].N, uint16(len(peerNetIDs)), "dks was pregenerated for different node count (N=%v)", dks[0].N) + require.Equal(t, dks[0].N, uint16(len(identities)), "dks was pregenerated for different node count (N=%v)", dks[0].N) require.Equal(t, dks[0].T, threshold, "dks was pregenerated for different threshold (T=%v)", dks[0].T) return dks[0].Address, registries } diff --git a/packages/testutil/testpeers/testkeys_pregenerated-1-1.bin b/packages/testutil/testpeers/testkeys_pregenerated-1-1.bin index 25d86fbd33..e847dbd39b 100644 Binary files a/packages/testutil/testpeers/testkeys_pregenerated-1-1.bin and b/packages/testutil/testpeers/testkeys_pregenerated-1-1.bin differ diff --git a/packages/testutil/testpeers/testkeys_pregenerated-10-7.bin b/packages/testutil/testpeers/testkeys_pregenerated-10-7.bin index 633fcf9661..e7ac38cb68 100644 Binary files a/packages/testutil/testpeers/testkeys_pregenerated-10-7.bin and b/packages/testutil/testpeers/testkeys_pregenerated-10-7.bin differ diff --git a/packages/testutil/testpeers/testkeys_pregenerated-100-67.bin b/packages/testutil/testpeers/testkeys_pregenerated-100-67.bin index a7953a510f..8a50d5c13d 100644 Binary files a/packages/testutil/testpeers/testkeys_pregenerated-100-67.bin and b/packages/testutil/testpeers/testkeys_pregenerated-100-67.bin differ diff --git a/packages/testutil/testpeers/testkeys_pregenerated-22-15.bin b/packages/testutil/testpeers/testkeys_pregenerated-22-15.bin index 6ae447247a..2e4e32abc7 100644 Binary files a/packages/testutil/testpeers/testkeys_pregenerated-22-15.bin and b/packages/testutil/testpeers/testkeys_pregenerated-22-15.bin differ diff --git a/packages/testutil/testpeers/testkeys_pregenerated-31-21.bin b/packages/testutil/testpeers/testkeys_pregenerated-31-21.bin index 7103af67a6..c33b30cb5d 100644 Binary files a/packages/testutil/testpeers/testkeys_pregenerated-31-21.bin and b/packages/testutil/testpeers/testkeys_pregenerated-31-21.bin differ diff --git a/packages/testutil/testpeers/testkeys_pregenerated-4-3.bin b/packages/testutil/testpeers/testkeys_pregenerated-4-3.bin index c9a5176e23..0a10105eff 100644 Binary files a/packages/testutil/testpeers/testkeys_pregenerated-4-3.bin and b/packages/testutil/testpeers/testkeys_pregenerated-4-3.bin differ diff --git a/packages/testutil/testpeers/testkeys_pregenerated-4-4.bin b/packages/testutil/testpeers/testkeys_pregenerated-4-4.bin index becdfb3178..f084b239ed 100644 Binary files a/packages/testutil/testpeers/testkeys_pregenerated-4-4.bin and b/packages/testutil/testpeers/testkeys_pregenerated-4-4.bin differ diff --git a/packages/testutil/testpeers/testkeys_pregenerated-40-27.bin b/packages/testutil/testpeers/testkeys_pregenerated-40-27.bin index e19e3a142d..2c686fc0ce 100644 Binary files a/packages/testutil/testpeers/testkeys_pregenerated-40-27.bin and b/packages/testutil/testpeers/testkeys_pregenerated-40-27.bin differ diff --git a/packages/testutil/testpeers/testkeys_pregenerated-70-47.bin b/packages/testutil/testpeers/testkeys_pregenerated-70-47.bin index dc6f5d90fb..9b3ebaa7ab 100644 Binary files a/packages/testutil/testpeers/testkeys_pregenerated-70-47.bin and b/packages/testutil/testpeers/testkeys_pregenerated-70-47.bin differ diff --git a/packages/testutil/testpeers/testkeys_pregenerated_test.go b/packages/testutil/testpeers/testkeys_pregenerated_test.go index 3acd485926..ca45eecb11 100644 --- a/packages/testutil/testpeers/testkeys_pregenerated_test.go +++ b/packages/testutil/testpeers/testkeys_pregenerated_test.go @@ -9,6 +9,7 @@ import ( "os" "testing" + "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/wasp/packages/tcrypto" "github.com/iotaledger/wasp/packages/testutil/testlogger" "github.com/iotaledger/wasp/packages/testutil/testpeers" @@ -51,6 +52,7 @@ func testPregenerateDKS(t *testing.T, n, f uint16) { dki.PublicCommits = make([]kyber.Point, 0) dki.PublicShares = make([]kyber.Point, 0) } + dki.NodePubKeys = make([]*ed25519.PublicKey, 0) dkb = dki.Bytes() require.Nil(t, util.WriteBytes16(&buf, dkb)) } diff --git a/packages/testutil/trustedNetworkManager.go b/packages/testutil/trustedNetworkManager.go index 0ba5512b74..1eb46ba277 100644 --- a/packages/testutil/trustedNetworkManager.go +++ b/packages/testutil/trustedNetworkManager.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package testutil import ( diff --git a/packages/vm/core/governance/accessnodes.go b/packages/vm/core/governance/accessnodes.go index 39afeea870..3431a532f0 100644 --- a/packages/vm/core/governance/accessnodes.go +++ b/packages/vm/core/governance/accessnodes.go @@ -17,6 +17,38 @@ import ( "golang.org/x/xerrors" ) +// NodeOwnershipCertificate is a proof that a specified address is an owner of the specified node. +// It is implemented as a signature over the node pub key concatenated with the owner address. +type NodeOwnershipCertificate []byte + +func NewNodeOwnershipCertificate(nodeKeyPair *ed25519.KeyPair, ownerAddress ledgerstate.Address) NodeOwnershipCertificate { + certData := bytes.Buffer{} + certData.Write(nodeKeyPair.PublicKey.Bytes()) + certData.Write(ownerAddress.Bytes()) + return nodeKeyPair.PrivateKey.Sign(certData.Bytes()).Bytes() +} + +func NewNodeOwnershipCertificateFromBytes(data []byte) NodeOwnershipCertificate { + return NodeOwnershipCertificate(data) +} + +func (c NodeOwnershipCertificate) Verify(nodePubKey ed25519.PublicKey, ownerAddress ledgerstate.Address) bool { + certData := bytes.Buffer{} + certData.Write(nodePubKey.Bytes()) + certData.Write(ownerAddress.Bytes()) + signature, _, err := ed25519.SignatureFromBytes(c.Bytes()) + if err != nil { + return false + } + return nodePubKey.VerifySignature(certData.Bytes(), signature) +} + +func (c NodeOwnershipCertificate) Bytes() []byte { + return c +} + +// AccessNodeInfo conveys all the information that is maintained +// on the governance SC about a specific node. type AccessNodeInfo struct { NodePubKey []byte // Public Key of the node. Stored as a key in the SC State and Params. ValidatorAddr []byte // Address of the validator owning the node. Not sent via parameters. @@ -45,6 +77,26 @@ func NewAccessNodeInfoFromBytes(pubKey, value []byte) (*AccessNodeInfo, error) { return &a, nil } +func NewAccessNodeInfoListFromMap(infoMap *collections.ImmutableMap) ([]*AccessNodeInfo, error) { + res := make([]*AccessNodeInfo, 0) + var accErr error + err := infoMap.Iterate(func(elemKey, value []byte) bool { + var a *AccessNodeInfo + if a, accErr = NewAccessNodeInfoFromBytes(elemKey, value); accErr != nil { + return false + } + res = append(res, a) + return true + }) + if accErr != nil { + return nil, xerrors.Errorf("failed to iterate over AccessNodeInfo list: %v", accErr) + } + if err != nil { + return nil, xerrors.Errorf("failed to iterate over AccessNodeInfo list: %v", err) + } + return res, nil +} + func (a *AccessNodeInfo) Bytes() []byte { w := bytes.Buffer{} // NodePubKey stored as a map key. @@ -101,19 +153,22 @@ func (a *AccessNodeInfo) ToRevokeAccessNodeParams() dict.Dict { return d } -func (a *AccessNodeInfo) AddCertificate(nodePrivKey ed25519.PrivateKey, ownerAddress ledgerstate.Address) *AccessNodeInfo { - certData := bytes.Buffer{} - certData.Write(a.NodePubKey) - certData.Write(ownerAddress.Bytes()) - a.Certificate = nodePrivKey.Sign(certData.Bytes()).Bytes() +func (a *AccessNodeInfo) AddCertificate(nodeKeyPair *ed25519.KeyPair, ownerAddress ledgerstate.Address) *AccessNodeInfo { + a.Certificate = NewNodeOwnershipCertificate(nodeKeyPair, ownerAddress).Bytes() return a } func (a *AccessNodeInfo) ValidateCertificate(ctx iscp.Sandbox) bool { - signedData := bytes.Buffer{} - signedData.Write(a.NodePubKey) - signedData.Write(a.ValidatorAddr) - return ctx.Utils().ED25519().ValidSignature(signedData.Bytes(), a.NodePubKey, a.Certificate) + nodePubKey, _, err := ed25519.PublicKeyFromBytes(a.NodePubKey) + if err != nil { + return false + } + validatorAddr, _, err := ledgerstate.AddressFromBytes(a.ValidatorAddr) + if err != nil { + return false + } + cert := NewNodeOwnershipCertificateFromBytes(a.Certificate) + return cert.Verify(nodePubKey, validatorAddr) } // diff --git a/packages/vm/core/governance/governanceimpl/accessnodesImpl.go b/packages/vm/core/governance/governanceimpl/accessnodesImpl.go index bded42eb38..4f4c984519 100644 --- a/packages/vm/core/governance/governanceimpl/accessnodesImpl.go +++ b/packages/vm/core/governance/governanceimpl/accessnodesImpl.go @@ -13,6 +13,8 @@ package governanceimpl import ( + "encoding/base64" + "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/iscp/assert" "github.com/iotaledger/wasp/packages/kv/collections" @@ -54,9 +56,17 @@ func addCandidateNodeFuncHandler(ctx iscp.Sandbox) (dict.Dict, error) { ani := governance.NewAccessNodeInfoFromAddCandidateNodeParams(ctx) a.Require(ani.ValidateCertificate(ctx), "certificate invalid") + pubKeyStr := base64.StdEncoding.EncodeToString(ani.NodePubKey) accessNodeCandidates := collections.NewMap(ctx.State(), governance.VarAccessNodeCandidates) accessNodeCandidates.MustSetAt(ani.NodePubKey, ani.Bytes()) + ctx.Log().Infof("Governance::AddCandidateNode: accessNodeCandidate added, pubKey=%s", pubKeyStr) + + if ctx.ChainOwnerID().Address().Equals(ctx.Request().SenderAddress()) { + accessNodes := collections.NewMap(ctx.State(), governance.VarAccessNodes) + accessNodes.MustSetAt(ani.NodePubKey, make([]byte, 0)) + ctx.Log().Infof("Governance::AddCandidateNode: accessNode added, pubKey=%s", pubKeyStr) + } return nil, nil } diff --git a/packages/vm/core/governance/governanceimpl/statecontroller.go b/packages/vm/core/governance/governanceimpl/statecontroller.go index 88c6e820e0..7f9f53a96a 100644 --- a/packages/vm/core/governance/governanceimpl/statecontroller.go +++ b/packages/vm/core/governance/governanceimpl/statecontroller.go @@ -33,6 +33,7 @@ func rotateStateController(ctx iscp.Sandbox) (dict.Dict, error) { // rotate request to another address has been issued. State update will be taken over by VM and will have no effect // By setting StateVarRotateToAddress we signal the VM this special situation // StateVarRotateToAddress value should never persist in the state + ctx.Log().Infof("Governance::RotateStateController: newStateControllerAddress=%s", newStateControllerAddr.String()) ctx.State().Set(governance.StateVarRotateToAddress, newStateControllerAddr.Bytes()) return nil, nil } diff --git a/packages/vm/core/testcore/governance_test.go b/packages/vm/core/testcore/governance_test.go index 99e5c5330e..2e0b87c082 100644 --- a/packages/vm/core/testcore/governance_test.go +++ b/packages/vm/core/testcore/governance_test.go @@ -141,7 +141,7 @@ func TestAccessNodes(t *testing.T) { NodePubKey: node1KP.PublicKey.Bytes(), ForCommittee: false, AccessAPI: "http://my-api/url", - }).AddCertificate(node1KP.PrivateKey, node1OwnerAddr).ToAddCandidateNodeParams(), + }).AddCertificate(node1KP, node1OwnerAddr).ToAddCandidateNodeParams(), ).WithIotas(1), node1OwnerKP, // Sender should match data used to create the Cert field value. ) @@ -189,7 +189,7 @@ func TestAccessNodes(t *testing.T) { governance.FuncRevokeAccessNode.Name, (&governance.AccessNodeInfo{ NodePubKey: node1KP.PublicKey.Bytes(), - }).AddCertificate(node1KP.PrivateKey, node1OwnerAddr).ToAddCandidateNodeParams(), + }).AddCertificate(node1KP, node1OwnerAddr).ToAddCandidateNodeParams(), ).WithIotas(1), node1OwnerKP, // Sender should match data used to create the Cert field value. ) diff --git a/packages/vm/core/testcore/sbtests/sbtestsc/impl_misc.go b/packages/vm/core/testcore/sbtests/sbtestsc/impl_misc.go index d2e8e9c108..2d5bab077b 100644 --- a/packages/vm/core/testcore/sbtests/sbtestsc/impl_misc.go +++ b/packages/vm/core/testcore/sbtests/sbtestsc/impl_misc.go @@ -2,7 +2,7 @@ package sbtestsc import ( "github.com/iotaledger/wasp/packages/iscp" - assert2 "github.com/iotaledger/wasp/packages/iscp/assert" + "github.com/iotaledger/wasp/packages/iscp/assert" "github.com/iotaledger/wasp/packages/kv" "github.com/iotaledger/wasp/packages/kv/codec" "github.com/iotaledger/wasp/packages/kv/dict" @@ -60,7 +60,7 @@ func runRecursion(ctx iscp.Sandbox) (dict.Dict, error) { func getFibonacci(ctx iscp.SandboxView) (dict.Dict, error) { params := kvdecoder.New(ctx.Params(), ctx.Log()) - a := assert2.NewAssert(ctx.Log()) + a := assert.NewAssert(ctx.Log()) callInt := params.MustGetInt64(ParamIntParamValue) ctx.Log().Infof("fibonacci( %d )", callInt) diff --git a/packages/vm/core/testcore/sbtests/sbtestsc/testcore_bg.wasm b/packages/vm/core/testcore/sbtests/sbtestsc/testcore_bg.wasm index e3b2cafe6e..4c5b2af584 100644 Binary files a/packages/vm/core/testcore/sbtests/sbtestsc/testcore_bg.wasm and b/packages/vm/core/testcore/sbtests/sbtestsc/testcore_bg.wasm differ diff --git a/packages/vm/wasmlib/go/wasmclient/arguments.go b/packages/vm/wasmlib/go/wasmclient/arguments.go new file mode 100644 index 0000000000..bea1f46bfb --- /dev/null +++ b/packages/vm/wasmlib/go/wasmclient/arguments.go @@ -0,0 +1,33 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package wasmclient + +import ( + "strconv" +) + +// The Arguments struct is used to gather all arguments for a smart +// contract function call and encode it into a deterministic byte array +type Arguments struct { + Encoder + args ArgMap +} + +func (a *Arguments) Set(key string, val []byte) { + if a.args == nil { + a.args = make(ArgMap) + } + a.args.Set(key, val) +} + +func (a *Arguments) IndexedKey(key string, index int) string { + return key + "." + strconv.Itoa(index) +} + +func (a *Arguments) Mandatory(key string) { + if a.args != nil && a.args.Get(key) != nil { + return + } + panic("missing mandatory " + key) +} diff --git a/packages/vm/wasmlib/go/wasmclient/clientfunc.go b/packages/vm/wasmlib/go/wasmclient/clientfunc.go new file mode 100644 index 0000000000..07654bbc88 --- /dev/null +++ b/packages/vm/wasmlib/go/wasmclient/clientfunc.go @@ -0,0 +1,43 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package wasmclient + +import "github.com/iotaledger/hive.go/crypto/ed25519" + +type ClientFunc struct { + svc *Service + keyPair *ed25519.KeyPair + onLedger bool + xfer *Transfer +} + +// OnLedgerRequest can override the default off-ledger to on-ledger posting +func (f *ClientFunc) OnLedgerRequest(onLedger bool) { + f.onLedger = onLedger +} + +// Post sends a request to the smart contract service +// You can wait for the request to complete by using the returned Request +// as parameter to Service.WaitRequest() +func (f *ClientFunc) Post(hFuncName uint32, args *Arguments) Request { + keyPair := f.keyPair + if keyPair == nil { + keyPair = f.svc.keyPair + } + if args == nil { + args = &Arguments{} + } + return f.svc.PostRequest(hFuncName, args.args, f.xfer, keyPair, f.onLedger) +} + +// Sign optionally overrides the default keypair from the service +func (f *ClientFunc) Sign(keyPair *ed25519.KeyPair) { + f.keyPair = keyPair +} + +// Transfer optionally indicates which tokens to transfer as part of the request +// The tokens are presumed to be available in the signing account on the chain +func (f *ClientFunc) Transfer(xfer *Transfer) { + f.xfer = xfer +} diff --git a/packages/vm/wasmlib/go/wasmclient/clientview.go b/packages/vm/wasmlib/go/wasmclient/clientview.go new file mode 100644 index 0000000000..bd0ceed8a2 --- /dev/null +++ b/packages/vm/wasmlib/go/wasmclient/clientview.go @@ -0,0 +1,25 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package wasmclient + +type ClientView struct { + svc *Service + err error + res ResMap +} + +func (v *ClientView) Call(viewName string, args *Arguments) { + if args == nil { + args = &Arguments{} + } + v.res, v.err = v.svc.CallView(viewName, args.args) +} + +func (v *ClientView) Error() error { + return v.err +} + +func (v *ClientView) Results() Results { + return Results{res: v.res} +} diff --git a/packages/vm/wasmlib/go/wasmclient/coreaccounts/service.go b/packages/vm/wasmlib/go/wasmclient/coreaccounts/service.go new file mode 100644 index 0000000000..269b5a35ed --- /dev/null +++ b/packages/vm/wasmlib/go/wasmclient/coreaccounts/service.go @@ -0,0 +1,204 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// (Re-)generated by schema tool +// >>>> DO NOT CHANGE THIS FILE! <<<< +// Change the json schema instead + +package coreaccountsclient + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmclient" + +const ( + ArgAgentID = "a" + ArgWithdrawAmount = "m" + ArgWithdrawColor = "c" + + ResAccountNonce = "n" + ResAgents = "this" + ResBalances = "this" +) + +///////////////////////////// deposit ///////////////////////////// + +type DepositFunc struct { + wasmclient.ClientFunc + args wasmclient.Arguments +} + +func (f *DepositFunc) AgentID(v wasmclient.AgentID) { + f.args.Set(ArgAgentID, f.args.FromAgentID(v)) +} + +func (f *DepositFunc) Post() wasmclient.Request { + return f.ClientFunc.Post(0xbdc9102d, &f.args) +} + +///////////////////////////// harvest ///////////////////////////// + +type HarvestFunc struct { + wasmclient.ClientFunc + args wasmclient.Arguments +} + +func (f *HarvestFunc) WithdrawAmount(v int64) { + f.args.Set(ArgWithdrawAmount, f.args.FromInt64(v)) +} + +func (f *HarvestFunc) WithdrawColor(v wasmclient.Color) { + f.args.Set(ArgWithdrawColor, f.args.FromColor(v)) +} + +func (f *HarvestFunc) Post() wasmclient.Request { + return f.ClientFunc.Post(0x7b40efbd, &f.args) +} + +///////////////////////////// withdraw ///////////////////////////// + +type WithdrawFunc struct { + wasmclient.ClientFunc +} + +func (f *WithdrawFunc) Post() wasmclient.Request { + return f.ClientFunc.Post(0x9dcc0f41, nil) +} + +///////////////////////////// accounts ///////////////////////////// + +type AccountsView struct { + wasmclient.ClientView +} + +func (f *AccountsView) Call() AccountsResults { + f.ClientView.Call("accounts", nil) + return AccountsResults{res: f.Results()} +} + +type AccountsResults struct { + res wasmclient.Results +} + +func (r *AccountsResults) Agents() map[wasmclient.AgentID][]byte { + res := make(map[wasmclient.AgentID][]byte) + r.res.ForEach(func(key []byte, val []byte) { + res[r.res.ToAgentID(key)] = r.res.ToBytes(val) + }) + return res +} + +///////////////////////////// balance ///////////////////////////// + +type BalanceView struct { + wasmclient.ClientView + args wasmclient.Arguments +} + +func (f *BalanceView) AgentID(v wasmclient.AgentID) { + f.args.Set(ArgAgentID, f.args.FromAgentID(v)) +} + +func (f *BalanceView) Call() BalanceResults { + f.args.Mandatory(ArgAgentID) + f.ClientView.Call("balance", &f.args) + return BalanceResults{res: f.Results()} +} + +type BalanceResults struct { + res wasmclient.Results +} + +func (r *BalanceResults) Balances() map[wasmclient.Color]int64 { + res := make(map[wasmclient.Color]int64) + r.res.ForEach(func(key []byte, val []byte) { + res[r.res.ToColor(key)] = r.res.ToInt64(val) + }) + return res +} + +///////////////////////////// getAccountNonce ///////////////////////////// + +type GetAccountNonceView struct { + wasmclient.ClientView + args wasmclient.Arguments +} + +func (f *GetAccountNonceView) AgentID(v wasmclient.AgentID) { + f.args.Set(ArgAgentID, f.args.FromAgentID(v)) +} + +func (f *GetAccountNonceView) Call() GetAccountNonceResults { + f.args.Mandatory(ArgAgentID) + f.ClientView.Call("getAccountNonce", &f.args) + return GetAccountNonceResults{res: f.Results()} +} + +type GetAccountNonceResults struct { + res wasmclient.Results +} + +func (r *GetAccountNonceResults) AccountNonce() int64 { + return r.res.ToInt64(r.res.Get(ResAccountNonce)) +} + +///////////////////////////// totalAssets ///////////////////////////// + +type TotalAssetsView struct { + wasmclient.ClientView +} + +func (f *TotalAssetsView) Call() TotalAssetsResults { + f.ClientView.Call("totalAssets", nil) + return TotalAssetsResults{res: f.Results()} +} + +type TotalAssetsResults struct { + res wasmclient.Results +} + +func (r *TotalAssetsResults) Balances() map[wasmclient.Color]int64 { + res := make(map[wasmclient.Color]int64) + r.res.ForEach(func(key []byte, val []byte) { + res[r.res.ToColor(key)] = r.res.ToInt64(val) + }) + return res +} + +///////////////////////////// CoreAccountsService ///////////////////////////// + +type CoreAccountsService struct { + wasmclient.Service +} + +func NewCoreAccountsService(cl *wasmclient.ServiceClient, chainID string) (*CoreAccountsService, error) { + s := &CoreAccountsService{} + err := s.Service.Init(cl, chainID, 0x3c4b5e02, nil) + return s, err +} + +func (s *CoreAccountsService) Deposit() DepositFunc { + return DepositFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *CoreAccountsService) Harvest() HarvestFunc { + return HarvestFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *CoreAccountsService) Withdraw() WithdrawFunc { + return WithdrawFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *CoreAccountsService) Accounts() AccountsView { + return AccountsView{ClientView: s.AsClientView()} +} + +func (s *CoreAccountsService) Balance() BalanceView { + return BalanceView{ClientView: s.AsClientView()} +} + +func (s *CoreAccountsService) GetAccountNonce() GetAccountNonceView { + return GetAccountNonceView{ClientView: s.AsClientView()} +} + +func (s *CoreAccountsService) TotalAssets() TotalAssetsView { + return TotalAssetsView{ClientView: s.AsClientView()} +} diff --git a/packages/vm/wasmlib/go/wasmclient/coreblob/service.go b/packages/vm/wasmlib/go/wasmclient/coreblob/service.go new file mode 100644 index 0000000000..208046b63e --- /dev/null +++ b/packages/vm/wasmlib/go/wasmclient/coreblob/service.go @@ -0,0 +1,145 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// (Re-)generated by schema tool +// >>>> DO NOT CHANGE THIS FILE! <<<< +// Change the json schema instead + +package coreblobclient + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmclient" + +const ( + ArgBlobs = "this" + ArgField = "field" + ArgHash = "hash" + + ResBlobSizes = "this" + ResBytes = "bytes" + ResHash = "hash" +) + +///////////////////////////// storeBlob ///////////////////////////// + +type StoreBlobFunc struct { + wasmclient.ClientFunc + args wasmclient.Arguments +} + +func (f *StoreBlobFunc) Blobs(v []byte) { + f.args.Set(ArgBlobs, f.args.FromBytes(v)) +} + +func (f *StoreBlobFunc) Post() wasmclient.Request { + return f.ClientFunc.Post(0xddd4c281, &f.args) +} + +///////////////////////////// getBlobField ///////////////////////////// + +type GetBlobFieldView struct { + wasmclient.ClientView + args wasmclient.Arguments +} + +func (f *GetBlobFieldView) Field(v string) { + f.args.Set(ArgField, f.args.FromString(v)) +} + +func (f *GetBlobFieldView) Hash(v wasmclient.Hash) { + f.args.Set(ArgHash, f.args.FromHash(v)) +} + +func (f *GetBlobFieldView) Call() GetBlobFieldResults { + f.args.Mandatory(ArgField) + f.args.Mandatory(ArgHash) + f.ClientView.Call("getBlobField", &f.args) + return GetBlobFieldResults{res: f.Results()} +} + +type GetBlobFieldResults struct { + res wasmclient.Results +} + +func (r *GetBlobFieldResults) Bytes() []byte { + return r.res.ToBytes(r.res.Get(ResBytes)) +} + +///////////////////////////// getBlobInfo ///////////////////////////// + +type GetBlobInfoView struct { + wasmclient.ClientView + args wasmclient.Arguments +} + +func (f *GetBlobInfoView) Hash(v wasmclient.Hash) { + f.args.Set(ArgHash, f.args.FromHash(v)) +} + +func (f *GetBlobInfoView) Call() GetBlobInfoResults { + f.args.Mandatory(ArgHash) + f.ClientView.Call("getBlobInfo", &f.args) + return GetBlobInfoResults{res: f.Results()} +} + +type GetBlobInfoResults struct { + res wasmclient.Results +} + +func (r *GetBlobInfoResults) BlobSizes() map[string]int32 { + res := make(map[string]int32) + r.res.ForEach(func(key []byte, val []byte) { + res[r.res.ToString(key)] = r.res.ToInt32(val) + }) + return res +} + +///////////////////////////// listBlobs ///////////////////////////// + +type ListBlobsView struct { + wasmclient.ClientView +} + +func (f *ListBlobsView) Call() ListBlobsResults { + f.ClientView.Call("listBlobs", nil) + return ListBlobsResults{res: f.Results()} +} + +type ListBlobsResults struct { + res wasmclient.Results +} + +func (r *ListBlobsResults) BlobSizes() map[wasmclient.Hash]int32 { + res := make(map[wasmclient.Hash]int32) + r.res.ForEach(func(key []byte, val []byte) { + res[r.res.ToHash(key)] = r.res.ToInt32(val) + }) + return res +} + +///////////////////////////// CoreBlobService ///////////////////////////// + +type CoreBlobService struct { + wasmclient.Service +} + +func NewCoreBlobService(cl *wasmclient.ServiceClient, chainID string) (*CoreBlobService, error) { + s := &CoreBlobService{} + err := s.Service.Init(cl, chainID, 0xfd91bc63, nil) + return s, err +} + +func (s *CoreBlobService) StoreBlob() StoreBlobFunc { + return StoreBlobFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *CoreBlobService) GetBlobField() GetBlobFieldView { + return GetBlobFieldView{ClientView: s.AsClientView()} +} + +func (s *CoreBlobService) GetBlobInfo() GetBlobInfoView { + return GetBlobInfoView{ClientView: s.AsClientView()} +} + +func (s *CoreBlobService) ListBlobs() ListBlobsView { + return ListBlobsView{ClientView: s.AsClientView()} +} diff --git a/packages/vm/wasmlib/go/wasmclient/coreblocklog/service.go b/packages/vm/wasmlib/go/wasmclient/coreblocklog/service.go new file mode 100644 index 0000000000..ff8101b85f --- /dev/null +++ b/packages/vm/wasmlib/go/wasmclient/coreblocklog/service.go @@ -0,0 +1,346 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// (Re-)generated by schema tool +// >>>> DO NOT CHANGE THIS FILE! <<<< +// Change the json schema instead + +package coreblocklogclient + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmclient" + +const ( + ArgBlockIndex = "n" + ArgContractHname = "h" + ArgFromBlock = "f" + ArgRequestID = "u" + ArgToBlock = "t" + + ResBlockIndex = "n" + ResBlockInfo = "i" + ResEvent = "e" + ResGoverningAddress = "g" + ResRequestID = "u" + ResRequestIndex = "r" + ResRequestProcessed = "p" + ResRequestRecord = "d" + ResStateControllerAddress = "s" +) + +///////////////////////////// controlAddresses ///////////////////////////// + +type ControlAddressesView struct { + wasmclient.ClientView +} + +func (f *ControlAddressesView) Call() ControlAddressesResults { + f.ClientView.Call("controlAddresses", nil) + return ControlAddressesResults{res: f.Results()} +} + +type ControlAddressesResults struct { + res wasmclient.Results +} + +func (r *ControlAddressesResults) BlockIndex() int32 { + return r.res.ToInt32(r.res.Get(ResBlockIndex)) +} + +func (r *ControlAddressesResults) GoverningAddress() wasmclient.Address { + return r.res.ToAddress(r.res.Get(ResGoverningAddress)) +} + +func (r *ControlAddressesResults) StateControllerAddress() wasmclient.Address { + return r.res.ToAddress(r.res.Get(ResStateControllerAddress)) +} + +///////////////////////////// getBlockInfo ///////////////////////////// + +type GetBlockInfoView struct { + wasmclient.ClientView + args wasmclient.Arguments +} + +func (f *GetBlockInfoView) BlockIndex(v int32) { + f.args.Set(ArgBlockIndex, f.args.FromInt32(v)) +} + +func (f *GetBlockInfoView) Call() GetBlockInfoResults { + f.args.Mandatory(ArgBlockIndex) + f.ClientView.Call("getBlockInfo", &f.args) + return GetBlockInfoResults{res: f.Results()} +} + +type GetBlockInfoResults struct { + res wasmclient.Results +} + +func (r *GetBlockInfoResults) BlockInfo() []byte { + return r.res.ToBytes(r.res.Get(ResBlockInfo)) +} + +///////////////////////////// getEventsForBlock ///////////////////////////// + +type GetEventsForBlockView struct { + wasmclient.ClientView + args wasmclient.Arguments +} + +func (f *GetEventsForBlockView) BlockIndex(v int32) { + f.args.Set(ArgBlockIndex, f.args.FromInt32(v)) +} + +func (f *GetEventsForBlockView) Call() GetEventsForBlockResults { + f.args.Mandatory(ArgBlockIndex) + f.ClientView.Call("getEventsForBlock", &f.args) + return GetEventsForBlockResults{res: f.Results()} +} + +type GetEventsForBlockResults struct { + res wasmclient.Results +} + +func (r *GetEventsForBlockResults) Event() []byte { + return r.res.ToBytes(r.res.Get(ResEvent)) +} + +///////////////////////////// getEventsForContract ///////////////////////////// + +type GetEventsForContractView struct { + wasmclient.ClientView + args wasmclient.Arguments +} + +func (f *GetEventsForContractView) ContractHname(v wasmclient.Hname) { + f.args.Set(ArgContractHname, f.args.FromHname(v)) +} + +func (f *GetEventsForContractView) FromBlock(v int32) { + f.args.Set(ArgFromBlock, f.args.FromInt32(v)) +} + +func (f *GetEventsForContractView) ToBlock(v int32) { + f.args.Set(ArgToBlock, f.args.FromInt32(v)) +} + +func (f *GetEventsForContractView) Call() GetEventsForContractResults { + f.args.Mandatory(ArgContractHname) + f.ClientView.Call("getEventsForContract", &f.args) + return GetEventsForContractResults{res: f.Results()} +} + +type GetEventsForContractResults struct { + res wasmclient.Results +} + +func (r *GetEventsForContractResults) Event() []byte { + return r.res.ToBytes(r.res.Get(ResEvent)) +} + +///////////////////////////// getEventsForRequest ///////////////////////////// + +type GetEventsForRequestView struct { + wasmclient.ClientView + args wasmclient.Arguments +} + +func (f *GetEventsForRequestView) RequestID(v wasmclient.RequestID) { + f.args.Set(ArgRequestID, f.args.FromRequestID(v)) +} + +func (f *GetEventsForRequestView) Call() GetEventsForRequestResults { + f.args.Mandatory(ArgRequestID) + f.ClientView.Call("getEventsForRequest", &f.args) + return GetEventsForRequestResults{res: f.Results()} +} + +type GetEventsForRequestResults struct { + res wasmclient.Results +} + +func (r *GetEventsForRequestResults) Event() []byte { + return r.res.ToBytes(r.res.Get(ResEvent)) +} + +///////////////////////////// getLatestBlockInfo ///////////////////////////// + +type GetLatestBlockInfoView struct { + wasmclient.ClientView +} + +func (f *GetLatestBlockInfoView) Call() GetLatestBlockInfoResults { + f.ClientView.Call("getLatestBlockInfo", nil) + return GetLatestBlockInfoResults{res: f.Results()} +} + +type GetLatestBlockInfoResults struct { + res wasmclient.Results +} + +func (r *GetLatestBlockInfoResults) BlockIndex() int32 { + return r.res.ToInt32(r.res.Get(ResBlockIndex)) +} + +func (r *GetLatestBlockInfoResults) BlockInfo() []byte { + return r.res.ToBytes(r.res.Get(ResBlockInfo)) +} + +///////////////////////////// getRequestIDsForBlock ///////////////////////////// + +type GetRequestIDsForBlockView struct { + wasmclient.ClientView + args wasmclient.Arguments +} + +func (f *GetRequestIDsForBlockView) BlockIndex(v int32) { + f.args.Set(ArgBlockIndex, f.args.FromInt32(v)) +} + +func (f *GetRequestIDsForBlockView) Call() GetRequestIDsForBlockResults { + f.args.Mandatory(ArgBlockIndex) + f.ClientView.Call("getRequestIDsForBlock", &f.args) + return GetRequestIDsForBlockResults{res: f.Results()} +} + +type GetRequestIDsForBlockResults struct { + res wasmclient.Results +} + +func (r *GetRequestIDsForBlockResults) RequestID() wasmclient.RequestID { + return r.res.ToRequestID(r.res.Get(ResRequestID)) +} + +///////////////////////////// getRequestReceipt ///////////////////////////// + +type GetRequestReceiptView struct { + wasmclient.ClientView + args wasmclient.Arguments +} + +func (f *GetRequestReceiptView) RequestID(v wasmclient.RequestID) { + f.args.Set(ArgRequestID, f.args.FromRequestID(v)) +} + +func (f *GetRequestReceiptView) Call() GetRequestReceiptResults { + f.args.Mandatory(ArgRequestID) + f.ClientView.Call("getRequestReceipt", &f.args) + return GetRequestReceiptResults{res: f.Results()} +} + +type GetRequestReceiptResults struct { + res wasmclient.Results +} + +func (r *GetRequestReceiptResults) BlockIndex() int32 { + return r.res.ToInt32(r.res.Get(ResBlockIndex)) +} + +func (r *GetRequestReceiptResults) RequestIndex() int16 { + return r.res.ToInt16(r.res.Get(ResRequestIndex)) +} + +func (r *GetRequestReceiptResults) RequestRecord() []byte { + return r.res.ToBytes(r.res.Get(ResRequestRecord)) +} + +///////////////////////////// getRequestReceiptsForBlock ///////////////////////////// + +type GetRequestReceiptsForBlockView struct { + wasmclient.ClientView + args wasmclient.Arguments +} + +func (f *GetRequestReceiptsForBlockView) BlockIndex(v int32) { + f.args.Set(ArgBlockIndex, f.args.FromInt32(v)) +} + +func (f *GetRequestReceiptsForBlockView) Call() GetRequestReceiptsForBlockResults { + f.args.Mandatory(ArgBlockIndex) + f.ClientView.Call("getRequestReceiptsForBlock", &f.args) + return GetRequestReceiptsForBlockResults{res: f.Results()} +} + +type GetRequestReceiptsForBlockResults struct { + res wasmclient.Results +} + +func (r *GetRequestReceiptsForBlockResults) RequestRecord() []byte { + return r.res.ToBytes(r.res.Get(ResRequestRecord)) +} + +///////////////////////////// isRequestProcessed ///////////////////////////// + +type IsRequestProcessedView struct { + wasmclient.ClientView + args wasmclient.Arguments +} + +func (f *IsRequestProcessedView) RequestID(v wasmclient.RequestID) { + f.args.Set(ArgRequestID, f.args.FromRequestID(v)) +} + +func (f *IsRequestProcessedView) Call() IsRequestProcessedResults { + f.args.Mandatory(ArgRequestID) + f.ClientView.Call("isRequestProcessed", &f.args) + return IsRequestProcessedResults{res: f.Results()} +} + +type IsRequestProcessedResults struct { + res wasmclient.Results +} + +func (r *IsRequestProcessedResults) RequestProcessed() string { + return r.res.ToString(r.res.Get(ResRequestProcessed)) +} + +///////////////////////////// CoreBlockLogService ///////////////////////////// + +type CoreBlockLogService struct { + wasmclient.Service +} + +func NewCoreBlockLogService(cl *wasmclient.ServiceClient, chainID string) (*CoreBlockLogService, error) { + s := &CoreBlockLogService{} + err := s.Service.Init(cl, chainID, 0xf538ef2b, nil) + return s, err +} + +func (s *CoreBlockLogService) ControlAddresses() ControlAddressesView { + return ControlAddressesView{ClientView: s.AsClientView()} +} + +func (s *CoreBlockLogService) GetBlockInfo() GetBlockInfoView { + return GetBlockInfoView{ClientView: s.AsClientView()} +} + +func (s *CoreBlockLogService) GetEventsForBlock() GetEventsForBlockView { + return GetEventsForBlockView{ClientView: s.AsClientView()} +} + +func (s *CoreBlockLogService) GetEventsForContract() GetEventsForContractView { + return GetEventsForContractView{ClientView: s.AsClientView()} +} + +func (s *CoreBlockLogService) GetEventsForRequest() GetEventsForRequestView { + return GetEventsForRequestView{ClientView: s.AsClientView()} +} + +func (s *CoreBlockLogService) GetLatestBlockInfo() GetLatestBlockInfoView { + return GetLatestBlockInfoView{ClientView: s.AsClientView()} +} + +func (s *CoreBlockLogService) GetRequestIDsForBlock() GetRequestIDsForBlockView { + return GetRequestIDsForBlockView{ClientView: s.AsClientView()} +} + +func (s *CoreBlockLogService) GetRequestReceipt() GetRequestReceiptView { + return GetRequestReceiptView{ClientView: s.AsClientView()} +} + +func (s *CoreBlockLogService) GetRequestReceiptsForBlock() GetRequestReceiptsForBlockView { + return GetRequestReceiptsForBlockView{ClientView: s.AsClientView()} +} + +func (s *CoreBlockLogService) IsRequestProcessed() IsRequestProcessedView { + return IsRequestProcessedView{ClientView: s.AsClientView()} +} diff --git a/packages/vm/wasmlib/go/wasmclient/coregovernance/service.go b/packages/vm/wasmlib/go/wasmclient/coregovernance/service.go new file mode 100644 index 0000000000..a3f5add5f3 --- /dev/null +++ b/packages/vm/wasmlib/go/wasmclient/coregovernance/service.go @@ -0,0 +1,374 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// (Re-)generated by schema tool +// >>>> DO NOT CHANGE THIS FILE! <<<< +// Change the json schema instead + +package coregovernanceclient + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmclient" + +const ( + ArgChainOwner = "oi" + ArgFeeColor = "fc" + ArgHname = "hn" + ArgMaxBlobSize = "bs" + ArgMaxEventSize = "es" + ArgMaxEventsPerReq = "ne" + ArgOwnerFee = "of" + ArgStateControllerAddress = "S" + ArgValidatorFee = "vf" + + ResAllowedStateControllerAddresses = "a" + ResChainID = "c" + ResChainOwnerID = "o" + ResDefaultOwnerFee = "do" + ResDefaultValidatorFee = "dv" + ResDescription = "d" + ResFeeColor = "f" + ResMaxBlobSize = "mb" + ResMaxEventSize = "me" + ResMaxEventsPerReq = "mr" + ResOwnerFee = "of" + ResValidatorFee = "vf" +) + +///////////////////////////// addAllowedStateControllerAddress ///////////////////////////// + +type AddAllowedStateControllerAddressFunc struct { + wasmclient.ClientFunc + args wasmclient.Arguments +} + +func (f *AddAllowedStateControllerAddressFunc) ChainOwner(v wasmclient.AgentID) { + f.args.Set(ArgChainOwner, f.args.FromAgentID(v)) +} + +func (f *AddAllowedStateControllerAddressFunc) FeeColor(v wasmclient.Color) { + f.args.Set(ArgFeeColor, f.args.FromColor(v)) +} + +func (f *AddAllowedStateControllerAddressFunc) StateControllerAddress(v wasmclient.Address) { + f.args.Set(ArgStateControllerAddress, f.args.FromAddress(v)) +} + +func (f *AddAllowedStateControllerAddressFunc) Post() wasmclient.Request { + f.args.Mandatory(ArgChainOwner) + f.args.Mandatory(ArgStateControllerAddress) + return f.ClientFunc.Post(0x9469d567, &f.args) +} + +///////////////////////////// claimChainOwnership ///////////////////////////// + +type ClaimChainOwnershipFunc struct { + wasmclient.ClientFunc +} + +func (f *ClaimChainOwnershipFunc) Post() wasmclient.Request { + return f.ClientFunc.Post(0x03ff0fc0, nil) +} + +///////////////////////////// delegateChainOwnership ///////////////////////////// + +type DelegateChainOwnershipFunc struct { + wasmclient.ClientFunc + args wasmclient.Arguments +} + +func (f *DelegateChainOwnershipFunc) ChainOwner(v wasmclient.AgentID) { + f.args.Set(ArgChainOwner, f.args.FromAgentID(v)) +} + +func (f *DelegateChainOwnershipFunc) Post() wasmclient.Request { + f.args.Mandatory(ArgChainOwner) + return f.ClientFunc.Post(0x93ecb6ad, &f.args) +} + +///////////////////////////// removeAllowedStateControllerAddress ///////////////////////////// + +type RemoveAllowedStateControllerAddressFunc struct { + wasmclient.ClientFunc + args wasmclient.Arguments +} + +func (f *RemoveAllowedStateControllerAddressFunc) StateControllerAddress(v wasmclient.Address) { + f.args.Set(ArgStateControllerAddress, f.args.FromAddress(v)) +} + +func (f *RemoveAllowedStateControllerAddressFunc) Post() wasmclient.Request { + f.args.Mandatory(ArgStateControllerAddress) + return f.ClientFunc.Post(0x31f69447, &f.args) +} + +///////////////////////////// rotateStateController ///////////////////////////// + +type RotateStateControllerFunc struct { + wasmclient.ClientFunc + args wasmclient.Arguments +} + +func (f *RotateStateControllerFunc) StateControllerAddress(v wasmclient.Address) { + f.args.Set(ArgStateControllerAddress, f.args.FromAddress(v)) +} + +func (f *RotateStateControllerFunc) Post() wasmclient.Request { + f.args.Mandatory(ArgStateControllerAddress) + return f.ClientFunc.Post(0x244d1038, &f.args) +} + +///////////////////////////// setChainInfo ///////////////////////////// + +type SetChainInfoFunc struct { + wasmclient.ClientFunc + args wasmclient.Arguments +} + +func (f *SetChainInfoFunc) MaxBlobSize(v int32) { + f.args.Set(ArgMaxBlobSize, f.args.FromInt32(v)) +} + +func (f *SetChainInfoFunc) MaxEventSize(v int16) { + f.args.Set(ArgMaxEventSize, f.args.FromInt16(v)) +} + +func (f *SetChainInfoFunc) MaxEventsPerReq(v int16) { + f.args.Set(ArgMaxEventsPerReq, f.args.FromInt16(v)) +} + +func (f *SetChainInfoFunc) OwnerFee(v int64) { + f.args.Set(ArgOwnerFee, f.args.FromInt64(v)) +} + +func (f *SetChainInfoFunc) ValidatorFee(v int64) { + f.args.Set(ArgValidatorFee, f.args.FromInt64(v)) +} + +func (f *SetChainInfoFunc) Post() wasmclient.Request { + return f.ClientFunc.Post(0x702f5d2b, &f.args) +} + +///////////////////////////// setContractFee ///////////////////////////// + +type SetContractFeeFunc struct { + wasmclient.ClientFunc + args wasmclient.Arguments +} + +func (f *SetContractFeeFunc) Hname(v wasmclient.Hname) { + f.args.Set(ArgHname, f.args.FromHname(v)) +} + +func (f *SetContractFeeFunc) OwnerFee(v int64) { + f.args.Set(ArgOwnerFee, f.args.FromInt64(v)) +} + +func (f *SetContractFeeFunc) ValidatorFee(v int64) { + f.args.Set(ArgValidatorFee, f.args.FromInt64(v)) +} + +func (f *SetContractFeeFunc) Post() wasmclient.Request { + f.args.Mandatory(ArgHname) + return f.ClientFunc.Post(0x8421a42b, &f.args) +} + +///////////////////////////// setDefaultFee ///////////////////////////// + +type SetDefaultFeeFunc struct { + wasmclient.ClientFunc + args wasmclient.Arguments +} + +func (f *SetDefaultFeeFunc) OwnerFee(v int64) { + f.args.Set(ArgOwnerFee, f.args.FromInt64(v)) +} + +func (f *SetDefaultFeeFunc) ValidatorFee(v int64) { + f.args.Set(ArgValidatorFee, f.args.FromInt64(v)) +} + +func (f *SetDefaultFeeFunc) Post() wasmclient.Request { + return f.ClientFunc.Post(0x3310ecd0, &f.args) +} + +///////////////////////////// getAllowedStateControllerAddresses ///////////////////////////// + +type GetAllowedStateControllerAddressesView struct { + wasmclient.ClientView +} + +func (f *GetAllowedStateControllerAddressesView) Call() GetAllowedStateControllerAddressesResults { + f.ClientView.Call("getAllowedStateControllerAddresses", nil) + return GetAllowedStateControllerAddressesResults{res: f.Results()} +} + +type GetAllowedStateControllerAddressesResults struct { + res wasmclient.Results +} + +func (r *GetAllowedStateControllerAddressesResults) AllowedStateControllerAddresses() []byte { + return r.res.ToBytes(r.res.Get(ResAllowedStateControllerAddresses)) +} + +///////////////////////////// getChainInfo ///////////////////////////// + +type GetChainInfoView struct { + wasmclient.ClientView +} + +func (f *GetChainInfoView) Call() GetChainInfoResults { + f.ClientView.Call("getChainInfo", nil) + return GetChainInfoResults{res: f.Results()} +} + +type GetChainInfoResults struct { + res wasmclient.Results +} + +func (r *GetChainInfoResults) ChainID() wasmclient.ChainID { + return r.res.ToChainID(r.res.Get(ResChainID)) +} + +func (r *GetChainInfoResults) ChainOwnerID() wasmclient.AgentID { + return r.res.ToAgentID(r.res.Get(ResChainOwnerID)) +} + +func (r *GetChainInfoResults) DefaultOwnerFee() int64 { + return r.res.ToInt64(r.res.Get(ResDefaultOwnerFee)) +} + +func (r *GetChainInfoResults) DefaultValidatorFee() int64 { + return r.res.ToInt64(r.res.Get(ResDefaultValidatorFee)) +} + +func (r *GetChainInfoResults) Description() string { + return r.res.ToString(r.res.Get(ResDescription)) +} + +func (r *GetChainInfoResults) FeeColor() wasmclient.Color { + return r.res.ToColor(r.res.Get(ResFeeColor)) +} + +func (r *GetChainInfoResults) MaxBlobSize() int32 { + return r.res.ToInt32(r.res.Get(ResMaxBlobSize)) +} + +func (r *GetChainInfoResults) MaxEventSize() int16 { + return r.res.ToInt16(r.res.Get(ResMaxEventSize)) +} + +func (r *GetChainInfoResults) MaxEventsPerReq() int16 { + return r.res.ToInt16(r.res.Get(ResMaxEventsPerReq)) +} + +///////////////////////////// getFeeInfo ///////////////////////////// + +type GetFeeInfoView struct { + wasmclient.ClientView + args wasmclient.Arguments +} + +func (f *GetFeeInfoView) Hname(v wasmclient.Hname) { + f.args.Set(ArgHname, f.args.FromHname(v)) +} + +func (f *GetFeeInfoView) Call() GetFeeInfoResults { + f.args.Mandatory(ArgHname) + f.ClientView.Call("getFeeInfo", &f.args) + return GetFeeInfoResults{res: f.Results()} +} + +type GetFeeInfoResults struct { + res wasmclient.Results +} + +func (r *GetFeeInfoResults) FeeColor() wasmclient.Color { + return r.res.ToColor(r.res.Get(ResFeeColor)) +} + +func (r *GetFeeInfoResults) OwnerFee() int64 { + return r.res.ToInt64(r.res.Get(ResOwnerFee)) +} + +func (r *GetFeeInfoResults) ValidatorFee() int64 { + return r.res.ToInt64(r.res.Get(ResValidatorFee)) +} + +///////////////////////////// getMaxBlobSize ///////////////////////////// + +type GetMaxBlobSizeView struct { + wasmclient.ClientView +} + +func (f *GetMaxBlobSizeView) Call() GetMaxBlobSizeResults { + f.ClientView.Call("getMaxBlobSize", nil) + return GetMaxBlobSizeResults{res: f.Results()} +} + +type GetMaxBlobSizeResults struct { + res wasmclient.Results +} + +func (r *GetMaxBlobSizeResults) MaxBlobSize() int32 { + return r.res.ToInt32(r.res.Get(ResMaxBlobSize)) +} + +///////////////////////////// CoreGovernanceService ///////////////////////////// + +type CoreGovernanceService struct { + wasmclient.Service +} + +func NewCoreGovernanceService(cl *wasmclient.ServiceClient, chainID string) (*CoreGovernanceService, error) { + s := &CoreGovernanceService{} + err := s.Service.Init(cl, chainID, 0x17cf909f, nil) + return s, err +} + +func (s *CoreGovernanceService) AddAllowedStateControllerAddress() AddAllowedStateControllerAddressFunc { + return AddAllowedStateControllerAddressFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *CoreGovernanceService) ClaimChainOwnership() ClaimChainOwnershipFunc { + return ClaimChainOwnershipFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *CoreGovernanceService) DelegateChainOwnership() DelegateChainOwnershipFunc { + return DelegateChainOwnershipFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *CoreGovernanceService) RemoveAllowedStateControllerAddress() RemoveAllowedStateControllerAddressFunc { + return RemoveAllowedStateControllerAddressFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *CoreGovernanceService) RotateStateController() RotateStateControllerFunc { + return RotateStateControllerFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *CoreGovernanceService) SetChainInfo() SetChainInfoFunc { + return SetChainInfoFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *CoreGovernanceService) SetContractFee() SetContractFeeFunc { + return SetContractFeeFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *CoreGovernanceService) SetDefaultFee() SetDefaultFeeFunc { + return SetDefaultFeeFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *CoreGovernanceService) GetAllowedStateControllerAddresses() GetAllowedStateControllerAddressesView { + return GetAllowedStateControllerAddressesView{ClientView: s.AsClientView()} +} + +func (s *CoreGovernanceService) GetChainInfo() GetChainInfoView { + return GetChainInfoView{ClientView: s.AsClientView()} +} + +func (s *CoreGovernanceService) GetFeeInfo() GetFeeInfoView { + return GetFeeInfoView{ClientView: s.AsClientView()} +} + +func (s *CoreGovernanceService) GetMaxBlobSize() GetMaxBlobSizeView { + return GetMaxBlobSizeView{ClientView: s.AsClientView()} +} diff --git a/packages/vm/wasmlib/go/wasmclient/coreroot/service.go b/packages/vm/wasmlib/go/wasmclient/coreroot/service.go new file mode 100644 index 0000000000..735d0e0968 --- /dev/null +++ b/packages/vm/wasmlib/go/wasmclient/coreroot/service.go @@ -0,0 +1,163 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// (Re-)generated by schema tool +// >>>> DO NOT CHANGE THIS FILE! <<<< +// Change the json schema instead + +package corerootclient + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmclient" + +const ( + ArgDeployer = "dp" + ArgDescription = "ds" + ArgHname = "hn" + ArgName = "nm" + ArgProgramHash = "ph" + + ResContractFound = "cf" + ResContractRecData = "dt" + ResContractRegistry = "r" +) + +///////////////////////////// deployContract ///////////////////////////// + +type DeployContractFunc struct { + wasmclient.ClientFunc + args wasmclient.Arguments +} + +func (f *DeployContractFunc) Description(v string) { + f.args.Set(ArgDescription, f.args.FromString(v)) +} + +func (f *DeployContractFunc) Name(v string) { + f.args.Set(ArgName, f.args.FromString(v)) +} + +func (f *DeployContractFunc) ProgramHash(v wasmclient.Hash) { + f.args.Set(ArgProgramHash, f.args.FromHash(v)) +} + +func (f *DeployContractFunc) Post() wasmclient.Request { + f.args.Mandatory(ArgName) + f.args.Mandatory(ArgProgramHash) + return f.ClientFunc.Post(0x28232c27, &f.args) +} + +///////////////////////////// grantDeployPermission ///////////////////////////// + +type GrantDeployPermissionFunc struct { + wasmclient.ClientFunc + args wasmclient.Arguments +} + +func (f *GrantDeployPermissionFunc) Deployer(v wasmclient.AgentID) { + f.args.Set(ArgDeployer, f.args.FromAgentID(v)) +} + +func (f *GrantDeployPermissionFunc) Post() wasmclient.Request { + f.args.Mandatory(ArgDeployer) + return f.ClientFunc.Post(0xf440263a, &f.args) +} + +///////////////////////////// revokeDeployPermission ///////////////////////////// + +type RevokeDeployPermissionFunc struct { + wasmclient.ClientFunc + args wasmclient.Arguments +} + +func (f *RevokeDeployPermissionFunc) Deployer(v wasmclient.AgentID) { + f.args.Set(ArgDeployer, f.args.FromAgentID(v)) +} + +func (f *RevokeDeployPermissionFunc) Post() wasmclient.Request { + f.args.Mandatory(ArgDeployer) + return f.ClientFunc.Post(0x850744f1, &f.args) +} + +///////////////////////////// findContract ///////////////////////////// + +type FindContractView struct { + wasmclient.ClientView + args wasmclient.Arguments +} + +func (f *FindContractView) Hname(v wasmclient.Hname) { + f.args.Set(ArgHname, f.args.FromHname(v)) +} + +func (f *FindContractView) Call() FindContractResults { + f.args.Mandatory(ArgHname) + f.ClientView.Call("findContract", &f.args) + return FindContractResults{res: f.Results()} +} + +type FindContractResults struct { + res wasmclient.Results +} + +func (r *FindContractResults) ContractFound() []byte { + return r.res.ToBytes(r.res.Get(ResContractFound)) +} + +func (r *FindContractResults) ContractRecData() []byte { + return r.res.ToBytes(r.res.Get(ResContractRecData)) +} + +///////////////////////////// getContractRecords ///////////////////////////// + +type GetContractRecordsView struct { + wasmclient.ClientView +} + +func (f *GetContractRecordsView) Call() GetContractRecordsResults { + f.ClientView.Call("getContractRecords", nil) + return GetContractRecordsResults{res: f.Results()} +} + +type GetContractRecordsResults struct { + res wasmclient.Results +} + +func (r *GetContractRecordsResults) ContractRegistry() map[wasmclient.Hname][]byte { + res := make(map[wasmclient.Hname][]byte) + r.res.ForEach(func(key []byte, val []byte) { + res[r.res.ToHname(key)] = r.res.ToBytes(val) + }) + return res +} + +///////////////////////////// CoreRootService ///////////////////////////// + +type CoreRootService struct { + wasmclient.Service +} + +func NewCoreRootService(cl *wasmclient.ServiceClient, chainID string) (*CoreRootService, error) { + s := &CoreRootService{} + err := s.Service.Init(cl, chainID, 0xcebf5908, nil) + return s, err +} + +func (s *CoreRootService) DeployContract() DeployContractFunc { + return DeployContractFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *CoreRootService) GrantDeployPermission() GrantDeployPermissionFunc { + return GrantDeployPermissionFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *CoreRootService) RevokeDeployPermission() RevokeDeployPermissionFunc { + return RevokeDeployPermissionFunc{ClientFunc: s.AsClientFunc()} +} + +func (s *CoreRootService) FindContract() FindContractView { + return FindContractView{ClientView: s.AsClientView()} +} + +func (s *CoreRootService) GetContractRecords() GetContractRecordsView { + return GetContractRecordsView{ClientView: s.AsClientView()} +} diff --git a/packages/vm/wasmlib/go/wasmclient/decoder.go b/packages/vm/wasmlib/go/wasmclient/decoder.go new file mode 100644 index 0000000000..11d17e749f --- /dev/null +++ b/packages/vm/wasmlib/go/wasmclient/decoder.go @@ -0,0 +1,97 @@ +package wasmclient + +import "encoding/binary" + +type Decoder struct{} + +func checkDefault(bytes []byte, typeID int32) []byte { + size := TypeSizes[typeID] + if bytes == nil { + // return default all-zero bytes value + return make([]byte, size) + } + if size != 0 && len(bytes) != int(size) { + panic("invalid type size") + } + return bytes +} + +func toBase58(bytes []byte, typeID int32) string { + return Base58Encode(checkDefault(bytes, typeID)) +} + +func (c Decoder) ToAddress(bytes []byte) Address { + return Address(toBase58(bytes, TYPE_ADDRESS)) +} + +func (c Decoder) ToAgentID(bytes []byte) AgentID { + return AgentID(toBase58(bytes, TYPE_AGENT_ID)) +} + +func (c Decoder) ToBool(bytes []byte) bool { + return checkDefault(bytes, TYPE_BOOL)[0] != 0 +} + +func (c Decoder) ToBytes(bytes []byte) []byte { + return checkDefault(bytes, TYPE_BYTES) +} + +func (c Decoder) ToChainID(bytes []byte) ChainID { + return ChainID(toBase58(bytes, TYPE_CHAIN_ID)) +} + +func (c Decoder) ToColor(bytes []byte) Color { + color := toBase58(bytes, TYPE_COLOR) + if color == COLOR_IOTA_BASE58 { + color = COLOR_IOTA + } + return Color(color) +} + +func (c Decoder) ToHash(bytes []byte) Hash { + return Hash(toBase58(bytes, TYPE_HASH)) +} + +func (c Decoder) ToHname(bytes []byte) Hname { + return Hname(binary.LittleEndian.Uint32(checkDefault(bytes, TYPE_HNAME))) +} + +func (c Decoder) ToInt8(bytes []byte) int8 { + return int8(c.ToUint8(bytes)) +} + +func (c Decoder) ToInt16(bytes []byte) int16 { + return int16(c.ToUint16(bytes)) +} + +func (c Decoder) ToInt32(bytes []byte) int32 { + return int32(c.ToUint32(bytes)) +} + +func (c Decoder) ToInt64(bytes []byte) int64 { + return int64(c.ToUint64(bytes)) +} + +func (c Decoder) ToRequestID(bytes []byte) RequestID { + return RequestID(toBase58(bytes, TYPE_REQUEST_ID)) +} + +func (c Decoder) ToString(bytes []byte) string { + return string(checkDefault(bytes, TYPE_STRING)) +} + +func (c Decoder) ToUint8(bytes []byte) uint8 { + return checkDefault(bytes, TYPE_INT8)[0] +} + +func (c Decoder) ToUint16(bytes []byte) uint16 { + return binary.LittleEndian.Uint16(checkDefault(bytes, TYPE_INT16)) +} + +func (c Decoder) ToUint32(bytes []byte) uint32 { + return binary.LittleEndian.Uint32(checkDefault(bytes, TYPE_INT32)) +} + +func (c Decoder) ToUint64(bytes []byte) uint64 { + return binary.LittleEndian.Uint64(checkDefault(bytes, TYPE_INT64)) +} diff --git a/packages/vm/wasmlib/go/wasmclient/encoder.go b/packages/vm/wasmlib/go/wasmclient/encoder.go new file mode 100644 index 0000000000..3f4ce6f227 --- /dev/null +++ b/packages/vm/wasmlib/go/wasmclient/encoder.go @@ -0,0 +1,102 @@ +package wasmclient + +import "encoding/binary" + +type Encoder struct{} + +func fromBase58(value string, typeID int32) []byte { + bytes := Base58Decode(value) + if len(bytes) != int(TypeSizes[typeID]) { + panic("invalid byte size") + } + return bytes +} + +func (c Encoder) FromAddress(value Address) []byte { + return fromBase58(string(value), TYPE_ADDRESS) +} + +func (c Encoder) FromAgentID(value AgentID) []byte { + return fromBase58(string(value), TYPE_AGENT_ID) +} + +func (c Encoder) FromBool(value bool) []byte { + bytes := []byte{0} + if value { + bytes[0] = 1 + } + return bytes +} + +func (c Encoder) FromBytes(value []byte) []byte { + if value == nil { + panic("missing mandatory byte array") + } + return value +} + +func (c Encoder) FromChainID(value ChainID) []byte { + return fromBase58(string(value), TYPE_CHAIN_ID) +} + +func (c Encoder) FromColor(value Color) []byte { + color := string(value) + if color == COLOR_IOTA { + color = COLOR_IOTA_BASE58 + } + return fromBase58(color, TYPE_COLOR) +} + +func (c Encoder) FromHash(value Hash) []byte { + return fromBase58(string(value), TYPE_HASH) +} + +func (c Encoder) FromHname(value Hname) []byte { + return c.FromUint32(uint32(value)) +} + +func (c Encoder) FromInt8(value int8) []byte { + return c.FromUint8(uint8(value)) +} + +func (c Encoder) FromInt16(value int16) []byte { + return c.FromUint16(uint16(value)) +} + +func (c Encoder) FromInt32(value int32) []byte { + return c.FromUint32(uint32(value)) +} + +func (c Encoder) FromInt64(value int64) []byte { + return c.FromUint64(uint64(value)) +} + +func (c Encoder) FromRequestID(value RequestID) []byte { + return fromBase58(string(value), TYPE_REQUEST_ID) +} + +func (c Encoder) FromString(value string) []byte { + return []byte(value) +} + +func (c Encoder) FromUint8(value uint8) []byte { + return []byte{value} +} + +func (c Encoder) FromUint16(value uint16) []byte { + bytes := make([]byte, 2) + binary.LittleEndian.PutUint16(bytes, value) + return bytes +} + +func (c Encoder) FromUint32(value uint32) []byte { + bytes := make([]byte, 4) + binary.LittleEndian.PutUint32(bytes, value) + return bytes +} + +func (c Encoder) FromUint64(value uint64) []byte { + bytes := make([]byte, 8) + binary.LittleEndian.PutUint64(bytes, value) + return bytes +} diff --git a/packages/vm/wasmlib/go/wasmclient/event.go b/packages/vm/wasmlib/go/wasmclient/event.go new file mode 100644 index 0000000000..d822989411 --- /dev/null +++ b/packages/vm/wasmlib/go/wasmclient/event.go @@ -0,0 +1,112 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package wasmclient + +import ( + "strconv" +) + +type Event struct { + message []string + Timestamp uint32 +} + +func (e *Event) Init(message []string) { + e.message = message + e.Timestamp = e.NextUint32() +} + +func (e *Event) next() string { + next := e.message[0] + e.message = e.message[1:] + return next +} + +func (e *Event) NextAddress() Address { + return Address(e.next()) +} + +func (e *Event) NextAgentID() AgentID { + return AgentID(e.next()) +} + +func (e *Event) NextBytes() []byte { + return Base58Decode(e.next()) +} + +func (e *Event) NextBool() bool { + return e.next() != "0" +} + +func (e *Event) NextChainID() ChainID { + return ChainID(e.next()) +} + +func (e *Event) NextColor() Color { + return Color(e.next()) +} + +func (e *Event) NextHash() Hash { + return Hash(e.next()) +} + +func (e *Event) NextHname() Hname { + return Hname(e.nextUint(32)) +} + +func (e *Event) nextInt(bitSize int) int64 { + val, err := strconv.ParseInt(e.next(), 10, bitSize) + if err != nil { + panic("int parse error") + } + return val +} + +func (e *Event) NextInt8() int8 { + return int8(e.nextInt(8)) +} + +func (e *Event) NextInt16() int16 { + return int16(e.nextInt(16)) +} + +func (e *Event) NextInt32() int32 { + return int32(e.nextInt(32)) +} + +func (e *Event) NextInt64() int64 { + return e.nextInt(64) +} + +func (e *Event) NextRequestID() RequestID { + return RequestID(e.next()) +} + +func (e *Event) NextString() string { + return e.next() +} + +func (e *Event) nextUint(bitSize int) uint64 { + val, err := strconv.ParseUint(e.next(), 10, bitSize) + if err != nil { + panic("uint parse error") + } + return val +} + +func (e *Event) NextUint8() uint8 { + return uint8(e.nextUint(8)) +} + +func (e *Event) NextUint16() uint16 { + return uint16(e.nextUint(16)) +} + +func (e *Event) NextUint32() uint32 { + return uint32(e.nextUint(32)) +} + +func (e *Event) NextUint64() uint64 { + return e.nextUint(64) +} diff --git a/packages/vm/wasmlib/go/wasmclient/request.go b/packages/vm/wasmlib/go/wasmclient/request.go new file mode 100644 index 0000000000..fdbeb5349a --- /dev/null +++ b/packages/vm/wasmlib/go/wasmclient/request.go @@ -0,0 +1,17 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package wasmclient + +import ( + "github.com/iotaledger/wasp/packages/iscp" +) + +type Request struct { + err error + id *iscp.RequestID +} + +func (r Request) Error() error { + return r.err +} diff --git a/packages/vm/wasmlib/go/wasmclient/results.go b/packages/vm/wasmlib/go/wasmclient/results.go new file mode 100644 index 0000000000..1af5ff4a2f --- /dev/null +++ b/packages/vm/wasmlib/go/wasmclient/results.go @@ -0,0 +1,24 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package wasmclient + +// The Results struct contains the results from a smart contract function call +type Results struct { + Decoder + res ResMap +} + +func (r Results) Exists(key string) bool { + return r.res.Get(key) != nil +} + +func (r Results) ForEach(keyValue func(key []byte, val []byte)) { + for key, val := range r.res { + keyValue([]byte(key), val) + } +} + +func (r Results) Get(key string) []byte { + return r.res.Get(key) +} diff --git a/packages/vm/wasmlib/go/wasmclient/seed.go b/packages/vm/wasmlib/go/wasmclient/seed.go new file mode 100644 index 0000000000..6c5cc8a7c4 --- /dev/null +++ b/packages/vm/wasmlib/go/wasmclient/seed.go @@ -0,0 +1,48 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package wasmclient + +import ( + "github.com/iotaledger/goshimmer/client/wallet/packages/seed" + "github.com/iotaledger/hive.go/crypto/ed25519" + "github.com/iotaledger/wasp/packages/iscp" + "github.com/mr-tron/base58" +) + +func ChainIsValid(chainID string) bool { + bytes, err := base58.Decode(chainID) + return err == nil && len(bytes) == 33 +} + +func SeedIsValid(mySeed string) bool { + seedBytes, err := base58.Decode(mySeed) + return err == nil && len(seedBytes) == 32 +} + +func SeedToAddress(mySeed string, index uint64) Address { + seedBytes, err := base58.Decode(mySeed) + if err != nil { + panic(err) + } + address := seed.NewSeed(seedBytes).Address(index) + return Address(base58.Encode(address.Address().Bytes())) +} + +func SeedToAgentID(mySeed string, index uint64) AgentID { + seedBytes, err := base58.Decode(mySeed) + if err != nil { + panic(err) + } + address := seed.NewSeed(seedBytes).Address(index) + agentID := iscp.NewAgentID(address.Address(), 0) + return AgentID(base58.Encode(agentID.Bytes())) +} + +func SeedToKeyPair(mySeed string, index uint64) *ed25519.KeyPair { + seedBytes, err := base58.Decode(mySeed) + if err != nil { + panic(err) + } + return seed.NewSeed(seedBytes).KeyPair(index) +} diff --git a/packages/vm/wasmlib/go/wasmclient/service.go b/packages/vm/wasmlib/go/wasmclient/service.go new file mode 100644 index 0000000000..fbd0a6778b --- /dev/null +++ b/packages/vm/wasmlib/go/wasmclient/service.go @@ -0,0 +1,170 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package wasmclient + +import ( + "fmt" + "strings" + "time" + + "github.com/iotaledger/hive.go/crypto/ed25519" + "github.com/iotaledger/wasp/client" + "github.com/iotaledger/wasp/packages/iscp" + "github.com/iotaledger/wasp/packages/iscp/colored" + "github.com/iotaledger/wasp/packages/iscp/request" + "github.com/iotaledger/wasp/packages/iscp/requestargs" + "github.com/iotaledger/wasp/packages/kv" + "github.com/iotaledger/wasp/packages/kv/dict" + "github.com/iotaledger/wasp/packages/subscribe" + "github.com/mr-tron/base58" +) + +type ArgMap dict.Dict + +func (m ArgMap) Get(key string) []byte { + return m[kv.Key(key)] +} + +func (m ArgMap) Set(key string, value []byte) { + m[kv.Key(key)] = value +} + +type ResMap dict.Dict + +func (m ResMap) Get(key string) []byte { + return m[kv.Key(key)] +} + +type Service struct { + chainID *iscp.ChainID + keyPair *ed25519.KeyPair + scHname iscp.Hname + waspClient *client.WaspClient +} + +func (s *Service) Init(svcClient *ServiceClient, chainID string, scHname uint32, eventHandlers map[string]func([]string)) (err error) { + s.waspClient = svcClient.waspClient + s.scHname = iscp.Hname(scHname) + s.chainID, err = iscp.ChainIDFromString(chainID) + if err != nil { + return err + } + if len(eventHandlers) != 0 { + // TODO allow user to specify event handlers for core contracts? + return s.startEventHandlers(svcClient.eventPort, eventHandlers) + } + return nil +} + +func (s *Service) AsClientFunc() ClientFunc { + return ClientFunc{svc: s} +} + +func (s *Service) AsClientView() ClientView { + return ClientView{svc: s} +} + +func (s *Service) CallView(viewName string, args ArgMap) (ResMap, error) { + res, err := s.waspClient.CallView(s.chainID, s.scHname, viewName, dict.Dict(args)) + if err != nil { + return nil, err + } + return ResMap(res), nil +} + +func (s *Service) PostRequest(hFuncName uint32, args ArgMap, transfer *Transfer, keyPair *ed25519.KeyPair, onLedger bool) Request { + bal, err := makeBalances(transfer) + if err != nil { + return Request{err: err} + } + reqArgs := requestargs.New() + if args != nil { + reqArgs.AddEncodeSimpleMany(dict.Dict(args)) + } + + if onLedger { + return s.postRequestOnLedger(hFuncName, reqArgs, bal, keyPair) + } + + req := request.NewOffLedger(s.chainID, s.scHname, iscp.Hname(hFuncName), reqArgs) + req.WithTransfer(bal) + req.Sign(keyPair) + err = s.waspClient.PostOffLedgerRequest(s.chainID, req) + if err != nil { + return Request{err: err} + } + id := req.ID() + return Request{id: &id} +} + +func (s *Service) postRequestOnLedger(hFuncName uint32, args requestargs.RequestArgs, bal colored.Balances, pair *ed25519.KeyPair) Request { + // TODO implement + return Request{} +} + +// overrides default contract name +func (s *Service) ServiceContractName(contractName string) { + s.scHname = iscp.Hn(contractName) +} + +func (s *Service) SignRequests(keyPair *ed25519.KeyPair) { + s.keyPair = keyPair +} + +func (s *Service) WaitRequest(req Request) error { + return s.waspClient.WaitUntilRequestProcessed(s.chainID, *req.id, 1*time.Minute) +} + +func (s *Service) startEventHandlers(eventPort string, handlers map[string]func([]string)) error { + chMsg := make(chan []string, 20) + chDone := make(chan bool) + err := subscribe.Subscribe(eventPort, chMsg, chDone, true, "") + if err != nil { + return err + } + go func() { + for { + for msgSplit := range chMsg { + event := strings.Join(msgSplit, " ") + fmt.Printf("%s\n", event) + if msgSplit[0] == "vmmsg" { + msg := strings.Split(msgSplit[3], "|") + handler, ok := handlers[msg[0]] + if ok { + handler(msg[1:]) + } + } + } + } + }() + return nil +} + +///////////////////////////////////////////////////////////////// + +func Base58Decode(s string) []byte { + res, err := base58.Decode(s) + if err != nil { + panic("invalid base58 encoding") + } + return res +} + +func Base58Encode(b []byte) string { + return base58.Encode(b) +} + +func makeBalances(transfer *Transfer) (colored.Balances, error) { + cb := colored.NewBalances() + if transfer != nil { + for color, amount := range transfer.xfer { + c, err := colored.ColorFromBase58EncodedString(color) + if err != nil { + return nil, err + } + cb.Set(c, amount) + } + } + return cb, nil +} diff --git a/packages/vm/wasmlib/go/wasmclient/serviceclient.go b/packages/vm/wasmlib/go/wasmclient/serviceclient.go new file mode 100644 index 0000000000..72c817fb68 --- /dev/null +++ b/packages/vm/wasmlib/go/wasmclient/serviceclient.go @@ -0,0 +1,19 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package wasmclient + +import "github.com/iotaledger/wasp/client" + +type ServiceClient struct { + waspClient *client.WaspClient + eventPort string +} + +func NewServiceClient(waspAPI, eventPort string) *ServiceClient { + return &ServiceClient{waspClient: client.NewWaspClient(waspAPI), eventPort: eventPort} +} + +func DefaultServiceClient() *ServiceClient { + return NewServiceClient("127.0.0.1:9090", "127.0.0.1:5550") +} diff --git a/packages/vm/wasmlib/go/wasmclient/transfer.go b/packages/vm/wasmlib/go/wasmclient/transfer.go new file mode 100644 index 0000000000..45541ddda2 --- /dev/null +++ b/packages/vm/wasmlib/go/wasmclient/transfer.go @@ -0,0 +1,31 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package wasmclient + +// The color string can be a base58-encoded 32-byte color, or "IOTA" + +type Transfer struct { + xfer map[string]uint64 +} + +func NewTransfer() *Transfer { + return &Transfer{xfer: make(map[string]uint64)} +} + +func TransferIotas(amount uint64) *Transfer { + return TransferTokens("IOTA", amount) +} + +func TransferTokens(color string, amount uint64) *Transfer { + transfer := NewTransfer() + transfer.Set(color, amount) + return transfer +} + +func (t *Transfer) Set(color string, amount uint64) { + if color == COLOR_IOTA { + color = COLOR_IOTA_BASE58 + } + t.xfer[color] = amount +} diff --git a/packages/vm/wasmlib/go/wasmclient/types.go b/packages/vm/wasmlib/go/wasmclient/types.go new file mode 100644 index 0000000000..d71ea560ea --- /dev/null +++ b/packages/vm/wasmlib/go/wasmclient/types.go @@ -0,0 +1,38 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package wasmclient + +//nolint:revive +const ( + TYPE_ADDRESS int32 = 1 + TYPE_AGENT_ID int32 = 2 + TYPE_BOOL int32 = 3 + TYPE_BYTES int32 = 4 + TYPE_CHAIN_ID int32 = 5 + TYPE_COLOR int32 = 6 + TYPE_HASH int32 = 7 + TYPE_HNAME int32 = 8 + TYPE_INT8 int32 = 9 + TYPE_INT16 int32 = 10 + TYPE_INT32 int32 = 11 + TYPE_INT64 int32 = 12 + TYPE_MAP int32 = 13 + TYPE_REQUEST_ID int32 = 14 + TYPE_STRING int32 = 15 + + COLOR_IOTA = "IOTA" + COLOR_IOTA_BASE58 = "11111111111111111111111111111111" +) + +type ( + Address string + AgentID string + ChainID string + Color string + Hash string + Hname uint32 + RequestID string +) + +var TypeSizes = [...]uint8{0, 33, 37, 1, 0, 33, 32, 32, 4, 1, 2, 4, 8, 0, 34, 0} diff --git a/packages/vm/wasmlib/go/wasmlib/context.go b/packages/vm/wasmlib/go/wasmlib/context.go index 01a851af57..e3fd8571ad 100644 --- a/packages/vm/wasmlib/go/wasmlib/context.go +++ b/packages/vm/wasmlib/go/wasmlib/context.go @@ -316,6 +316,9 @@ func (ctx ScFuncContext) Post(chainID ScChainID, hContract, hFunction ScHname, p // generates a random value from 0 to max (exclusive max) using a deterministic RNG func (ctx ScFuncContext) Random(max int64) int64 { + if max == 0 { + ctx.Panic("random: max parameter should be non-zero") + } state := ScMutableMap{objID: OBJ_ID_STATE} rnd := state.GetBytes(KeyRandom) seed := rnd.Value() diff --git a/packages/vm/wasmlib/src/context.rs b/packages/vm/wasmlib/src/context.rs index 9077472418..eadcb87483 100644 --- a/packages/vm/wasmlib/src/context.rs +++ b/packages/vm/wasmlib/src/context.rs @@ -345,6 +345,9 @@ impl ScFuncContext { // generates a random value from 0 to max (exclusive max) using a deterministic RNG pub fn random(&self, max: i64) -> i64 { + if max == 0 { + self.panic("random: max parameter should be non-zero"); + } let state = ScMutableMap { obj_id: OBJ_ID_STATE }; let rnd = state.get_bytes(&KEY_RANDOM); let mut seed = rnd.value(); diff --git a/packages/vm/wasmlib/src/coreaccounts/results.rs b/packages/vm/wasmlib/src/coreaccounts/results.rs index 918522561e..463868574a 100644 --- a/packages/vm/wasmlib/src/coreaccounts/results.rs +++ b/packages/vm/wasmlib/src/coreaccounts/results.rs @@ -12,6 +12,7 @@ use crate::*; use crate::coreaccounts::*; use crate::host::*; +#[derive(Clone, Copy)] pub struct MapAgentIDToImmutableBytes { pub(crate) obj_id: i32, } @@ -33,6 +34,7 @@ impl ImmutableAccountsResults { } } +#[derive(Clone, Copy)] pub struct MapAgentIDToMutableBytes { pub(crate) obj_id: i32, } @@ -58,6 +60,7 @@ impl MutableAccountsResults { } } +#[derive(Clone, Copy)] pub struct MapColorToImmutableInt64 { pub(crate) obj_id: i32, } @@ -79,6 +82,7 @@ impl ImmutableBalanceResults { } } +#[derive(Clone, Copy)] pub struct MapColorToMutableInt64 { pub(crate) obj_id: i32, } diff --git a/packages/vm/wasmlib/src/coreblob/params.rs b/packages/vm/wasmlib/src/coreblob/params.rs index 54c0d9bebe..736edcdcfd 100644 --- a/packages/vm/wasmlib/src/coreblob/params.rs +++ b/packages/vm/wasmlib/src/coreblob/params.rs @@ -12,6 +12,7 @@ use crate::*; use crate::coreblob::*; use crate::host::*; +#[derive(Clone, Copy)] pub struct MapStringToImmutableBytes { pub(crate) obj_id: i32, } @@ -33,6 +34,7 @@ impl ImmutableStoreBlobParams { } } +#[derive(Clone, Copy)] pub struct MapStringToMutableBytes { pub(crate) obj_id: i32, } diff --git a/packages/vm/wasmlib/src/coreblob/results.rs b/packages/vm/wasmlib/src/coreblob/results.rs index dd06064b2e..c040ca1241 100644 --- a/packages/vm/wasmlib/src/coreblob/results.rs +++ b/packages/vm/wasmlib/src/coreblob/results.rs @@ -56,6 +56,7 @@ impl MutableGetBlobFieldResults { } } +#[derive(Clone, Copy)] pub struct MapStringToImmutableInt32 { pub(crate) obj_id: i32, } @@ -77,6 +78,7 @@ impl ImmutableGetBlobInfoResults { } } +#[derive(Clone, Copy)] pub struct MapStringToMutableInt32 { pub(crate) obj_id: i32, } @@ -102,6 +104,7 @@ impl MutableGetBlobInfoResults { } } +#[derive(Clone, Copy)] pub struct MapHashToImmutableInt32 { pub(crate) obj_id: i32, } @@ -123,6 +126,7 @@ impl ImmutableListBlobsResults { } } +#[derive(Clone, Copy)] pub struct MapHashToMutableInt32 { pub(crate) obj_id: i32, } diff --git a/packages/vm/wasmlib/src/coreblocklog/results.rs b/packages/vm/wasmlib/src/coreblocklog/results.rs index 19809b8973..98d0efaf24 100644 --- a/packages/vm/wasmlib/src/coreblocklog/results.rs +++ b/packages/vm/wasmlib/src/coreblocklog/results.rs @@ -72,6 +72,7 @@ impl MutableGetBlockInfoResults { } } +#[derive(Clone, Copy)] pub struct ArrayOfImmutableBytes { pub(crate) obj_id: i32, } @@ -98,6 +99,7 @@ impl ImmutableGetEventsForBlockResults { } } +#[derive(Clone, Copy)] pub struct ArrayOfMutableBytes { pub(crate) obj_id: i32, } @@ -206,6 +208,7 @@ impl MutableGetLatestBlockInfoResults { } } +#[derive(Clone, Copy)] pub struct ArrayOfImmutableRequestID { pub(crate) obj_id: i32, } @@ -232,6 +235,7 @@ impl ImmutableGetRequestIDsForBlockResults { } } +#[derive(Clone, Copy)] pub struct ArrayOfMutableRequestID { pub(crate) obj_id: i32, } diff --git a/packages/vm/wasmlib/src/coregovernance/results.rs b/packages/vm/wasmlib/src/coregovernance/results.rs index 0c5e2c9709..d834e234b7 100644 --- a/packages/vm/wasmlib/src/coregovernance/results.rs +++ b/packages/vm/wasmlib/src/coregovernance/results.rs @@ -12,6 +12,7 @@ use crate::*; use crate::coregovernance::*; use crate::host::*; +#[derive(Clone, Copy)] pub struct ArrayOfImmutableBytes { pub(crate) obj_id: i32, } @@ -38,6 +39,7 @@ impl ImmutableGetAllowedStateControllerAddressesResults { } } +#[derive(Clone, Copy)] pub struct ArrayOfMutableBytes { pub(crate) obj_id: i32, } diff --git a/packages/vm/wasmlib/src/coreroot/results.rs b/packages/vm/wasmlib/src/coreroot/results.rs index 9a4f88fdb5..933c193392 100644 --- a/packages/vm/wasmlib/src/coreroot/results.rs +++ b/packages/vm/wasmlib/src/coreroot/results.rs @@ -42,6 +42,7 @@ impl MutableFindContractResults { } } +#[derive(Clone, Copy)] pub struct MapHnameToImmutableBytes { pub(crate) obj_id: i32, } @@ -64,6 +65,7 @@ impl ImmutableGetContractRecordsResults { } } +#[derive(Clone, Copy)] pub struct MapHnameToMutableBytes { pub(crate) obj_id: i32, } diff --git a/packages/vm/wasmlib/ts/wasmclient/api_common/request_sender.ts b/packages/vm/wasmlib/ts/wasmclient/api_common/request_sender.ts new file mode 100644 index 0000000000..4fba917538 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/api_common/request_sender.ts @@ -0,0 +1,56 @@ +import { IResponse, IExtendedResponse } from './response_models'; + +const headers: { [id: string]: string } = { + 'Content-Type': 'application/json', +}; + +export async function sendRequest( + url: string, + verb: 'put' | 'post' | 'get' | 'delete', + path: string, + request?: T | undefined +): Promise { + const response = await sendRequestExt(url, verb, path, request); + return response.body; +} + +export async function sendRequestExt( + apiUrl: string, + verb: 'put' | 'post' | 'get' | 'delete', + path: string, + request?: T | undefined +): Promise> { + let fetchResponse: Response; + + try { + if(!path.startsWith("/")) + path = "/" + path; + const url = `${apiUrl}/${path}`; + fetchResponse = await fetch(url, { + method: verb, + headers, + body: JSON.stringify(request), + }); + + if (!fetchResponse) { + throw new Error('No data was returned from the API'); + } + + try { + const response = await fetchResponse.text() + .then((data)=> data ? JSON.parse(data) : {}); + return { body: response, response: fetchResponse }; + } catch (err) { + const error = err as Error; + if (fetchResponse.ok) { + throw new Error(error.message); + } else { + const text = await fetchResponse.text(); + throw new Error(error.message + ' --- ' + text); + } + } + } catch (err) { + const error = err as Error; + throw new Error('sendRequest: ' + error.message); + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/api_common/response_models.ts b/packages/vm/wasmlib/ts/wasmclient/api_common/response_models.ts new file mode 100644 index 0000000000..ca1faaa082 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/api_common/response_models.ts @@ -0,0 +1,8 @@ +export interface IResponse { + error?: string; +} + +export interface IExtendedResponse { + body: U; + response: Response; +} diff --git a/packages/vm/wasmlib/ts/wasmclient/arguments.ts b/packages/vm/wasmlib/ts/wasmclient/arguments.ts new file mode 100644 index 0000000000..b181bde558 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/arguments.ts @@ -0,0 +1,70 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import * as wasmclient from "./index" +import {Buffer} from "./buffer"; + +// The Arguments struct is used to gather all arguments for this smart +// contract function call and encode it into this deterministic byte array +export class Arguments extends wasmclient.Encoder { + private args = new Map(); + + // get(key: string): wasmclient.Bytes { + // const bytes = this.args.get(key); + // return bytes ?? Buffer.alloc(0); + // } + + public set(key: string, val: wasmclient.Bytes): void { + this.args.set(key, val); + } + + public indexedKey(key: string, index: wasmclient.Int32): string { + return key + "." + index.toString(); + } + + public mandatory(key: string): void { + if (!this.args.has(key)) { + wasmclient.panic("missing mandatory " + key) + } + } + + // Encode returns a byte array that encodes the Arguments as follows: + // Sort all keys in ascending order (very important, because this data + // will be part of the data that will be signed, so the order needs to + // be 100% deterministic). Then emit the 4-byte argument count. + // Next for each argument emit the 2-byte key length, the key prepended + // with the minus sign, the 4-byte value length, and then the value bytes. + public encode(): wasmclient.Bytes { + const keys = new Array(); + for (const key of this.args.keys()) { + keys.push(key); + } + keys.sort((lhs, rhs) => lhs.localeCompare(rhs)); + + let buf = Buffer.alloc(4); + buf.writeUInt32LE(keys.length, 0); + for (const key of keys) { + const keyBuf = Buffer.from("-" + key); + const keyLen = Buffer.alloc(2); + keyLen.writeUInt16LE(keyBuf.length, 0); + const valBuf = this.args.get(key); + if (!valBuf) { + throw new Error("Arguments.encode: missing value"); + } + const valLen = Buffer.alloc(4); + valLen.writeUInt32LE(valBuf.length, 0); + buf = Buffer.concat([buf, keyLen, keyBuf, valLen, valBuf]); + } + return buf; + } + + public encodeCall(): wasmclient.Items { + let items = new wasmclient.Items() + for (const [key, val] of this.args) { + const k = Buffer.from(key).toString("base64"); + const v = val.toString("base64"); + items.Items.push(new wasmclient.Item(k, v)) + } + return items; + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/buffer/index.d.ts b/packages/vm/wasmlib/ts/wasmclient/buffer/index.d.ts new file mode 100644 index 0000000000..99764ab071 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/buffer/index.d.ts @@ -0,0 +1,194 @@ +export class Buffer extends Uint8Array { + length: number + write(string: string, offset?: number, length?: number, encoding?: string): number; + toString(encoding?: string, start?: number, end?: number): string; + toJSON(): { type: 'Buffer', data: any[] }; + equals(otherBuffer: Buffer): boolean; + compare(otherBuffer: Uint8Array, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number; + copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number; + slice(start?: number, end?: number): Buffer; + writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number; + readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number; + readIntLE(offset: number, byteLength: number, noAssert?: boolean): number; + readIntBE(offset: number, byteLength: number, noAssert?: boolean): number; + readUInt8(offset: number, noAssert?: boolean): number; + readUInt16LE(offset: number, noAssert?: boolean): number; + readUInt16BE(offset: number, noAssert?: boolean): number; + readUInt32LE(offset: number, noAssert?: boolean): number; + readUInt32BE(offset: number, noAssert?: boolean): number; + readBigUInt64LE(offset: number): bigint; + readBigUInt64BE(offset: number): bigint; + readInt8(offset: number, noAssert?: boolean): number; + readInt16LE(offset: number, noAssert?: boolean): number; + readInt16BE(offset: number, noAssert?: boolean): number; + readInt32LE(offset: number, noAssert?: boolean): number; + readInt32BE(offset: number, noAssert?: boolean): number; + readBigInt64LE(offset: number): bigint; + readBigInt64BE(offset: number): bigint; + readFloatLE(offset: number, noAssert?: boolean): number; + readFloatBE(offset: number, noAssert?: boolean): number; + readDoubleLE(offset: number, noAssert?: boolean): number; + readDoubleBE(offset: number, noAssert?: boolean): number; + reverse(): this; + swap16(): Buffer; + swap32(): Buffer; + swap64(): Buffer; + writeUInt8(value: number, offset: number, noAssert?: boolean): number; + writeUInt16LE(value: number, offset: number, noAssert?: boolean): number; + writeUInt16BE(value: number, offset: number, noAssert?: boolean): number; + writeUInt32LE(value: number, offset: number, noAssert?: boolean): number; + writeUInt32BE(value: number, offset: number, noAssert?: boolean): number; + writeBigUInt64LE(value: bigint, offset: number): number; + writeBigUInt64BE(value: bigint, offset: number): number; + writeInt8(value: number, offset: number, noAssert?: boolean): number; + writeInt16LE(value: number, offset: number, noAssert?: boolean): number; + writeInt16BE(value: number, offset: number, noAssert?: boolean): number; + writeInt32LE(value: number, offset: number, noAssert?: boolean): number; + writeInt32BE(value: number, offset: number, noAssert?: boolean): number; + writeBigInt64LE(value: bigint, offset: number): number; + writeBigInt64BE(value: bigint, offset: number): number; + writeFloatLE(value: number, offset: number, noAssert?: boolean): number; + writeFloatBE(value: number, offset: number, noAssert?: boolean): number; + writeDoubleLE(value: number, offset: number, noAssert?: boolean): number; + writeDoubleBE(value: number, offset: number, noAssert?: boolean): number; + fill(value: any, offset?: number, end?: number): this; + indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number; + lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number; + includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean; + + /** + * Allocates a new buffer containing the given {str}. + * + * @param str String to store in buffer. + * @param encoding encoding to use, optional. Default is 'utf8' + */ + constructor(str: string, encoding?: string); + /** + * Allocates a new buffer of {size} octets. + * + * @param size count of octets to allocate. + */ + constructor(size: number); + /** + * Allocates a new buffer containing the given {array} of octets. + * + * @param array The octets to store. + */ + constructor(array: Uint8Array); + /** + * Produces a Buffer backed by the same allocated memory as + * the given {ArrayBuffer}. + * + * + * @param arrayBuffer The ArrayBuffer with which to share memory. + */ + constructor(arrayBuffer: ArrayBuffer); + /** + * Allocates a new buffer containing the given {array} of octets. + * + * @param array The octets to store. + */ + constructor(array: any[]); + /** + * Copies the passed {buffer} data onto a new {Buffer} instance. + * + * @param buffer The buffer to copy. + */ + constructor(buffer: Buffer); + prototype: Buffer; + /** + * Allocates a new Buffer using an {array} of octets. + * + * @param array + */ + static from(array: any[]): Buffer; + /** + * When passed a reference to the .buffer property of a TypedArray instance, + * the newly created Buffer will share the same allocated memory as the TypedArray. + * The optional {byteOffset} and {length} arguments specify a memory range + * within the {arrayBuffer} that will be shared by the Buffer. + * + * @param arrayBuffer The .buffer property of a TypedArray or a new ArrayBuffer() + * @param byteOffset + * @param length + */ + static from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer; + /** + * Copies the passed {buffer} data onto a new Buffer instance. + * + * @param buffer + */ + static from(buffer: Buffer | Uint8Array): Buffer; + /** + * Creates a new Buffer containing the given JavaScript string {str}. + * If provided, the {encoding} parameter identifies the character encoding. + * If not provided, {encoding} defaults to 'utf8'. + * + * @param str + */ + static from(str: string, encoding?: string): Buffer; + /** + * Returns true if {obj} is a Buffer + * + * @param obj object to test. + */ + static isBuffer(obj: any): obj is Buffer; + /** + * Returns true if {encoding} is a valid encoding argument. + * Valid string encodings in Node 0.12: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex' + * + * @param encoding string to test. + */ + static isEncoding(encoding: string): boolean; + /** + * Gives the actual byte length of a string. encoding defaults to 'utf8'. + * This is not the same as String.prototype.length since that returns the number of characters in a string. + * + * @param string string to test. + * @param encoding encoding used to evaluate (defaults to 'utf8') + */ + static byteLength(string: string, encoding?: string): number; + /** + * Returns a buffer which is the result of concatenating all the buffers in the list together. + * + * If the list has no items, or if the totalLength is 0, then it returns a zero-length buffer. + * If the list has exactly one item, then the first item of the list is returned. + * If the list has more than one item, then a new Buffer is created. + * + * @param list An array of Buffer objects to concatenate + * @param totalLength Total length of the buffers when concatenated. + * If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly. + */ + static concat(list: Uint8Array[], totalLength?: number): Buffer; + /** + * The same as buf1.compare(buf2). + */ + static compare(buf1: Uint8Array, buf2: Uint8Array): number; + /** + * Allocates a new buffer of {size} octets. + * + * @param size count of octets to allocate. + * @param fill if specified, buffer will be initialized by calling buf.fill(fill). + * If parameter is omitted, buffer will be filled with zeros. + * @param encoding encoding used for call to buf.fill while initializing + */ + static alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer; + /** + * Allocates a new buffer of {size} octets, leaving memory not initialized, so the contents + * of the newly created Buffer are unknown and may contain sensitive data. + * + * @param size count of octets to allocate + */ + static allocUnsafe(size: number): Buffer; + /** + * Allocates a new non-pooled buffer of {size} octets, leaving memory not initialized, so the contents + * of the newly created Buffer are unknown and may contain sensitive data. + * + * @param size count of octets to allocate + */ + static allocUnsafeSlow(size: number): Buffer; +} diff --git a/packages/vm/wasmlib/ts/wasmclient/buffer/index.js b/packages/vm/wasmlib/ts/wasmclient/buffer/index.js new file mode 100644 index 0000000000..a17a05b861 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/buffer/index.js @@ -0,0 +1,2115 @@ +/* eslint-disable no-unused-vars */ +/* eslint-disable no-constant-condition */ +/* eslint-disable no-undef */ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +/* eslint-disable no-proto */ + +'use strict' + +const base64 = require('base64-js') +const ieee754 = require('ieee754') +const customInspectSymbol = + (typeof Symbol === 'function' && typeof Symbol['for'] === 'function') // eslint-disable-line dot-notation + ? Symbol['for']('nodejs.util.inspect.custom') // eslint-disable-line dot-notation + : null + +exports.Buffer = Buffer +exports.SlowBuffer = SlowBuffer +exports.INSPECT_MAX_BYTES = 50 + +const K_MAX_LENGTH = 0x7fffffff +exports.kMaxLength = K_MAX_LENGTH + +/** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Print warning and recommend using `buffer` v4.x which has an Object + * implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * We report that the browser does not support typed arrays if the are not subclassable + * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array` + * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support + * for __proto__ and has a buggy typed array implementation. + */ +Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport() + +if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' && + typeof console.error === 'function') { + console.error( + 'This browser lacks typed array (Uint8Array) support which is required by ' + + '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.' + ) +} + +function typedArraySupport() { + // Can typed array instances can be augmented? + try { + const arr = new Uint8Array(1) + const proto = { foo: function () { return 42 } } + Object.setPrototypeOf(proto, Uint8Array.prototype) + Object.setPrototypeOf(arr, proto) + return arr.foo() === 42 + } catch (e) { + return false + } +} + +Object.defineProperty(Buffer.prototype, 'parent', { + enumerable: true, + get: function () { + if (!Buffer.isBuffer(this)) return undefined + return this.buffer + } +}) + +Object.defineProperty(Buffer.prototype, 'offset', { + enumerable: true, + get: function () { + if (!Buffer.isBuffer(this)) return undefined + return this.byteOffset + } +}) + +function createBuffer(length) { + if (length > K_MAX_LENGTH) { + throw new RangeError('The value "' + length + '" is invalid for option "size"') + } + // Return an augmented `Uint8Array` instance + const buf = new Uint8Array(length) + Object.setPrototypeOf(buf, Buffer.prototype) + return buf +} + +/** + * The Buffer constructor returns instances of `Uint8Array` that have their + * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of + * `Uint8Array`, so the returned instances will have all the node `Buffer` methods + * and the `Uint8Array` methods. Square bracket notation works as expected -- it + * returns a single octet. + * + * The `Uint8Array` prototype remains unmodified. + */ + +function Buffer(arg, encodingOrOffset, length) { + // Common case. + if (typeof arg === 'number') { + if (typeof encodingOrOffset === 'string') { + throw new TypeError( + 'The "string" argument must be of type string. Received type number' + ) + } + return allocUnsafe(arg) + } + return from(arg, encodingOrOffset, length) +} + +Buffer.poolSize = 8192 // not used by this implementation + +function from(value, encodingOrOffset, length) { + if (typeof value === 'string') { + return fromString(value, encodingOrOffset) + } + + if (ArrayBuffer.isView(value)) { + return fromArrayView(value) + } + + if (value == null) { + throw new TypeError( + 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + + 'or Array-like Object. Received type ' + (typeof value) + ) + } + + if (isInstance(value, ArrayBuffer) || + (value && isInstance(value.buffer, ArrayBuffer))) { + return fromArrayBuffer(value, encodingOrOffset, length) + } + + if (typeof SharedArrayBuffer !== 'undefined' && + (isInstance(value, SharedArrayBuffer) || + (value && isInstance(value.buffer, SharedArrayBuffer)))) { + return fromArrayBuffer(value, encodingOrOffset, length) + } + + if (typeof value === 'number') { + throw new TypeError( + 'The "value" argument must not be of type number. Received type number' + ) + } + + const valueOf = value.valueOf && value.valueOf() + if (valueOf != null && valueOf !== value) { + return Buffer.from(valueOf, encodingOrOffset, length) + } + + const b = fromObject(value) + if (b) return b + + if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null && + typeof value[Symbol.toPrimitive] === 'function') { + return Buffer.from(value[Symbol.toPrimitive]('string'), encodingOrOffset, length) + } + + throw new TypeError( + 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + + 'or Array-like Object. Received type ' + (typeof value) + ) +} + +/** + * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError + * if value is a number. + * Buffer.from(str[, encoding]) + * Buffer.from(array) + * Buffer.from(buffer) + * Buffer.from(arrayBuffer[, byteOffset[, length]]) + **/ +Buffer.from = function (value, encodingOrOffset, length) { + return from(value, encodingOrOffset, length) +} + +// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug: +// https://github.com/feross/buffer/pull/148 +Object.setPrototypeOf(Buffer.prototype, Uint8Array.prototype) +Object.setPrototypeOf(Buffer, Uint8Array) + +function assertSize(size) { + if (typeof size !== 'number') { + throw new TypeError('"size" argument must be of type number') + } else if (size < 0) { + throw new RangeError('The value "' + size + '" is invalid for option "size"') + } +} + +function alloc(size, fill, encoding) { + assertSize(size) + if (size <= 0) { + return createBuffer(size) + } + if (fill !== undefined) { + // Only pay attention to encoding if it's a string. This + // prevents accidentally sending in a number that would + // be interpreted as a start offset. + return typeof encoding === 'string' + ? createBuffer(size).fill(fill, encoding) + : createBuffer(size).fill(fill) + } + return createBuffer(size) +} + +/** + * Creates a new filled Buffer instance. + * alloc(size[, fill[, encoding]]) + **/ +Buffer.alloc = function (size, fill, encoding) { + return alloc(size, fill, encoding) +} + +function allocUnsafe(size) { + assertSize(size) + return createBuffer(size < 0 ? 0 : checked(size) | 0) +} + +/** + * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. + * */ +Buffer.allocUnsafe = function (size) { + return allocUnsafe(size) +} +/** + * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. + */ +Buffer.allocUnsafeSlow = function (size) { + return allocUnsafe(size) +} + +function fromString(string, encoding) { + if (typeof encoding !== 'string' || encoding === '') { + encoding = 'utf8' + } + + if (!Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding) + } + + const length = byteLength(string, encoding) | 0 + let buf = createBuffer(length) + + const actual = buf.write(string, encoding) + + if (actual !== length) { + // Writing a hex string, for example, that contains invalid characters will + // cause everything after the first invalid character to be ignored. (e.g. + // 'abxxcd' will be treated as 'ab') + buf = buf.slice(0, actual) + } + + return buf +} + +function fromArrayLike(array) { + const length = array.length < 0 ? 0 : checked(array.length) | 0 + const buf = createBuffer(length) + for (let i = 0; i < length; i += 1) { + buf[i] = array[i] & 255 + } + return buf +} + +function fromArrayView(arrayView) { + if (isInstance(arrayView, Uint8Array)) { + const copy = new Uint8Array(arrayView) + return fromArrayBuffer(copy.buffer, copy.byteOffset, copy.byteLength) + } + return fromArrayLike(arrayView) +} + +function fromArrayBuffer(array, byteOffset, length) { + if (byteOffset < 0 || array.byteLength < byteOffset) { + throw new RangeError('"offset" is outside of buffer bounds') + } + + if (array.byteLength < byteOffset + (length || 0)) { + throw new RangeError('"length" is outside of buffer bounds') + } + + let buf + if (byteOffset === undefined && length === undefined) { + buf = new Uint8Array(array) + } else if (length === undefined) { + buf = new Uint8Array(array, byteOffset) + } else { + buf = new Uint8Array(array, byteOffset, length) + } + + // Return an augmented `Uint8Array` instance + Object.setPrototypeOf(buf, Buffer.prototype) + + return buf +} + +function fromObject(obj) { + if (Buffer.isBuffer(obj)) { + const len = checked(obj.length) | 0 + const buf = createBuffer(len) + + if (buf.length === 0) { + return buf + } + + obj.copy(buf, 0, 0, len) + return buf + } + + if (obj.length !== undefined) { + if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) { + return createBuffer(0) + } + return fromArrayLike(obj) + } + + if (obj.type === 'Buffer' && Array.isArray(obj.data)) { + return fromArrayLike(obj.data) + } +} + +function checked(length) { + // Note: cannot use `length < K_MAX_LENGTH` here because that fails when + // length is NaN (which is otherwise coerced to zero.) + if (length >= K_MAX_LENGTH) { + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes') + } + return length | 0 +} + +function SlowBuffer(length) { + if (+length != length) { // eslint-disable-line eqeqeq + length = 0 + } + return Buffer.alloc(+length) +} + +Buffer.isBuffer = function isBuffer(b) { + return b != null && b._isBuffer === true && + b !== Buffer.prototype // so Buffer.isBuffer(Buffer.prototype) will be false +} + +Buffer.compare = function compare(a, b) { + if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength) + if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength) + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + throw new TypeError( + 'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array' + ) + } + + if (a === b) return 0 + + let x = a.length + let y = b.length + + for (let i = 0, len = Math.min(x, y); i < len; ++i) { + if (a[i] !== b[i]) { + x = a[i] + y = b[i] + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +Buffer.isEncoding = function isEncoding(encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'latin1': + case 'binary': + case 'base64': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true + default: + return false + } +} + +Buffer.concat = function concat(list, length) { + if (!Array.isArray(list)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + + if (list.length === 0) { + return Buffer.alloc(0) + } + + let i + if (length === undefined) { + length = 0 + for (i = 0; i < list.length; ++i) { + length += list[i].length + } + } + + const buffer = Buffer.allocUnsafe(length) + let pos = 0 + for (i = 0; i < list.length; ++i) { + let buf = list[i] + if (isInstance(buf, Uint8Array)) { + if (pos + buf.length > buffer.length) { + if (!Buffer.isBuffer(buf)) { + buf = Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength) + } + buf.copy(buffer, pos) + } else { + Uint8Array.prototype.set.call( + buffer, + buf, + pos + ) + } + } else if (!Buffer.isBuffer(buf)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } else { + buf.copy(buffer, pos) + } + pos += buf.length + } + return buffer +} + +function byteLength(string, encoding) { + if (Buffer.isBuffer(string)) { + return string.length + } + if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) { + return string.byteLength + } + if (typeof string !== 'string') { + throw new TypeError( + 'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' + + 'Received type ' + typeof string + ) + } + + const len = string.length + const mustMatch = (arguments.length > 2 && arguments[2] === true) + if (!mustMatch && len === 0) return 0 + + // Use a for loop to avoid recursion + let loweredCase = false + for (; ;) { + switch (encoding) { + case 'ascii': + case 'latin1': + case 'binary': + return len + case 'utf8': + case 'utf-8': + return utf8ToBytes(string).length + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return len * 2 + case 'hex': + return len >>> 1 + case 'base64': + return base64ToBytes(string).length + default: + if (loweredCase) { + return mustMatch ? -1 : utf8ToBytes(string).length // assume utf8 + } + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} +Buffer.byteLength = byteLength + +function slowToString(encoding, start, end) { + let loweredCase = false + + // No need to verify that "this.length <= MAX_UINT32" since it's a read-only + // property of a typed array. + + // This behaves neither like String nor Uint8Array in that we set start/end + // to their upper/lower bounds if the value passed is out of range. + // undefined is handled specially as per ECMA-262 6th Edition, + // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. + if (start === undefined || start < 0) { + start = 0 + } + // Return early if start > this.length. Done here to prevent potential uint32 + // coercion fail below. + if (start > this.length) { + return '' + } + + if (end === undefined || end > this.length) { + end = this.length + } + + if (end <= 0) { + return '' + } + + // Force coercion to uint32. This will also coerce falsey/NaN values to 0. + end >>>= 0 + start >>>= 0 + + if (end <= start) { + return '' + } + + if (!encoding) encoding = 'utf8' + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) + + case 'ascii': + return asciiSlice(this, start, end) + + case 'latin1': + case 'binary': + return latin1Slice(this, start, end) + + case 'base64': + return base64Slice(this, start, end) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase() + loweredCase = true + } + } +} + +// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package) +// to detect a Buffer instance. It's not possible to use `instanceof Buffer` +// reliably in a browserify context because there could be multiple different +// copies of the 'buffer' package in use. This method works even for Buffer +// instances that were created from another copy of the `buffer` package. +// See: https://github.com/feross/buffer/issues/154 +Buffer.prototype._isBuffer = true + +function swap(b, n, m) { + const i = b[n] + b[n] = b[m] + b[m] = i +} + +Buffer.prototype.swap16 = function swap16() { + const len = this.length + if (len % 2 !== 0) { + throw new RangeError('Buffer size must be a multiple of 16-bits') + } + for (let i = 0; i < len; i += 2) { + swap(this, i, i + 1) + } + return this +} + +Buffer.prototype.swap32 = function swap32() { + const len = this.length + if (len % 4 !== 0) { + throw new RangeError('Buffer size must be a multiple of 32-bits') + } + for (let i = 0; i < len; i += 4) { + swap(this, i, i + 3) + swap(this, i + 1, i + 2) + } + return this +} + +Buffer.prototype.swap64 = function swap64() { + const len = this.length + if (len % 8 !== 0) { + throw new RangeError('Buffer size must be a multiple of 64-bits') + } + for (let i = 0; i < len; i += 8) { + swap(this, i, i + 7) + swap(this, i + 1, i + 6) + swap(this, i + 2, i + 5) + swap(this, i + 3, i + 4) + } + return this +} + +Buffer.prototype.toString = function toString() { + const length = this.length + if (length === 0) return '' + if (arguments.length === 0) return utf8Slice(this, 0, length) + return slowToString.apply(this, arguments) +} + +Buffer.prototype.toLocaleString = Buffer.prototype.toString + +Buffer.prototype.equals = function equals(b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + if (this === b) return true + return Buffer.compare(this, b) === 0 +} + +Buffer.prototype.inspect = function inspect() { + let str = '' + const max = exports.INSPECT_MAX_BYTES + str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim() + if (this.length > max) str += ' ... ' + return '' +} +if (customInspectSymbol) { + Buffer.prototype[customInspectSymbol] = Buffer.prototype.inspect +} + +Buffer.prototype.compare = function compare(target, start, end, thisStart, thisEnd) { + if (isInstance(target, Uint8Array)) { + target = Buffer.from(target, target.offset, target.byteLength) + } + if (!Buffer.isBuffer(target)) { + throw new TypeError( + 'The "target" argument must be one of type Buffer or Uint8Array. ' + + 'Received type ' + (typeof target) + ) + } + + if (start === undefined) { + start = 0 + } + if (end === undefined) { + end = target ? target.length : 0 + } + if (thisStart === undefined) { + thisStart = 0 + } + if (thisEnd === undefined) { + thisEnd = this.length + } + + if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { + throw new RangeError('out of range index') + } + + if (thisStart >= thisEnd && start >= end) { + return 0 + } + if (thisStart >= thisEnd) { + return -1 + } + if (start >= end) { + return 1 + } + + start >>>= 0 + end >>>= 0 + thisStart >>>= 0 + thisEnd >>>= 0 + + if (this === target) return 0 + + let x = thisEnd - thisStart + let y = end - start + const len = Math.min(x, y) + + const thisCopy = this.slice(thisStart, thisEnd) + const targetCopy = target.slice(start, end) + + for (let i = 0; i < len; ++i) { + if (thisCopy[i] !== targetCopy[i]) { + x = thisCopy[i] + y = targetCopy[i] + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, +// OR the last index of `val` in `buffer` at offset <= `byteOffset`. +// +// Arguments: +// - buffer - a Buffer to search +// - val - a string, Buffer, or number +// - byteOffset - an index into `buffer`; will be clamped to an int32 +// - encoding - an optional encoding, relevant is val is a string +// - dir - true for indexOf, false for lastIndexOf +function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) { + // Empty buffer means no match + if (buffer.length === 0) return -1 + + // Normalize byteOffset + if (typeof byteOffset === 'string') { + encoding = byteOffset + byteOffset = 0 + } else if (byteOffset > 0x7fffffff) { + byteOffset = 0x7fffffff + } else if (byteOffset < -0x80000000) { + byteOffset = -0x80000000 + } + byteOffset = +byteOffset // Coerce to Number. + if (numberIsNaN(byteOffset)) { + // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer + byteOffset = dir ? 0 : (buffer.length - 1) + } + + // Normalize byteOffset: negative offsets start from the end of the buffer + if (byteOffset < 0) byteOffset = buffer.length + byteOffset + if (byteOffset >= buffer.length) { + if (dir) return -1 + else byteOffset = buffer.length - 1 + } else if (byteOffset < 0) { + if (dir) byteOffset = 0 + else return -1 + } + + // Normalize val + if (typeof val === 'string') { + val = Buffer.from(val, encoding) + } + + // Finally, search either indexOf (if dir is true) or lastIndexOf + if (Buffer.isBuffer(val)) { + // Special case: looking for empty string/buffer always fails + if (val.length === 0) { + return -1 + } + return arrayIndexOf(buffer, val, byteOffset, encoding, dir) + } else if (typeof val === 'number') { + val = val & 0xFF // Search for a byte value [0-255] + if (typeof Uint8Array.prototype.indexOf === 'function') { + if (dir) { + return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) + } else { + return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) + } + } + return arrayIndexOf(buffer, [val], byteOffset, encoding, dir) + } + + throw new TypeError('val must be string, number or Buffer') +} + +function arrayIndexOf(arr, val, byteOffset, encoding, dir) { + let indexSize = 1 + let arrLength = arr.length + let valLength = val.length + + if (encoding !== undefined) { + encoding = String(encoding).toLowerCase() + if (encoding === 'ucs2' || encoding === 'ucs-2' || + encoding === 'utf16le' || encoding === 'utf-16le') { + if (arr.length < 2 || val.length < 2) { + return -1 + } + indexSize = 2 + arrLength /= 2 + valLength /= 2 + byteOffset /= 2 + } + } + + function read(buf, i) { + if (indexSize === 1) { + return buf[i] + } else { + return buf.readUInt16BE(i * indexSize) + } + } + + let i + if (dir) { + let foundIndex = -1 + for (i = byteOffset; i < arrLength; i++) { + if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { + if (foundIndex === -1) foundIndex = i + if (i - foundIndex + 1 === valLength) return foundIndex * indexSize + } else { + if (foundIndex !== -1) i -= i - foundIndex + foundIndex = -1 + } + } + } else { + if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength + for (i = byteOffset; i >= 0; i--) { + let found = true + for (let j = 0; j < valLength; j++) { + if (read(arr, i + j) !== read(val, j)) { + found = false + break + } + } + if (found) return i + } + } + + return -1 +} + +Buffer.prototype.includes = function includes(val, byteOffset, encoding) { + return this.indexOf(val, byteOffset, encoding) !== -1 +} + +Buffer.prototype.indexOf = function indexOf(val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, true) +} + +Buffer.prototype.lastIndexOf = function lastIndexOf(val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, false) +} + +function hexWrite(buf, string, offset, length) { + offset = Number(offset) || 0 + const remaining = buf.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + + const strLen = string.length + + if (length > strLen / 2) { + length = strLen / 2 + } + let i + for (i = 0; i < length; ++i) { + const parsed = parseInt(string.substr(i * 2, 2), 16) + if (numberIsNaN(parsed)) return i + buf[offset + i] = parsed + } + return i +} + +function utf8Write(buf, string, offset, length) { + return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) +} + +function asciiWrite(buf, string, offset, length) { + return blitBuffer(asciiToBytes(string), buf, offset, length) +} + +function base64Write(buf, string, offset, length) { + return blitBuffer(base64ToBytes(string), buf, offset, length) +} + +function ucs2Write(buf, string, offset, length) { + return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) +} + +Buffer.prototype.write = function write(string, offset, length, encoding) { + // Buffer#write(string) + if (offset === undefined) { + encoding = 'utf8' + length = this.length + offset = 0 + // Buffer#write(string, encoding) + } else if (length === undefined && typeof offset === 'string') { + encoding = offset + length = this.length + offset = 0 + // Buffer#write(string, offset[, length][, encoding]) + } else if (isFinite(offset)) { + offset = offset >>> 0 + if (isFinite(length)) { + length = length >>> 0 + if (encoding === undefined) encoding = 'utf8' + } else { + encoding = length + length = undefined + } + } else { + throw new Error( + 'Buffer.write(string, encoding, offset[, length]) is no longer supported' + ) + } + + const remaining = this.length - offset + if (length === undefined || length > remaining) length = remaining + + if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { + throw new RangeError('Attempt to write outside buffer bounds') + } + + if (!encoding) encoding = 'utf8' + + let loweredCase = false + for (; ;) { + switch (encoding) { + case 'hex': + return hexWrite(this, string, offset, length) + + case 'utf8': + case 'utf-8': + return utf8Write(this, string, offset, length) + + case 'ascii': + case 'latin1': + case 'binary': + return asciiWrite(this, string, offset, length) + + case 'base64': + // Warning: maxLength not taken into account in base64Write + return base64Write(this, string, offset, length) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return ucs2Write(this, string, offset, length) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} + +Buffer.prototype.toJSON = function toJSON() { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + } +} + +function base64Slice(buf, start, end) { + if (start === 0 && end === buf.length) { + return base64.fromByteArray(buf) + } else { + return base64.fromByteArray(buf.slice(start, end)) + } +} + +function utf8Slice(buf, start, end) { + end = Math.min(buf.length, end) + const res = [] + + let i = start + while (i < end) { + const firstByte = buf[i] + let codePoint = null + let bytesPerSequence = (firstByte > 0xEF) + ? 4 + : (firstByte > 0xDF) + ? 3 + : (firstByte > 0xBF) + ? 2 + : 1 + + if (i + bytesPerSequence <= end) { + let secondByte, thirdByte, fourthByte, tempCodePoint + + switch (bytesPerSequence) { + case 1: + if (firstByte < 0x80) { + codePoint = firstByte + } + break + case 2: + secondByte = buf[i + 1] + if ((secondByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) + if (tempCodePoint > 0x7F) { + codePoint = tempCodePoint + } + } + break + case 3: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) + if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { + codePoint = tempCodePoint + } + } + break + case 4: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + fourthByte = buf[i + 3] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) + if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { + codePoint = tempCodePoint + } + } + } + } + + if (codePoint === null) { + // we did not generate a valid codePoint so insert a + // replacement char (U+FFFD) and advance only 1 byte + codePoint = 0xFFFD + bytesPerSequence = 1 + } else if (codePoint > 0xFFFF) { + // encode to utf16 (surrogate pair dance) + codePoint -= 0x10000 + res.push(codePoint >>> 10 & 0x3FF | 0xD800) + codePoint = 0xDC00 | codePoint & 0x3FF + } + + res.push(codePoint) + i += bytesPerSequence + } + + return decodeCodePointsArray(res) +} + +// Based on http://stackoverflow.com/a/22747272/680742, the browser with +// the lowest limit is Chrome, with 0x10000 args. +// We go 1 magnitude less, for safety +const MAX_ARGUMENTS_LENGTH = 0x1000 + +function decodeCodePointsArray(codePoints) { + const len = codePoints.length + if (len <= MAX_ARGUMENTS_LENGTH) { + return String.fromCharCode.apply(String, codePoints) // avoid extra slice() + } + + // Decode in chunks to avoid "call stack size exceeded". + let res = '' + let i = 0 + while (i < len) { + res += String.fromCharCode.apply( + String, + codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) + ) + } + return res +} + +function asciiSlice(buf, start, end) { + let ret = '' + end = Math.min(buf.length, end) + + for (let i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i] & 0x7F) + } + return ret +} + +function latin1Slice(buf, start, end) { + let ret = '' + end = Math.min(buf.length, end) + + for (let i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i]) + } + return ret +} + +function hexSlice(buf, start, end) { + const len = buf.length + + if (!start || start < 0) start = 0 + if (!end || end < 0 || end > len) end = len + + let out = '' + for (let i = start; i < end; ++i) { + out += hexSliceLookupTable[buf[i]] + } + return out +} + +function utf16leSlice(buf, start, end) { + const bytes = buf.slice(start, end) + let res = '' + // If bytes.length is odd, the last 8 bits must be ignored (same as node.js) + for (let i = 0; i < bytes.length - 1; i += 2) { + res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256)) + } + return res +} + +Buffer.prototype.slice = function slice(start, end) { + const len = this.length + start = ~~start + end = end === undefined ? len : ~~end + + if (start < 0) { + start += len + if (start < 0) start = 0 + } else if (start > len) { + start = len + } + + if (end < 0) { + end += len + if (end < 0) end = 0 + } else if (end > len) { + end = len + } + + if (end < start) end = start + + const newBuf = this.subarray(start, end) + // Return an augmented `Uint8Array` instance + Object.setPrototypeOf(newBuf, Buffer.prototype) + + return newBuf +} + +/* + * Need to make sure that buffer isn't trying to write out of bounds. + */ +function checkOffset(offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') + if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') +} + +Buffer.prototype.readUintLE = + Buffer.prototype.readUIntLE = function readUIntLE(offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + let val = this[offset] + let mul = 1 + let i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + + return val + } + +Buffer.prototype.readUintBE = + Buffer.prototype.readUIntBE = function readUIntBE(offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + checkOffset(offset, byteLength, this.length) + } + + let val = this[offset + --byteLength] + let mul = 1 + while (byteLength > 0 && (mul *= 0x100)) { + val += this[offset + --byteLength] * mul + } + + return val + } + +Buffer.prototype.readUint8 = + Buffer.prototype.readUInt8 = function readUInt8(offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 1, this.length) + return this[offset] + } + +Buffer.prototype.readUint16LE = + Buffer.prototype.readUInt16LE = function readUInt16LE(offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + return this[offset] | (this[offset + 1] << 8) + } + +Buffer.prototype.readUint16BE = + Buffer.prototype.readUInt16BE = function readUInt16BE(offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] + } + +Buffer.prototype.readUint32LE = + Buffer.prototype.readUInt32LE = function readUInt32LE(offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return ((this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16)) + + (this[offset + 3] * 0x1000000) + } + +Buffer.prototype.readUint32BE = + Buffer.prototype.readUInt32BE = function readUInt32BE(offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) + } + +Buffer.prototype.readBigUInt64LE = defineBigIntMethod(function readBigUInt64LE(offset) { + offset = offset >>> 0 + validateNumber(offset, 'offset') + const first = this[offset] + const last = this[offset + 7] + if (first === undefined || last === undefined) { + boundsError(offset, this.length - 8) + } + + const lo = first + + this[++offset] * 2 ** 8 + + this[++offset] * 2 ** 16 + + this[++offset] * 2 ** 24 + + const hi = this[++offset] + + this[++offset] * 2 ** 8 + + this[++offset] * 2 ** 16 + + last * 2 ** 24 + + return BigInt(lo) + (BigInt(hi) << BigInt(32)) +}) + +Buffer.prototype.readBigUInt64BE = defineBigIntMethod(function readBigUInt64BE(offset) { + offset = offset >>> 0 + validateNumber(offset, 'offset') + const first = this[offset] + const last = this[offset + 7] + if (first === undefined || last === undefined) { + boundsError(offset, this.length - 8) + } + + const hi = first * 2 ** 24 + + this[++offset] * 2 ** 16 + + this[++offset] * 2 ** 8 + + this[++offset] + + const lo = this[++offset] * 2 ** 24 + + this[++offset] * 2 ** 16 + + this[++offset] * 2 ** 8 + + last + + return (BigInt(hi) << BigInt(32)) + BigInt(lo) +}) + +Buffer.prototype.readIntLE = function readIntLE(offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + let val = this[offset] + let mul = 1 + let i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readIntBE = function readIntBE(offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + let i = byteLength + let mul = 1 + let val = this[offset + --i] + while (i > 0 && (mul *= 0x100)) { + val += this[offset + --i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readInt8 = function readInt8(offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 1, this.length) + if (!(this[offset] & 0x80)) return (this[offset]) + return ((0xff - this[offset] + 1) * -1) +} + +Buffer.prototype.readInt16LE = function readInt16LE(offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + const val = this[offset] | (this[offset + 1] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt16BE = function readInt16BE(offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + const val = this[offset + 1] | (this[offset] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt32LE = function readInt32LE(offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) +} + +Buffer.prototype.readInt32BE = function readInt32BE(offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) +} + +Buffer.prototype.readBigInt64LE = defineBigIntMethod(function readBigInt64LE(offset) { + offset = offset >>> 0 + validateNumber(offset, 'offset') + const first = this[offset] + const last = this[offset + 7] + if (first === undefined || last === undefined) { + boundsError(offset, this.length - 8) + } + + const val = this[offset + 4] + + this[offset + 5] * 2 ** 8 + + this[offset + 6] * 2 ** 16 + + (last << 24) // Overflow + + return (BigInt(val) << BigInt(32)) + + BigInt(first + + this[++offset] * 2 ** 8 + + this[++offset] * 2 ** 16 + + this[++offset] * 2 ** 24) +}) + +Buffer.prototype.readBigInt64BE = defineBigIntMethod(function readBigInt64BE(offset) { + offset = offset >>> 0 + validateNumber(offset, 'offset') + const first = this[offset] + const last = this[offset + 7] + if (first === undefined || last === undefined) { + boundsError(offset, this.length - 8) + } + + const val = (first << 24) + // Overflow + this[++offset] * 2 ** 16 + + this[++offset] * 2 ** 8 + + this[++offset] + + return (BigInt(val) << BigInt(32)) + + BigInt(this[++offset] * 2 ** 24 + + this[++offset] * 2 ** 16 + + this[++offset] * 2 ** 8 + + last) +}) + +Buffer.prototype.readFloatLE = function readFloatLE(offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, true, 23, 4) +} + +Buffer.prototype.readFloatBE = function readFloatBE(offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, false, 23, 4) +} + +Buffer.prototype.readDoubleLE = function readDoubleLE(offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, true, 52, 8) +} + +Buffer.prototype.readDoubleBE = function readDoubleBE(offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, false, 52, 8) +} + +function checkInt(buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') + if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') + if (offset + ext > buf.length) throw new RangeError('Index out of range') +} + +Buffer.prototype.writeUintLE = + Buffer.prototype.writeUIntLE = function writeUIntLE(value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + const maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + let mul = 1 + let i = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength + } + +Buffer.prototype.writeUintBE = + Buffer.prototype.writeUIntBE = function writeUIntBE(value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + const maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + let i = byteLength - 1 + let mul = 1 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength + } + +Buffer.prototype.writeUint8 = + Buffer.prototype.writeUInt8 = function writeUInt8(value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) + this[offset] = (value & 0xff) + return offset + 1 + } + +Buffer.prototype.writeUint16LE = + Buffer.prototype.writeUInt16LE = function writeUInt16LE(value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + return offset + 2 + } + +Buffer.prototype.writeUint16BE = + Buffer.prototype.writeUInt16BE = function writeUInt16BE(value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + return offset + 2 + } + +Buffer.prototype.writeUint32LE = + Buffer.prototype.writeUInt32LE = function writeUInt32LE(value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = (value & 0xff) + return offset + 4 + } + +Buffer.prototype.writeUint32BE = + Buffer.prototype.writeUInt32BE = function writeUInt32BE(value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + return offset + 4 + } + +function wrtBigUInt64LE(buf, value, offset, min, max) { + checkIntBI(value, min, max, buf, offset, 7) + + let lo = Number(value & BigInt(0xffffffff)) + + buf[offset++] = lo + lo = lo >> 8 + buf[offset++] = lo + lo = lo >> 8 + buf[offset++] = lo + lo = lo >> 8 + buf[offset++] = lo + + let hi = Number(value >> (BigInt(32) & BigInt(0xffffffff))) + + buf[offset++] = hi + hi = hi >> 8 + buf[offset++] = hi + hi = hi >> 8 + buf[offset++] = hi + hi = hi >> 8 + buf[offset++] = hi + + return offset +} + +function wrtBigUInt64BE(buf, value, offset, min, max) { + checkIntBI(value, min, max, buf, offset, 7) + + let lo = Number(value & BigInt(0xffffffff)) + buf[offset + 7] = lo + lo = lo >> 8 + buf[offset + 6] = lo + lo = lo >> 8 + buf[offset + 5] = lo + lo = lo >> 8 + buf[offset + 4] = lo + let hi = Number(value >> (BigInt(32) & BigInt(0xffffffff))) + buf[offset + 3] = hi + hi = hi >> 8 + buf[offset + 2] = hi + hi = hi >> 8 + buf[offset + 1] = hi + hi = hi >> 8 + buf[offset] = hi + return offset + 8 +} + +Buffer.prototype.writeBigUInt64LE = defineBigIntMethod(function writeBigUInt64LE(value, offset = 0) { + return wrtBigUInt64LE(this, value, offset, BigInt(0), BigInt('0xffffffffffffffff')) +}) + +Buffer.prototype.writeBigUInt64BE = defineBigIntMethod(function writeBigUInt64BE(value, offset = 0) { + return wrtBigUInt64BE(this, value, offset, BigInt(0), BigInt('0xffffffffffffffff')) +}) + +Buffer.prototype.writeIntLE = function writeIntLE(value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + const limit = Math.pow(2, (8 * byteLength) - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + let i = 0 + let mul = 1 + let sub = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { + sub = 1 + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeIntBE = function writeIntBE(value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + const limit = Math.pow(2, (8 * byteLength) - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + let i = byteLength - 1 + let mul = 1 + let sub = 0 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { + sub = 1 + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeInt8 = function writeInt8(value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) + if (value < 0) value = 0xff + value + 1 + this[offset] = (value & 0xff) + return offset + 1 +} + +Buffer.prototype.writeInt16LE = function writeInt16LE(value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + return offset + 2 +} + +Buffer.prototype.writeInt16BE = function writeInt16BE(value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + return offset + 2 +} + +Buffer.prototype.writeInt32LE = function writeInt32LE(value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) + return offset + 4 +} + +Buffer.prototype.writeInt32BE = function writeInt32BE(value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (value < 0) value = 0xffffffff + value + 1 + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + return offset + 4 +} + +Buffer.prototype.writeBigInt64LE = defineBigIntMethod(function writeBigInt64LE(value, offset = 0) { + return wrtBigUInt64LE(this, value, offset, -BigInt('0x8000000000000000'), BigInt('0x7fffffffffffffff')) +}) + +Buffer.prototype.writeBigInt64BE = defineBigIntMethod(function writeBigInt64BE(value, offset = 0) { + return wrtBigUInt64BE(this, value, offset, -BigInt('0x8000000000000000'), BigInt('0x7fffffffffffffff')) +}) + +function checkIEEE754(buf, value, offset, ext, max, min) { + if (offset + ext > buf.length) throw new RangeError('Index out of range') + if (offset < 0) throw new RangeError('Index out of range') +} + +function writeFloat(buf, value, offset, littleEndian, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) + } + ieee754.write(buf, value, offset, littleEndian, 23, 4) + return offset + 4 +} + +Buffer.prototype.writeFloatLE = function writeFloatLE(value, offset, noAssert) { + return writeFloat(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeFloatBE = function writeFloatBE(value, offset, noAssert) { + return writeFloat(this, value, offset, false, noAssert) +} + +function writeDouble(buf, value, offset, littleEndian, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) + } + ieee754.write(buf, value, offset, littleEndian, 52, 8) + return offset + 8 +} + +Buffer.prototype.writeDoubleLE = function writeDoubleLE(value, offset, noAssert) { + return writeDouble(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeDoubleBE = function writeDoubleBE(value, offset, noAssert) { + return writeDouble(this, value, offset, false, noAssert) +} + +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function copy(target, targetStart, start, end) { + if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer') + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (targetStart >= target.length) targetStart = target.length + if (!targetStart) targetStart = 0 + if (end > 0 && end < start) end = start + + // Copy 0 bytes; we're done + if (end === start) return 0 + if (target.length === 0 || this.length === 0) return 0 + + // Fatal error conditions + if (targetStart < 0) { + throw new RangeError('targetStart out of bounds') + } + if (start < 0 || start >= this.length) throw new RangeError('Index out of range') + if (end < 0) throw new RangeError('sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) end = this.length + if (target.length - targetStart < end - start) { + end = target.length - targetStart + start + } + + const len = end - start + + if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') { + // Use built-in when available, missing from IE11 + this.copyWithin(targetStart, start, end) + } else { + Uint8Array.prototype.set.call( + target, + this.subarray(start, end), + targetStart + ) + } + + return len +} + +// Usage: +// buffer.fill(number[, offset[, end]]) +// buffer.fill(buffer[, offset[, end]]) +// buffer.fill(string[, offset[, end]][, encoding]) +Buffer.prototype.fill = function fill(val, start, end, encoding) { + // Handle string cases: + if (typeof val === 'string') { + if (typeof start === 'string') { + encoding = start + start = 0 + end = this.length + } else if (typeof end === 'string') { + encoding = end + end = this.length + } + if (encoding !== undefined && typeof encoding !== 'string') { + throw new TypeError('encoding must be a string') + } + if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding) + } + if (val.length === 1) { + const code = val.charCodeAt(0) + if ((encoding === 'utf8' && code < 128) || + encoding === 'latin1') { + // Fast path: If `val` fits into a single byte, use that numeric value. + val = code + } + } + } else if (typeof val === 'number') { + val = val & 255 + } else if (typeof val === 'boolean') { + val = Number(val) + } + + // Invalid ranges are not set to a default, so can range check early. + if (start < 0 || this.length < start || this.length < end) { + throw new RangeError('Out of range index') + } + + if (end <= start) { + return this + } + + start = start >>> 0 + end = end === undefined ? this.length : end >>> 0 + + if (!val) val = 0 + + let i + if (typeof val === 'number') { + for (i = start; i < end; ++i) { + this[i] = val + } + } else { + const bytes = Buffer.isBuffer(val) + ? val + : Buffer.from(val, encoding) + const len = bytes.length + if (len === 0) { + throw new TypeError('The value "' + val + + '" is invalid for argument "value"') + } + for (i = 0; i < end - start; ++i) { + this[i + start] = bytes[i % len] + } + } + + return this +} + +// CUSTOM ERRORS +// ============= + +// Simplified versions from Node, changed for Buffer-only usage +const errors = { } +function E(sym, getMessage, Base) { + errors[sym] = class NodeError extends Base { + constructor() { + super() + + Object.defineProperty(this, 'message', { + value: getMessage.apply(this, arguments), + writable: true, + configurable: true + }) + + // Add the error code to the name to include it in the stack trace. + this.name = `${this.name} [${sym}]` + // Access the stack to generate the error message including the error code + // from the name. + this.stack // eslint-disable-line no-unused-expressions + // Reset the name to the actual name. + delete this.name + } + + get code() { + return sym + } + + set code(value) { + Object.defineProperty(this, 'code', { + configurable: true, + enumerable: true, + value, + writable: true + }) + } + + toString() { + return `${this.name} [${sym}]: ${this.message}` + } + } +} + +E('ERR_BUFFER_OUT_OF_BOUNDS', + function (name) { + if (name) { + return `${name} is outside of buffer bounds` + } + + return 'Attempt to access memory outside buffer bounds' + }, RangeError) +E('ERR_INVALID_ARG_TYPE', + function (name, actual) { + return `The "${name}" argument must be of type number. Received type ${typeof actual}` + }, TypeError) +E('ERR_OUT_OF_RANGE', + function (str, range, input) { + let msg = `The value of "${str}" is out of range.` + let received = input + if (Number.isInteger(input) && Math.abs(input) > 2 ** 32) { + received = addNumericalSeparator(String(input)) + } else if (typeof input === 'bigint') { + received = String(input) + if (input > BigInt(2) ** BigInt(32) || input < -(BigInt(2) ** BigInt(32))) { + received = addNumericalSeparator(received) + } + received += 'n' + } + msg += ` It must be ${range}. Received ${received}` + return msg + }, RangeError) + +function addNumericalSeparator(val) { + let res = '' + let i = val.length + const start = val[0] === '-' ? 1 : 0 + for (; i >= start + 4; i -= 3) { + res = `_${val.slice(i - 3, i)}${res}` + } + return `${val.slice(0, i)}${res}` +} + +// CHECK FUNCTIONS +// =============== + +function checkBounds(buf, offset, byteLength) { + validateNumber(offset, 'offset') + if (buf[offset] === undefined || buf[offset + byteLength] === undefined) { + boundsError(offset, buf.length - (byteLength + 1)) + } +} + +function checkIntBI(value, min, max, buf, offset, byteLength) { + if (value > max || value < min) { + const n = typeof min === 'bigint' ? 'n' : '' + let range + if (byteLength > 3) { + if (min === 0 || min === BigInt(0)) { + range = `>= 0${n} and < 2${n} ** ${(byteLength + 1) * 8}${n}` + } else { + range = `>= -(2${n} ** ${(byteLength + 1) * 8 - 1}${n}) and < 2 ** ` + + `${(byteLength + 1) * 8 - 1}${n}` + } + } else { + range = `>= ${min}${n} and <= ${max}${n}` + } + throw new errors.ERR_OUT_OF_RANGE('value', range, value) + } + checkBounds(buf, offset, byteLength) +} + +function validateNumber(value, name) { + if (typeof value !== 'number') { + throw new errors.ERR_INVALID_ARG_TYPE(name, 'number', value) + } +} + +function boundsError(value, length, type) { + if (Math.floor(value) !== value) { + validateNumber(value, type) + throw new errors.ERR_OUT_OF_RANGE(type || 'offset', 'an integer', value) + } + + if (length < 0) { + throw new errors.ERR_BUFFER_OUT_OF_BOUNDS() + } + + throw new errors.ERR_OUT_OF_RANGE(type || 'offset', + `>= ${type ? 1 : 0} and <= ${length}`, + value) +} + +// HELPER FUNCTIONS +// ================ + +const INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g + +function base64clean(str) { + // Node takes equal signs as end of the Base64 encoding + str = str.split('=')[0] + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = str.trim().replace(INVALID_BASE64_RE, '') + // Node converts strings with length < 2 to '' + if (str.length < 2) return '' + // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + while (str.length % 4 !== 0) { + str = str + '=' + } + return str +} + +function utf8ToBytes(string, units) { + units = units || Infinity + let codePoint + const length = string.length + let leadSurrogate = null + const bytes = [] + + for (let i = 0; i < length; ++i) { + codePoint = string.charCodeAt(i) + + // is surrogate component + if (codePoint > 0xD7FF && codePoint < 0xE000) { + // last char was a lead + if (!leadSurrogate) { + // no lead yet + if (codePoint > 0xDBFF) { + // unexpected trail + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } else if (i + 1 === length) { + // unpaired lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } + + // valid lead + leadSurrogate = codePoint + + continue + } + + // 2 leads in a row + if (codePoint < 0xDC00) { + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + leadSurrogate = codePoint + continue + } + + // valid surrogate pair + codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 + } else if (leadSurrogate) { + // valid bmp char, but last char was a lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + } + + leadSurrogate = null + + // encode utf8 + if (codePoint < 0x80) { + if ((units -= 1) < 0) break + bytes.push(codePoint) + } else if (codePoint < 0x800) { + if ((units -= 2) < 0) break + bytes.push( + codePoint >> 0x6 | 0xC0, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x10000) { + if ((units -= 3) < 0) break + bytes.push( + codePoint >> 0xC | 0xE0, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x110000) { + if ((units -= 4) < 0) break + bytes.push( + codePoint >> 0x12 | 0xF0, + codePoint >> 0xC & 0x3F | 0x80, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else { + throw new Error('Invalid code point') + } + } + + return bytes +} + +function asciiToBytes(str) { + const byteArray = [] + for (let i = 0; i < str.length; ++i) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF) + } + return byteArray +} + +function utf16leToBytes(str, units) { + let c, hi, lo + const byteArray = [] + for (let i = 0; i < str.length; ++i) { + if ((units -= 2) < 0) break + + c = str.charCodeAt(i) + hi = c >> 8 + lo = c % 256 + byteArray.push(lo) + byteArray.push(hi) + } + + return byteArray +} + +function base64ToBytes(str) { + return base64.toByteArray(base64clean(str)) +} + +function blitBuffer(src, dst, offset, length) { + let i + for (i = 0; i < length; ++i) { + if ((i + offset >= dst.length) || (i >= src.length)) break + dst[i + offset] = src[i] + } + return i +} + +// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass +// the `instanceof` check but they should be treated as of that type. +// See: https://github.com/feross/buffer/issues/166 +function isInstance(obj, type) { + return obj instanceof type || + (obj != null && obj.constructor != null && obj.constructor.name != null && + obj.constructor.name === type.name) +} +function numberIsNaN(obj) { + // For IE11 support + return obj !== obj // eslint-disable-line no-self-compare +} + +// Create lookup table for `toString('hex')` +// See: https://github.com/feross/buffer/issues/219 +const hexSliceLookupTable = (function () { + const alphabet = '0123456789abcdef' + const table = new Array(256) + for (let i = 0; i < 16; ++i) { + const i16 = i * 16 + for (let j = 0; j < 16; ++j) { + table[i16 + j] = alphabet[i] + alphabet[j] + } + } + return table +})() + +// Return not function with Error if BigInt not supported +function defineBigIntMethod(fn) { + return typeof BigInt === 'undefined' ? BufferBigIntNotDefined : fn +} + +function BufferBigIntNotDefined() { + throw new Error('BigInt not supported') +} diff --git a/packages/vm/wasmlib/ts/wasmclient/buffer/readme.md b/packages/vm/wasmlib/ts/wasmclient/buffer/readme.md new file mode 100644 index 0000000000..0c78405f8c --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/buffer/readme.md @@ -0,0 +1,3 @@ +From https://github.com/feross/buffer/ + +Required minor changes to work with TypeScript properly and is not published yet. diff --git a/packages/vm/wasmlib/ts/wasmclient/clientfunc.ts b/packages/vm/wasmlib/ts/wasmclient/clientfunc.ts new file mode 100644 index 0000000000..06bb352dd9 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/clientfunc.ts @@ -0,0 +1,46 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import * as wasmclient from "./index"; +import { IKeyPair } from "./crypto"; + +export class ClientFunc { + protected svc: wasmclient.Service; + private keyPair: IKeyPair | null = null; + private onLedger: boolean = false; + private xfer: wasmclient.Transfer = new wasmclient.Transfer(); + + constructor(svc: wasmclient.Service) { + this.svc = svc; + } + + + // onLedger can override the default off-ledger to on-ledger posting + public onLedgerRequest(onLedger: boolean): void { + this.onLedger = onLedger; + } + + // Sends a request to the smart contract service + // You can wait for the request to complete by using the returned RequestID + // as parameter to Service.waitRequest() + public async post(hFuncName: wasmclient.Hname, args: wasmclient.Arguments | null): Promise { + if (!args) args = new wasmclient.Arguments(); + + if (!this.keyPair) this.keyPair = this.svc.keyPair; + + if (!this.keyPair) throw new Error("Key pair not defined"); + + return await this.svc.postRequest(hFuncName, args, this.xfer, this.keyPair, this.onLedger); + } + + // Optionally overrides the default keypair from the service + public sign(keyPair: IKeyPair): void { + this.keyPair = keyPair; + } + + // Optionally indicates which tokens to transfer as part of the request + // The tokens are presumed to be available in the signing account on the chain + public transfer(xfer: wasmclient.Transfer): void { + this.xfer = xfer; + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/clientview.ts b/packages/vm/wasmlib/ts/wasmclient/clientview.ts new file mode 100644 index 0000000000..22bf3f74e5 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/clientview.ts @@ -0,0 +1,19 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import * as wasmclient from "./index" + +export class ClientView { + private svc: wasmclient.Service; + + constructor(svc: wasmclient.Service) { + this.svc = svc; + } + + protected async callView(viewName: string, args: wasmclient.Arguments | null, res: wasmclient.Results): Promise { + if (args == null) { + args = new wasmclient.Arguments(); + } + await this.svc.callView(viewName, args, res); + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/colors.ts b/packages/vm/wasmlib/ts/wasmclient/colors.ts new file mode 100644 index 0000000000..475b229cb6 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/colors.ts @@ -0,0 +1,9 @@ +import { Buffer } from "./buffer"; + +export class Colors { + public static readonly IOTA_COLOR: string = "IOTA"; + public static readonly IOTA_COLOR_STRING: string = "11111111111111111111111111111111"; + public static readonly IOTA_COLOR_BYTES: Buffer = Buffer.alloc(32); +} + +export type ColorCollection = { [key: string]: bigint }; diff --git a/packages/vm/wasmlib/ts/wasmclient/configuration.ts b/packages/vm/wasmlib/ts/wasmclient/configuration.ts new file mode 100644 index 0000000000..4f25142a2f --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/configuration.ts @@ -0,0 +1,29 @@ +import { Buffer } from './buffer'; + +export interface IConfiguration { + seed: Buffer | null; + waspWebSocketUrl: string; + waspApiUrl: string; + goShimmerApiUrl: string; +} + +export class Configuration implements IConfiguration { + seed: Buffer | null = null; + waspWebSocketUrl: string = ''; + waspApiUrl: string = ''; + goShimmerApiUrl: string = ''; + chainId: string = ''; + + constructor(configuration: IConfiguration) { + if(!configuration) throw new Error("Configuration not defined"); + + this.seed = configuration.seed; + this.waspWebSocketUrl = configuration.waspWebSocketUrl; + this.waspApiUrl = configuration.waspApiUrl; + this.goShimmerApiUrl = configuration.goShimmerApiUrl; + } + + public toString = (): string => { + return `Configuration : { seed: ${this.seed}, waspWebSocketUrl : ${this.waspWebSocketUrl}, waspApiUrl : ${this.waspApiUrl}, goShimmerApiUrl : ${this.goShimmerApiUrl}, chainId : ${this.chainId}}`; + }; +} diff --git a/packages/vm/wasmlib/ts/wasmclient/coreaccounts/service.ts b/packages/vm/wasmlib/ts/wasmclient/coreaccounts/service.ts new file mode 100644 index 0000000000..a3a39405b0 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/coreaccounts/service.ts @@ -0,0 +1,190 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// (Re-)generated by schema tool +// >>>> DO NOT CHANGE THIS FILE! <<<< +// Change the json schema instead + +import * as wasmclient from "wasmclient" + +const ArgAgentID = "a"; +const ArgWithdrawAmount = "m"; +const ArgWithdrawColor = "c"; + +const ResAccountNonce = "n"; +const ResAgents = "this"; +const ResBalances = "this"; + +///////////////////////////// deposit ///////////////////////////// + +export class DepositFunc extends wasmclient.ClientFunc { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public agentID(v: wasmclient.AgentID): void { + this.args.set(ArgAgentID, this.args.fromAgentID(v)); + } + + public async post(): Promise { + return await super.post(0xbdc9102d, this.args); + } +} + +///////////////////////////// harvest ///////////////////////////// + +export class HarvestFunc extends wasmclient.ClientFunc { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public withdrawAmount(v: wasmclient.Int64): void { + this.args.set(ArgWithdrawAmount, this.args.fromInt64(v)); + } + + public withdrawColor(v: wasmclient.Color): void { + this.args.set(ArgWithdrawColor, this.args.fromColor(v)); + } + + public async post(): Promise { + return await super.post(0x7b40efbd, this.args); + } +} + +///////////////////////////// withdraw ///////////////////////////// + +export class WithdrawFunc extends wasmclient.ClientFunc { + + public async post(): Promise { + return await super.post(0x9dcc0f41, null); + } +} + +///////////////////////////// accounts ///////////////////////////// + +export class AccountsView extends wasmclient.ClientView { + + public async call(): Promise { + const res = new AccountsResults(); + await this.callView("accounts", null, res); + return res; + } +} + +export class AccountsResults extends wasmclient.Results { + + agents(): Map { + const res = new Map(); + this.forEach((key, val) => { + res.set(this.toAgentID(key), this.toBytes(val)); + }); + return res; + } +} + +///////////////////////////// balance ///////////////////////////// + +export class BalanceView extends wasmclient.ClientView { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public agentID(v: wasmclient.AgentID): void { + this.args.set(ArgAgentID, this.args.fromAgentID(v)); + } + + public async call(): Promise { + this.args.mandatory(ArgAgentID); + const res = new BalanceResults(); + await this.callView("balance", this.args, res); + return res; + } +} + +export class BalanceResults extends wasmclient.Results { + + balances(): Map { + const res = new Map(); + this.forEach((key, val) => { + res.set(this.toColor(key), this.toInt64(val)); + }); + return res; + } +} + +///////////////////////////// getAccountNonce ///////////////////////////// + +export class GetAccountNonceView extends wasmclient.ClientView { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public agentID(v: wasmclient.AgentID): void { + this.args.set(ArgAgentID, this.args.fromAgentID(v)); + } + + public async call(): Promise { + this.args.mandatory(ArgAgentID); + const res = new GetAccountNonceResults(); + await this.callView("getAccountNonce", this.args, res); + return res; + } +} + +export class GetAccountNonceResults extends wasmclient.Results { + + accountNonce(): wasmclient.Int64 { + return this.toInt64(this.get(ResAccountNonce)); + } +} + +///////////////////////////// totalAssets ///////////////////////////// + +export class TotalAssetsView extends wasmclient.ClientView { + + public async call(): Promise { + const res = new TotalAssetsResults(); + await this.callView("totalAssets", null, res); + return res; + } +} + +export class TotalAssetsResults extends wasmclient.Results { + + balances(): Map { + const res = new Map(); + this.forEach((key, val) => { + res.set(this.toColor(key), this.toInt64(val)); + }); + return res; + } +} + +///////////////////////////// CoreAccountsService ///////////////////////////// + +export class CoreAccountsService extends wasmclient.Service { + + public constructor(cl: wasmclient.ServiceClient) { + super(cl, 0x3c4b5e02, new Map()); + } + + public deposit(): DepositFunc { + return new DepositFunc(this); + } + + public harvest(): HarvestFunc { + return new HarvestFunc(this); + } + + public withdraw(): WithdrawFunc { + return new WithdrawFunc(this); + } + + public accounts(): AccountsView { + return new AccountsView(this); + } + + public balance(): BalanceView { + return new BalanceView(this); + } + + public getAccountNonce(): GetAccountNonceView { + return new GetAccountNonceView(this); + } + + public totalAssets(): TotalAssetsView { + return new TotalAssetsView(this); + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/coreblob/service.ts b/packages/vm/wasmlib/ts/wasmclient/coreblob/service.ts new file mode 100644 index 0000000000..265fe35f9e --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/coreblob/service.ts @@ -0,0 +1,141 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// (Re-)generated by schema tool +// >>>> DO NOT CHANGE THIS FILE! <<<< +// Change the json schema instead + +import * as wasmclient from "wasmclient" + +const ArgBlobs = "this"; +const ArgField = "field"; +const ArgHash = "hash"; + +const ResBlobSizes = "this"; +const ResBytes = "bytes"; +const ResHash = "hash"; + +///////////////////////////// storeBlob ///////////////////////////// + +export class StoreBlobFunc extends wasmclient.ClientFunc { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public blobs(v: wasmclient.Bytes): void { + this.args.set(ArgBlobs, this.args.fromBytes(v)); + } + + public async post(): Promise { + return await super.post(0xddd4c281, this.args); + } +} + +export class StoreBlobResults extends wasmclient.Results { + + hash(): wasmclient.Hash { + return this.toHash(this.get(ResHash)); + } +} + +///////////////////////////// getBlobField ///////////////////////////// + +export class GetBlobFieldView extends wasmclient.ClientView { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public field(v: string): void { + this.args.set(ArgField, this.args.fromString(v)); + } + + public hash(v: wasmclient.Hash): void { + this.args.set(ArgHash, this.args.fromHash(v)); + } + + public async call(): Promise { + this.args.mandatory(ArgField); + this.args.mandatory(ArgHash); + const res = new GetBlobFieldResults(); + await this.callView("getBlobField", this.args, res); + return res; + } +} + +export class GetBlobFieldResults extends wasmclient.Results { + + bytes(): wasmclient.Bytes { + return this.toBytes(this.get(ResBytes)); + } +} + +///////////////////////////// getBlobInfo ///////////////////////////// + +export class GetBlobInfoView extends wasmclient.ClientView { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public hash(v: wasmclient.Hash): void { + this.args.set(ArgHash, this.args.fromHash(v)); + } + + public async call(): Promise { + this.args.mandatory(ArgHash); + const res = new GetBlobInfoResults(); + await this.callView("getBlobInfo", this.args, res); + return res; + } +} + +export class GetBlobInfoResults extends wasmclient.Results { + + blobSizes(): Map { + const res = new Map(); + this.forEach((key, val) => { + res.set(this.toString(key), this.toInt32(val)); + }); + return res; + } +} + +///////////////////////////// listBlobs ///////////////////////////// + +export class ListBlobsView extends wasmclient.ClientView { + + public async call(): Promise { + const res = new ListBlobsResults(); + await this.callView("listBlobs", null, res); + return res; + } +} + +export class ListBlobsResults extends wasmclient.Results { + + blobSizes(): Map { + const res = new Map(); + this.forEach((key, val) => { + res.set(this.toHash(key), this.toInt32(val)); + }); + return res; + } +} + +///////////////////////////// CoreBlobService ///////////////////////////// + +export class CoreBlobService extends wasmclient.Service { + + public constructor(cl: wasmclient.ServiceClient) { + super(cl, 0xfd91bc63, new Map()); + } + + public storeBlob(): StoreBlobFunc { + return new StoreBlobFunc(this); + } + + public getBlobField(): GetBlobFieldView { + return new GetBlobFieldView(this); + } + + public getBlobInfo(): GetBlobInfoView { + return new GetBlobInfoView(this); + } + + public listBlobs(): ListBlobsView { + return new ListBlobsView(this); + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/coreblocklog/service.ts b/packages/vm/wasmlib/ts/wasmclient/coreblocklog/service.ts new file mode 100644 index 0000000000..abe2db5dc9 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/coreblocklog/service.ts @@ -0,0 +1,329 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// (Re-)generated by schema tool +// >>>> DO NOT CHANGE THIS FILE! <<<< +// Change the json schema instead + +import * as wasmclient from "wasmclient" + +const ArgBlockIndex = "n"; +const ArgContractHname = "h"; +const ArgFromBlock = "f"; +const ArgRequestID = "u"; +const ArgToBlock = "t"; + +const ResBlockIndex = "n"; +const ResBlockInfo = "i"; +const ResEvent = "e"; +const ResGoverningAddress = "g"; +const ResRequestID = "u"; +const ResRequestIndex = "r"; +const ResRequestProcessed = "p"; +const ResRequestRecord = "d"; +const ResStateControllerAddress = "s"; + +///////////////////////////// controlAddresses ///////////////////////////// + +export class ControlAddressesView extends wasmclient.ClientView { + + public async call(): Promise { + const res = new ControlAddressesResults(); + await this.callView("controlAddresses", null, res); + return res; + } +} + +export class ControlAddressesResults extends wasmclient.Results { + + blockIndex(): wasmclient.Int32 { + return this.toInt32(this.get(ResBlockIndex)); + } + + governingAddress(): wasmclient.Address { + return this.toAddress(this.get(ResGoverningAddress)); + } + + stateControllerAddress(): wasmclient.Address { + return this.toAddress(this.get(ResStateControllerAddress)); + } +} + +///////////////////////////// getBlockInfo ///////////////////////////// + +export class GetBlockInfoView extends wasmclient.ClientView { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public blockIndex(v: wasmclient.Int32): void { + this.args.set(ArgBlockIndex, this.args.fromInt32(v)); + } + + public async call(): Promise { + this.args.mandatory(ArgBlockIndex); + const res = new GetBlockInfoResults(); + await this.callView("getBlockInfo", this.args, res); + return res; + } +} + +export class GetBlockInfoResults extends wasmclient.Results { + + blockInfo(): wasmclient.Bytes { + return this.toBytes(this.get(ResBlockInfo)); + } +} + +///////////////////////////// getEventsForBlock ///////////////////////////// + +export class GetEventsForBlockView extends wasmclient.ClientView { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public blockIndex(v: wasmclient.Int32): void { + this.args.set(ArgBlockIndex, this.args.fromInt32(v)); + } + + public async call(): Promise { + this.args.mandatory(ArgBlockIndex); + const res = new GetEventsForBlockResults(); + await this.callView("getEventsForBlock", this.args, res); + return res; + } +} + +export class GetEventsForBlockResults extends wasmclient.Results { + + event(): wasmclient.Bytes { + return this.toBytes(this.get(ResEvent)); + } +} + +///////////////////////////// getEventsForContract ///////////////////////////// + +export class GetEventsForContractView extends wasmclient.ClientView { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public contractHname(v: wasmclient.Hname): void { + this.args.set(ArgContractHname, this.args.fromHname(v)); + } + + public fromBlock(v: wasmclient.Int32): void { + this.args.set(ArgFromBlock, this.args.fromInt32(v)); + } + + public toBlock(v: wasmclient.Int32): void { + this.args.set(ArgToBlock, this.args.fromInt32(v)); + } + + public async call(): Promise { + this.args.mandatory(ArgContractHname); + const res = new GetEventsForContractResults(); + await this.callView("getEventsForContract", this.args, res); + return res; + } +} + +export class GetEventsForContractResults extends wasmclient.Results { + + event(): wasmclient.Bytes { + return this.toBytes(this.get(ResEvent)); + } +} + +///////////////////////////// getEventsForRequest ///////////////////////////// + +export class GetEventsForRequestView extends wasmclient.ClientView { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public requestID(v: wasmclient.RequestID): void { + this.args.set(ArgRequestID, this.args.fromRequestID(v)); + } + + public async call(): Promise { + this.args.mandatory(ArgRequestID); + const res = new GetEventsForRequestResults(); + await this.callView("getEventsForRequest", this.args, res); + return res; + } +} + +export class GetEventsForRequestResults extends wasmclient.Results { + + event(): wasmclient.Bytes { + return this.toBytes(this.get(ResEvent)); + } +} + +///////////////////////////// getLatestBlockInfo ///////////////////////////// + +export class GetLatestBlockInfoView extends wasmclient.ClientView { + + public async call(): Promise { + const res = new GetLatestBlockInfoResults(); + await this.callView("getLatestBlockInfo", null, res); + return res; + } +} + +export class GetLatestBlockInfoResults extends wasmclient.Results { + + blockIndex(): wasmclient.Int32 { + return this.toInt32(this.get(ResBlockIndex)); + } + + blockInfo(): wasmclient.Bytes { + return this.toBytes(this.get(ResBlockInfo)); + } +} + +///////////////////////////// getRequestIDsForBlock ///////////////////////////// + +export class GetRequestIDsForBlockView extends wasmclient.ClientView { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public blockIndex(v: wasmclient.Int32): void { + this.args.set(ArgBlockIndex, this.args.fromInt32(v)); + } + + public async call(): Promise { + this.args.mandatory(ArgBlockIndex); + const res = new GetRequestIDsForBlockResults(); + await this.callView("getRequestIDsForBlock", this.args, res); + return res; + } +} + +export class GetRequestIDsForBlockResults extends wasmclient.Results { + + requestID(): wasmclient.RequestID { + return this.toRequestID(this.get(ResRequestID)); + } +} + +///////////////////////////// getRequestReceipt ///////////////////////////// + +export class GetRequestReceiptView extends wasmclient.ClientView { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public requestID(v: wasmclient.RequestID): void { + this.args.set(ArgRequestID, this.args.fromRequestID(v)); + } + + public async call(): Promise { + this.args.mandatory(ArgRequestID); + const res = new GetRequestReceiptResults(); + await this.callView("getRequestReceipt", this.args, res); + return res; + } +} + +export class GetRequestReceiptResults extends wasmclient.Results { + + blockIndex(): wasmclient.Int32 { + return this.toInt32(this.get(ResBlockIndex)); + } + + requestIndex(): wasmclient.Int16 { + return this.toInt16(this.get(ResRequestIndex)); + } + + requestRecord(): wasmclient.Bytes { + return this.toBytes(this.get(ResRequestRecord)); + } +} + +///////////////////////////// getRequestReceiptsForBlock ///////////////////////////// + +export class GetRequestReceiptsForBlockView extends wasmclient.ClientView { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public blockIndex(v: wasmclient.Int32): void { + this.args.set(ArgBlockIndex, this.args.fromInt32(v)); + } + + public async call(): Promise { + this.args.mandatory(ArgBlockIndex); + const res = new GetRequestReceiptsForBlockResults(); + await this.callView("getRequestReceiptsForBlock", this.args, res); + return res; + } +} + +export class GetRequestReceiptsForBlockResults extends wasmclient.Results { + + requestRecord(): wasmclient.Bytes { + return this.toBytes(this.get(ResRequestRecord)); + } +} + +///////////////////////////// isRequestProcessed ///////////////////////////// + +export class IsRequestProcessedView extends wasmclient.ClientView { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public requestID(v: wasmclient.RequestID): void { + this.args.set(ArgRequestID, this.args.fromRequestID(v)); + } + + public async call(): Promise { + this.args.mandatory(ArgRequestID); + const res = new IsRequestProcessedResults(); + await this.callView("isRequestProcessed", this.args, res); + return res; + } +} + +export class IsRequestProcessedResults extends wasmclient.Results { + + requestProcessed(): string { + return this.toString(this.get(ResRequestProcessed)); + } +} + +///////////////////////////// CoreBlockLogService ///////////////////////////// + +export class CoreBlockLogService extends wasmclient.Service { + + public constructor(cl: wasmclient.ServiceClient) { + super(cl, 0xf538ef2b, new Map()); + } + + public controlAddresses(): ControlAddressesView { + return new ControlAddressesView(this); + } + + public getBlockInfo(): GetBlockInfoView { + return new GetBlockInfoView(this); + } + + public getEventsForBlock(): GetEventsForBlockView { + return new GetEventsForBlockView(this); + } + + public getEventsForContract(): GetEventsForContractView { + return new GetEventsForContractView(this); + } + + public getEventsForRequest(): GetEventsForRequestView { + return new GetEventsForRequestView(this); + } + + public getLatestBlockInfo(): GetLatestBlockInfoView { + return new GetLatestBlockInfoView(this); + } + + public getRequestIDsForBlock(): GetRequestIDsForBlockView { + return new GetRequestIDsForBlockView(this); + } + + public getRequestReceipt(): GetRequestReceiptView { + return new GetRequestReceiptView(this); + } + + public getRequestReceiptsForBlock(): GetRequestReceiptsForBlockView { + return new GetRequestReceiptsForBlockView(this); + } + + public isRequestProcessed(): IsRequestProcessedView { + return new IsRequestProcessedView(this); + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/coregovernance/service.ts b/packages/vm/wasmlib/ts/wasmclient/coregovernance/service.ts new file mode 100644 index 0000000000..f30da2d644 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/coregovernance/service.ts @@ -0,0 +1,355 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// (Re-)generated by schema tool +// >>>> DO NOT CHANGE THIS FILE! <<<< +// Change the json schema instead + +import * as wasmclient from "wasmclient" + +const ArgChainOwner = "oi"; +const ArgFeeColor = "fc"; +const ArgHname = "hn"; +const ArgMaxBlobSize = "bs"; +const ArgMaxEventSize = "es"; +const ArgMaxEventsPerReq = "ne"; +const ArgOwnerFee = "of"; +const ArgStateControllerAddress = "S"; +const ArgValidatorFee = "vf"; + +const ResAllowedStateControllerAddresses = "a"; +const ResChainID = "c"; +const ResChainOwnerID = "o"; +const ResDefaultOwnerFee = "do"; +const ResDefaultValidatorFee = "dv"; +const ResDescription = "d"; +const ResFeeColor = "f"; +const ResMaxBlobSize = "mb"; +const ResMaxEventSize = "me"; +const ResMaxEventsPerReq = "mr"; +const ResOwnerFee = "of"; +const ResValidatorFee = "vf"; + +///////////////////////////// addAllowedStateControllerAddress ///////////////////////////// + +export class AddAllowedStateControllerAddressFunc extends wasmclient.ClientFunc { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public chainOwner(v: wasmclient.AgentID): void { + this.args.set(ArgChainOwner, this.args.fromAgentID(v)); + } + + public feeColor(v: wasmclient.Color): void { + this.args.set(ArgFeeColor, this.args.fromColor(v)); + } + + public stateControllerAddress(v: wasmclient.Address): void { + this.args.set(ArgStateControllerAddress, this.args.fromAddress(v)); + } + + public async post(): Promise { + this.args.mandatory(ArgChainOwner); + this.args.mandatory(ArgStateControllerAddress); + return await super.post(0x9469d567, this.args); + } +} + +///////////////////////////// claimChainOwnership ///////////////////////////// + +export class ClaimChainOwnershipFunc extends wasmclient.ClientFunc { + + public async post(): Promise { + return await super.post(0x03ff0fc0, null); + } +} + +///////////////////////////// delegateChainOwnership ///////////////////////////// + +export class DelegateChainOwnershipFunc extends wasmclient.ClientFunc { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public chainOwner(v: wasmclient.AgentID): void { + this.args.set(ArgChainOwner, this.args.fromAgentID(v)); + } + + public async post(): Promise { + this.args.mandatory(ArgChainOwner); + return await super.post(0x93ecb6ad, this.args); + } +} + +///////////////////////////// removeAllowedStateControllerAddress ///////////////////////////// + +export class RemoveAllowedStateControllerAddressFunc extends wasmclient.ClientFunc { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public stateControllerAddress(v: wasmclient.Address): void { + this.args.set(ArgStateControllerAddress, this.args.fromAddress(v)); + } + + public async post(): Promise { + this.args.mandatory(ArgStateControllerAddress); + return await super.post(0x31f69447, this.args); + } +} + +///////////////////////////// rotateStateController ///////////////////////////// + +export class RotateStateControllerFunc extends wasmclient.ClientFunc { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public stateControllerAddress(v: wasmclient.Address): void { + this.args.set(ArgStateControllerAddress, this.args.fromAddress(v)); + } + + public async post(): Promise { + this.args.mandatory(ArgStateControllerAddress); + return await super.post(0x244d1038, this.args); + } +} + +///////////////////////////// setChainInfo ///////////////////////////// + +export class SetChainInfoFunc extends wasmclient.ClientFunc { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public maxBlobSize(v: wasmclient.Int32): void { + this.args.set(ArgMaxBlobSize, this.args.fromInt32(v)); + } + + public maxEventSize(v: wasmclient.Int16): void { + this.args.set(ArgMaxEventSize, this.args.fromInt16(v)); + } + + public maxEventsPerReq(v: wasmclient.Int16): void { + this.args.set(ArgMaxEventsPerReq, this.args.fromInt16(v)); + } + + public ownerFee(v: wasmclient.Int64): void { + this.args.set(ArgOwnerFee, this.args.fromInt64(v)); + } + + public validatorFee(v: wasmclient.Int64): void { + this.args.set(ArgValidatorFee, this.args.fromInt64(v)); + } + + public async post(): Promise { + return await super.post(0x702f5d2b, this.args); + } +} + +///////////////////////////// setContractFee ///////////////////////////// + +export class SetContractFeeFunc extends wasmclient.ClientFunc { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public hname(v: wasmclient.Hname): void { + this.args.set(ArgHname, this.args.fromHname(v)); + } + + public ownerFee(v: wasmclient.Int64): void { + this.args.set(ArgOwnerFee, this.args.fromInt64(v)); + } + + public validatorFee(v: wasmclient.Int64): void { + this.args.set(ArgValidatorFee, this.args.fromInt64(v)); + } + + public async post(): Promise { + this.args.mandatory(ArgHname); + return await super.post(0x8421a42b, this.args); + } +} + +///////////////////////////// setDefaultFee ///////////////////////////// + +export class SetDefaultFeeFunc extends wasmclient.ClientFunc { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public ownerFee(v: wasmclient.Int64): void { + this.args.set(ArgOwnerFee, this.args.fromInt64(v)); + } + + public validatorFee(v: wasmclient.Int64): void { + this.args.set(ArgValidatorFee, this.args.fromInt64(v)); + } + + public async post(): Promise { + return await super.post(0x3310ecd0, this.args); + } +} + +///////////////////////////// getAllowedStateControllerAddresses ///////////////////////////// + +export class GetAllowedStateControllerAddressesView extends wasmclient.ClientView { + + public async call(): Promise { + const res = new GetAllowedStateControllerAddressesResults(); + await this.callView("getAllowedStateControllerAddresses", null, res); + return res; + } +} + +export class GetAllowedStateControllerAddressesResults extends wasmclient.Results { + + allowedStateControllerAddresses(): wasmclient.Bytes { + return this.toBytes(this.get(ResAllowedStateControllerAddresses)); + } +} + +///////////////////////////// getChainInfo ///////////////////////////// + +export class GetChainInfoView extends wasmclient.ClientView { + + public async call(): Promise { + const res = new GetChainInfoResults(); + await this.callView("getChainInfo", null, res); + return res; + } +} + +export class GetChainInfoResults extends wasmclient.Results { + + chainID(): wasmclient.ChainID { + return this.toChainID(this.get(ResChainID)); + } + + chainOwnerID(): wasmclient.AgentID { + return this.toAgentID(this.get(ResChainOwnerID)); + } + + defaultOwnerFee(): wasmclient.Int64 { + return this.toInt64(this.get(ResDefaultOwnerFee)); + } + + defaultValidatorFee(): wasmclient.Int64 { + return this.toInt64(this.get(ResDefaultValidatorFee)); + } + + description(): string { + return this.toString(this.get(ResDescription)); + } + + feeColor(): wasmclient.Color { + return this.toColor(this.get(ResFeeColor)); + } + + maxBlobSize(): wasmclient.Int32 { + return this.toInt32(this.get(ResMaxBlobSize)); + } + + maxEventSize(): wasmclient.Int16 { + return this.toInt16(this.get(ResMaxEventSize)); + } + + maxEventsPerReq(): wasmclient.Int16 { + return this.toInt16(this.get(ResMaxEventsPerReq)); + } +} + +///////////////////////////// getFeeInfo ///////////////////////////// + +export class GetFeeInfoView extends wasmclient.ClientView { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public hname(v: wasmclient.Hname): void { + this.args.set(ArgHname, this.args.fromHname(v)); + } + + public async call(): Promise { + this.args.mandatory(ArgHname); + const res = new GetFeeInfoResults(); + await this.callView("getFeeInfo", this.args, res); + return res; + } +} + +export class GetFeeInfoResults extends wasmclient.Results { + + feeColor(): wasmclient.Color { + return this.toColor(this.get(ResFeeColor)); + } + + ownerFee(): wasmclient.Int64 { + return this.toInt64(this.get(ResOwnerFee)); + } + + validatorFee(): wasmclient.Int64 { + return this.toInt64(this.get(ResValidatorFee)); + } +} + +///////////////////////////// getMaxBlobSize ///////////////////////////// + +export class GetMaxBlobSizeView extends wasmclient.ClientView { + + public async call(): Promise { + const res = new GetMaxBlobSizeResults(); + await this.callView("getMaxBlobSize", null, res); + return res; + } +} + +export class GetMaxBlobSizeResults extends wasmclient.Results { + + maxBlobSize(): wasmclient.Int32 { + return this.toInt32(this.get(ResMaxBlobSize)); + } +} + +///////////////////////////// CoreGovernanceService ///////////////////////////// + +export class CoreGovernanceService extends wasmclient.Service { + + public constructor(cl: wasmclient.ServiceClient) { + super(cl, 0x17cf909f, new Map()); + } + + public addAllowedStateControllerAddress(): AddAllowedStateControllerAddressFunc { + return new AddAllowedStateControllerAddressFunc(this); + } + + public claimChainOwnership(): ClaimChainOwnershipFunc { + return new ClaimChainOwnershipFunc(this); + } + + public delegateChainOwnership(): DelegateChainOwnershipFunc { + return new DelegateChainOwnershipFunc(this); + } + + public removeAllowedStateControllerAddress(): RemoveAllowedStateControllerAddressFunc { + return new RemoveAllowedStateControllerAddressFunc(this); + } + + public rotateStateController(): RotateStateControllerFunc { + return new RotateStateControllerFunc(this); + } + + public setChainInfo(): SetChainInfoFunc { + return new SetChainInfoFunc(this); + } + + public setContractFee(): SetContractFeeFunc { + return new SetContractFeeFunc(this); + } + + public setDefaultFee(): SetDefaultFeeFunc { + return new SetDefaultFeeFunc(this); + } + + public getAllowedStateControllerAddresses(): GetAllowedStateControllerAddressesView { + return new GetAllowedStateControllerAddressesView(this); + } + + public getChainInfo(): GetChainInfoView { + return new GetChainInfoView(this); + } + + public getFeeInfo(): GetFeeInfoView { + return new GetFeeInfoView(this); + } + + public getMaxBlobSize(): GetMaxBlobSizeView { + return new GetMaxBlobSizeView(this); + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/coreroot/service.ts b/packages/vm/wasmlib/ts/wasmclient/coreroot/service.ts new file mode 100644 index 0000000000..b00ab43f67 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/coreroot/service.ts @@ -0,0 +1,151 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// (Re-)generated by schema tool +// >>>> DO NOT CHANGE THIS FILE! <<<< +// Change the json schema instead + +import * as wasmclient from "wasmclient" + +const ArgDeployer = "dp"; +const ArgDescription = "ds"; +const ArgHname = "hn"; +const ArgName = "nm"; +const ArgProgramHash = "ph"; + +const ResContractFound = "cf"; +const ResContractRecData = "dt"; +const ResContractRegistry = "r"; + +///////////////////////////// deployContract ///////////////////////////// + +export class DeployContractFunc extends wasmclient.ClientFunc { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public description(v: string): void { + this.args.set(ArgDescription, this.args.fromString(v)); + } + + public name(v: string): void { + this.args.set(ArgName, this.args.fromString(v)); + } + + public programHash(v: wasmclient.Hash): void { + this.args.set(ArgProgramHash, this.args.fromHash(v)); + } + + public async post(): Promise { + this.args.mandatory(ArgName); + this.args.mandatory(ArgProgramHash); + return await super.post(0x28232c27, this.args); + } +} + +///////////////////////////// grantDeployPermission ///////////////////////////// + +export class GrantDeployPermissionFunc extends wasmclient.ClientFunc { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public deployer(v: wasmclient.AgentID): void { + this.args.set(ArgDeployer, this.args.fromAgentID(v)); + } + + public async post(): Promise { + this.args.mandatory(ArgDeployer); + return await super.post(0xf440263a, this.args); + } +} + +///////////////////////////// revokeDeployPermission ///////////////////////////// + +export class RevokeDeployPermissionFunc extends wasmclient.ClientFunc { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public deployer(v: wasmclient.AgentID): void { + this.args.set(ArgDeployer, this.args.fromAgentID(v)); + } + + public async post(): Promise { + this.args.mandatory(ArgDeployer); + return await super.post(0x850744f1, this.args); + } +} + +///////////////////////////// findContract ///////////////////////////// + +export class FindContractView extends wasmclient.ClientView { + private args: wasmclient.Arguments = new wasmclient.Arguments(); + + public hname(v: wasmclient.Hname): void { + this.args.set(ArgHname, this.args.fromHname(v)); + } + + public async call(): Promise { + this.args.mandatory(ArgHname); + const res = new FindContractResults(); + await this.callView("findContract", this.args, res); + return res; + } +} + +export class FindContractResults extends wasmclient.Results { + + contractFound(): wasmclient.Bytes { + return this.toBytes(this.get(ResContractFound)); + } + + contractRecData(): wasmclient.Bytes { + return this.toBytes(this.get(ResContractRecData)); + } +} + +///////////////////////////// getContractRecords ///////////////////////////// + +export class GetContractRecordsView extends wasmclient.ClientView { + + public async call(): Promise { + const res = new GetContractRecordsResults(); + await this.callView("getContractRecords", null, res); + return res; + } +} + +export class GetContractRecordsResults extends wasmclient.Results { + + contractRegistry(): Map { + const res = new Map(); + this.forEach((key, val) => { + res.set(this.toHname(key), this.toBytes(val)); + }); + return res; + } +} + +///////////////////////////// CoreRootService ///////////////////////////// + +export class CoreRootService extends wasmclient.Service { + + public constructor(cl: wasmclient.ServiceClient) { + super(cl, 0xcebf5908, new Map()); + } + + public deployContract(): DeployContractFunc { + return new DeployContractFunc(this); + } + + public grantDeployPermission(): GrantDeployPermissionFunc { + return new GrantDeployPermissionFunc(this); + } + + public revokeDeployPermission(): RevokeDeployPermissionFunc { + return new RevokeDeployPermissionFunc(this); + } + + public findContract(): FindContractView { + return new FindContractView(this); + } + + public getContractRecords(): GetContractRecordsView { + return new GetContractRecordsView(this); + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/crypto/base58.ts b/packages/vm/wasmlib/ts/wasmclient/crypto/base58.ts new file mode 100644 index 0000000000..fdb2dd5943 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/crypto/base58.ts @@ -0,0 +1,144 @@ +import { Buffer } from '../buffer'; + +export class Base58 { + private static readonly ALPHABET: string = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; + private static readonly ALPHABET_MAP: { [id: string]: number } = {}; + + /** + * Encode a buffer to base58. + * @param buffer The buffer to encode as base 58. + * @returns The encoded data as a string. + */ + public static encode(buffer: Buffer): string { + if (!buffer || buffer.length == 0) { + return ''; + } + let i = 0; + let j; + let carry; + const digits = [0]; + while (i < buffer.length) { + j = 0; + while (j < digits.length) { + digits[j] <<= 8; + j++; + } + digits[0] += buffer[i]; + carry = 0; + j = 0; + while (j < digits.length) { + digits[j] += carry; + carry = (digits[j] / 58) | 0; + digits[j] %= 58; + ++j; + } + while (carry) { + digits.push(carry % 58); + carry = (carry / 58) | 0; + } + i++; + } + i = 0; + while (buffer[i] == 0 && i < buffer.length - 1) { + digits.push(0); + i++; + } + return digits + .reverse() + .map((digit) => { + return Base58.ALPHABET[digit]; + }) + .join(''); + } + + /** + * Decode a base58 string to a buffer. + * @param encoded The buffer to encode as base 58. + * @returns The encoded data as a string. + */ + public static decode(encoded: string): Buffer { + if (!encoded || encoded.length == 0) { + return Buffer.from(''); + } + Base58.buildMap(); + const bytes = [0]; + let i = 0; + while (i < encoded.length) { + const c = encoded[i]; + if (!(c in Base58.ALPHABET_MAP)) { + throw new Error(`Character '${c}' is not in the Base58 alphabet.`); + } + let j = 0; + while (j < bytes.length) { + bytes[j] *= 58; + j++; + } + bytes[0] += Base58.ALPHABET_MAP[c]; + let carry = 0; + j = 0; + while (j < bytes.length) { + bytes[j] += carry; + carry = bytes[j] >> 8; + bytes[j] &= 0xff; + ++j; + } + while (carry) { + bytes.push(carry & 0xff); + carry >>= 8; + } + i++; + } + i = 0; + while (encoded[i] == '1' && i < encoded.length - 1) { + bytes.push(0); + i++; + } + return Buffer.from(bytes.reverse()); + } + + /** + * Is the encoded string valid base58. + * @param encoded The encoded string as base 58. + * @returns True is the characters are valid. + */ + public static isValid(encoded?: string): boolean { + if (!encoded) { + return false; + } + Base58.buildMap(); + for (const ch of encoded) { + if (!(ch in Base58.ALPHABET_MAP)) { + return false; + } + } + return true; + } + + /** + * Concatenate 2 base58 strings. + * @param id1 The first id. + * @param id2 The second id. + * @returns The concatenated ids. + */ + public static concat(id1: string, id2: string): string { + const b1 = Base58.decode(id1); + const b2 = Base58.decode(id2); + const combined = Buffer.alloc(b1.length + b2.length); + combined.set(b1, 0); + combined.set(b2, b1.length); + return Base58.encode(combined); + } + + /** + * Build the reverse lookup map. + */ + private static buildMap(): void { + if (Object.keys(Base58.ALPHABET_MAP).length == 0) { + let i = 0; + while (i < Base58.ALPHABET.length) { + Base58.ALPHABET_MAP[Base58.ALPHABET.charAt(i)] = i; + i++; + } + } + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/crypto/ed25519.ts b/packages/vm/wasmlib/ts/wasmclient/crypto/ed25519.ts new file mode 100644 index 0000000000..f4e58ac567 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/crypto/ed25519.ts @@ -0,0 +1,78 @@ +import nacl from "tweetnacl"; +import { AgentID } from ".."; +import { Buffer } from "../buffer"; +import { Base58 } from "./base58"; +import { Hash } from "./hash"; +import { Seed } from "./seed"; + +export interface IKeyPair { + publicKey: Buffer; + secretKey: Buffer; +} + +/** + * Calculates the AgentID for the key pair's address. + * @param keyPair The key pair used to get the address and calculate the AgentID. + * @returns AgentID. + */ + export function getAgentId(keyPair: IKeyPair) : AgentID { + const address = getAddress(keyPair); + const addressBuffer = Base58.decode(address); + const hNameBuffer = Buffer.alloc(4); + const agentIdBuffer = Buffer.concat([addressBuffer,hNameBuffer]); + const agentId = Base58.encode(agentIdBuffer); + return agentId; +} + +/** + * Calculates the address for key pair + * @param keyPair The key pair used to calculate the address + * @returns The generated address. + */ + export function getAddress(keyPair: IKeyPair): string { + const publicKeyBuffer = Buffer.from(keyPair.publicKey); + return getAddressFromPublicKeyBuffer(publicKeyBuffer); +} + +export function getAddressFromPublicKeyBuffer(publicKeyBuffer: Buffer): string { + const digest = Hash.from(publicKeyBuffer); + + const buffer = Buffer.alloc(Seed.SEED_SIZE + 1); + buffer[0] = ED25519.VERSION; + Buffer.from(digest).copy(buffer, 1); + + return Base58.encode(buffer); +} + +/** + * Class to help with ED25519 Signature scheme. + */ +export class ED25519 { + public static VERSION: number = 0; + public static PUBLIC_KEY_SIZE: number = 32; + public static SIGNATURE_SIZE: number = 64; + + /** + * Generate a key pair from the seed. + * @param seed The seed to generate the key pair from. + * @returns The key pair. + */ + public static keyPairFromSeed(seed: Buffer): IKeyPair { + const signKeyPair = nacl.sign.keyPair.fromSeed(seed); + + return { + publicKey: Buffer.from(signKeyPair.publicKey), + secretKey: Buffer.from(signKeyPair.secretKey), + }; + } + + /** + * Privately sign the data. + * @param keyPair The key pair to sign with. + * @param buffer The data to sign. + * @returns The signature. + */ + public static privateSign(keyPair: IKeyPair, buffer: Buffer): Buffer { + return Buffer.from(nacl.sign.detached(buffer, keyPair.secretKey)); + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/crypto/hash.ts b/packages/vm/wasmlib/ts/wasmclient/crypto/hash.ts new file mode 100644 index 0000000000..fd29d3d50a --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/crypto/hash.ts @@ -0,0 +1,9 @@ +import {blake2b} from 'blakejs'; +import {Buffer} from '../buffer'; + +export class Hash { + public static from(bytes: Buffer): Buffer { + // @ts-ignore + return blake2b(bytes, undefined, 32 /* Blake256 */); + } +} \ No newline at end of file diff --git a/packages/vm/wasmlib/ts/wasmclient/crypto/index.ts b/packages/vm/wasmlib/ts/wasmclient/crypto/index.ts new file mode 100644 index 0000000000..1a3d9fa59e --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/crypto/index.ts @@ -0,0 +1,6 @@ +// @index('./*.ts', f => `export * from '${f.path}'`) +export * from "./base58"; +export * from "./ed25519"; +export * from "./hash"; +export * from "./seed"; +// @endindex diff --git a/packages/vm/wasmlib/ts/wasmclient/crypto/seed.ts b/packages/vm/wasmlib/ts/wasmclient/crypto/seed.ts new file mode 100644 index 0000000000..3654f66792 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/crypto/seed.ts @@ -0,0 +1,89 @@ +import { Base58 } from './base58'; +import { Buffer } from '../buffer'; +import { ED25519, getAddressFromPublicKeyBuffer, IKeyPair } from './ed25519'; +import { Hash } from './hash'; + +export class Seed { + /** + * SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032. + */ + public static SEED_SIZE: number = 32; + + /** + * Generate a new seed. + * @returns The random seed. + */ + public static generate(): Buffer { + const cryptoObj: Crypto = window.crypto; + const array = new Uint32Array(Seed.SEED_SIZE); + + cryptoObj.getRandomValues(array); + + return Buffer.from(array); + } + + /** + * Generate the nth subseed. + * @param seed The seed to generate from. + * @param index The index of the subseed to generate. + * @returns The subseed. + */ + public static subseed(seed: Buffer, index: number): Buffer { + const indexBytes = Buffer.alloc(8); + indexBytes.writeBigUInt64LE(BigInt(index), 0); + const subseed = Buffer.alloc(this.SEED_SIZE); + const hashOfPaddedBuffer = Hash.from(indexBytes); + + Seed.xorBytes(seed, Buffer.from(hashOfPaddedBuffer), subseed); + return subseed; + } + + /** + * Is the string a valid seed. + * @param seed The seed to check. + * @returns True is the seed is valid. + */ + public static isValid(seed?: string): boolean { + if (!seed) { + return false; + } + if (!Base58.isValid(seed)) { + return false; + } + return Base58.decode(seed).length == Seed.SEED_SIZE; + } + + /** + * Generate a key pair for the seed index. + * @param seed The seed. + * @param index The index of the address to generate. + * @returns The generated address key pair. + */ + public static generateKeyPair(seed: Buffer, index: number): IKeyPair { + const subSeed = Seed.subseed(seed, index); + return ED25519.keyPairFromSeed(subSeed); + } + + /** + * Generate an address for the seed. + * @param seed The seed. + * @param index The index of the address to generate. + * @returns The generated address. + */ + public static generateAddress(seed: Buffer, index: number): string { + const { publicKey: publicKeyBuffer } = Seed.generateKeyPair(seed, index); + return getAddressFromPublicKeyBuffer(publicKeyBuffer); + } + + /** + * XOR the two input buffers into the output. + * @param srcA The first source buffer. + * @param srcB The second source buffer, + * @param dest The destination buffer. + */ + private static xorBytes(srcA: Buffer, srcB: Buffer, dest: Buffer): void { + for (let i = 0; i < srcA.byteLength; i++) { + dest.writeUInt8(srcA.readUInt8(i) ^ srcB.readUInt8(i), i); + } + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/decoder.ts b/packages/vm/wasmlib/ts/wasmclient/decoder.ts new file mode 100644 index 0000000000..c83f5a9e64 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/decoder.ts @@ -0,0 +1,98 @@ +// The Results struct is used to gather all arguments for a smart +// contract function call and encode it into a deterministic byte array +import * as wasmclient from "./index"; +import {Base58} from "./crypto"; +import {Buffer} from "./buffer"; + +export class Decoder { + private static checkDefault(bytes: Buffer | undefined, typeID: wasmclient.Int32): Buffer { + const size = wasmclient.TYPE_SIZES[typeID]; + if (bytes === undefined) { + return Buffer.alloc(size); + } + if (size != 0 && bytes.length != size) { + wasmclient.panic("invalid type size"); + } + return bytes; + } + + private static toBase58(bytes: Buffer | undefined, typeID: wasmclient.Int32): string { + return Base58.encode(Decoder.checkDefault(bytes, typeID)); + } + + protected toAddress(bytes: Buffer | undefined): wasmclient.Address { + return Decoder.toBase58(bytes, wasmclient.TYPE_ADDRESS); + } + + protected toAgentID(bytes: Buffer | undefined): wasmclient.AgentID { + return Decoder.toBase58(bytes, wasmclient.TYPE_AGENT_ID); + } + + protected toBytes(bytes: Buffer | undefined): wasmclient.Bytes { + return Decoder.checkDefault(bytes, wasmclient.TYPE_BYTES) + } + + protected toBool(bytes: Buffer | undefined): wasmclient.Bool { + return Decoder.checkDefault(bytes, wasmclient.TYPE_BOOL)[0] != 0; + } + + protected toChainID(bytes: Buffer | undefined): wasmclient.ChainID { + return Decoder.toBase58(bytes, wasmclient.TYPE_CHAIN_ID); + } + + protected toColor(bytes: Buffer | undefined): wasmclient.Color { + let color = Decoder.toBase58(bytes, wasmclient.TYPE_COLOR); + if (color == "11111111111111111111111111111111") { + color = "IOTA"; + } + return color; + } + + protected toHash(bytes: Buffer | undefined): wasmclient.Hash { + return Decoder.toBase58(bytes, wasmclient.TYPE_HASH); + } + + protected toHname(bytes: Buffer | undefined): wasmclient.Hname { + return Decoder.checkDefault(bytes, wasmclient.TYPE_HNAME).readUInt32LE(0); + } + + protected toInt8(bytes: Buffer | undefined): wasmclient.Int8 { + return Decoder.checkDefault(bytes, wasmclient.TYPE_INT8).readInt8(0); + } + + protected toInt16(bytes: Buffer | undefined): wasmclient.Int16 { + return Decoder.checkDefault(bytes, wasmclient.TYPE_INT16).readInt16LE(0); + } + + protected toInt32(bytes: Buffer | undefined): wasmclient.Int32 { + return Decoder.checkDefault(bytes, wasmclient.TYPE_INT32).readInt32LE(0); + } + + protected toInt64(bytes: Buffer | undefined): wasmclient.Int64 { + return Decoder.checkDefault(bytes, wasmclient.TYPE_INT64).readBigInt64LE(0); + } + + protected toRequestID(bytes: Buffer | undefined): wasmclient.RequestID { + return Decoder.toBase58(bytes, wasmclient.TYPE_REQUEST_ID); + } + + protected toString(bytes: Buffer | undefined): wasmclient.String { + return Decoder.checkDefault(bytes, wasmclient.TYPE_STRING).toString(); + } + + protected toUint8(bytes: Buffer | undefined): wasmclient.Uint8 { + return Decoder.checkDefault(bytes, wasmclient.TYPE_INT8).readUInt8(0); + } + + protected toUint16(bytes: Buffer | undefined): wasmclient.Uint16 { + return Decoder.checkDefault(bytes, wasmclient.TYPE_INT16).readUInt16LE(0); + } + + protected toUint32(bytes: Buffer | undefined): wasmclient.Uint32 { + return Decoder.checkDefault(bytes, wasmclient.TYPE_INT32).readUInt32LE(0); + } + + protected toUint64(bytes: Buffer | undefined): wasmclient.Uint64 { + return Decoder.checkDefault(bytes, wasmclient.TYPE_INT64).readBigUInt64LE(0); + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/encoder.ts b/packages/vm/wasmlib/ts/wasmclient/encoder.ts new file mode 100644 index 0000000000..8fba1473fe --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/encoder.ts @@ -0,0 +1,113 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import * as wasmclient from "./index" +import {Base58} from "./crypto"; +import {Buffer} from "./buffer"; + +// The Arguments struct is used to gather all arguments for this smart +// contract function call and encode it into this deterministic byte array +export class Encoder { + private fromBase58(val: string, typeID: wasmclient.Int32): Buffer { + const bytes = Base58.decode(val); + if (bytes.length != wasmclient.TYPE_SIZES[typeID]) { + wasmclient.panic("invalid byte size"); + } + return bytes; + } + + fromAddress(val: wasmclient.AgentID): Buffer { + return this.fromBase58(val, wasmclient.TYPE_ADDRESS); + } + + fromAgentID(val: wasmclient.AgentID): Buffer { + return this.fromBase58(val, wasmclient.TYPE_AGENT_ID); + } + + fromBool(val: boolean): Buffer { + const bytes = Buffer.alloc(1); + if (val) { + bytes.writeUInt8(1, 0); + } + return bytes; + } + + fromBytes(val: wasmclient.Bytes): Buffer { + return val; + } + + fromChainID(val: wasmclient.ChainID): Buffer { + return this.fromBase58(val, wasmclient.TYPE_CHAIN_ID); + } + + fromColor(val: wasmclient.Color): Buffer { + if (val == "IOTA") { + val = "11111111111111111111111111111111"; + } + return this.fromBase58(val, wasmclient.TYPE_COLOR); + } + + fromHash(val: wasmclient.Hash): Buffer { + return this.fromBase58(val, wasmclient.TYPE_HASH); + } + + fromHname(val: wasmclient.Hname): Buffer { + return this.fromUint32(val); + } + + fromInt8(val: wasmclient.Int8): Buffer { + const bytes = Buffer.alloc(1); + bytes.writeInt8(val, 0); + return bytes; + } + + fromInt16(val: wasmclient.Int16): Buffer { + const bytes = Buffer.alloc(2); + bytes.writeInt16LE(val, 0); + return bytes; + } + + fromInt32(val: wasmclient.Int32): Buffer { + const bytes = Buffer.alloc(4); + bytes.writeInt32LE(val, 0); + return bytes; + } + + fromInt64(val: wasmclient.Int64): Buffer { + const bytes = Buffer.alloc(8); + bytes.writeBigInt64LE(val, 0); + return bytes; + } + + fromRequestID(val: wasmclient.RequestID): Buffer { + return this.fromBase58(val, wasmclient.TYPE_REQUEST_ID); + } + + fromString(val: string): Buffer { + return Buffer.from(val); + } + + fromUint8(val: wasmclient.Uint8): Buffer { + const bytes = Buffer.alloc(1); + bytes.writeUInt8(val, 0); + return bytes; + } + + fromUint16(val: wasmclient.Uint16): Buffer { + const bytes = Buffer.alloc(2); + bytes.writeUInt16LE(val, 0); + return bytes; + } + + fromUint32(val: wasmclient.Uint32): Buffer { + const bytes = Buffer.alloc(4); + bytes.writeUInt32LE(val, 0); + return bytes; + } + + fromUint64(val: wasmclient.Uint64): Buffer { + const bytes = Buffer.alloc(8); + bytes.writeBigUInt64LE(val, 0); + return bytes; + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/event.ts b/packages/vm/wasmlib/ts/wasmclient/event.ts new file mode 100644 index 0000000000..f23c08220f --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/event.ts @@ -0,0 +1,92 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import * as wasmclient from "./index" +import {Base58} from "./crypto"; + +export class Event { + private index = 0; + private readonly msg: string[]; + public readonly timestamp: wasmclient.Int32; + + protected constructor(msg: string[]) { + this.msg = msg; + this.timestamp = Number(this.next()); + } + + private next(): string { + return this.msg[this.index++]; + } + + protected nextAddress(): wasmclient.Address { + return this.next(); + } + + protected nextAgentID(): wasmclient.AgentID { + return this.next(); + } + + protected nextBool(): wasmclient.Bool { + return this.next() != "0"; + } + + protected nextBytes(): wasmclient.Bytes { + return Base58.decode(this.next()); + } + + protected nextChainID(): wasmclient.ChainID { + return this.next(); + } + + protected nextColor(): wasmclient.Color { + return this.next(); + } + + protected nextHash(): wasmclient.Hash { + return this.next(); + } + + protected nextHname(): wasmclient.Hname { + return Number(this.next()); + } + + protected nextInt8(): wasmclient.Int8 { + return Number(this.next()); + } + + protected nextInt16(): wasmclient.Int16 { + return Number(this.next()); + } + + protected nextInt32(): wasmclient.Int32 { + return Number(this.next()); + } + + protected nextInt64(): wasmclient.Int64 { + return BigInt(this.next()); + } + + protected nextRequestID(): wasmclient.RequestID { + return this.next(); + } + + protected nextString(): string { + return this.next(); + } + + protected nextUint8(): wasmclient.Uint8 { + return Number(this.next()); + } + + protected nextUint16(): wasmclient.Uint16 { + return Number(this.next()); + } + + protected nextUint32(): wasmclient.Uint32 { + return Number(this.next()); + } + + protected nextUint64(): wasmclient.Uint64 { + return BigInt(this.next()); + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/goshimmer/faucet/faucet_helper.ts b/packages/vm/wasmlib/ts/wasmclient/goshimmer/faucet/faucet_helper.ts new file mode 100644 index 0000000000..bda8a9582c --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/goshimmer/faucet/faucet_helper.ts @@ -0,0 +1,30 @@ +import { Buffer } from '../../buffer'; +import { Base58 } from '../../crypto'; +import { IFaucetRequest } from './faucet_models'; + +export class FaucetHelper { + public static ToBuffer(faucetRequest: IFaucetRequest): Buffer { + const buffers = []; + + const payloadLen = Buffer.alloc(4); + payloadLen.writeUInt32LE(109, 0); + buffers.push(payloadLen); + + const faucetRequestType = Buffer.alloc(4); + faucetRequestType.writeUInt32LE(2, 0); + buffers.push(faucetRequestType); + + const addressBytes = Base58.decode(faucetRequest.address); + buffers.push(addressBytes); + + const aManaPledgeBytes = Base58.decode(faucetRequest.accessManaPledgeID); + buffers.push(aManaPledgeBytes); + + const cManaPledgeBytes = Base58.decode(faucetRequest.consensusManaPledgeID); + buffers.push(cManaPledgeBytes); + + const data = Buffer.concat(buffers); + + return data; + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/goshimmer/faucet/faucet_models.ts b/packages/vm/wasmlib/ts/wasmclient/goshimmer/faucet/faucet_models.ts new file mode 100644 index 0000000000..9da4521dbc --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/goshimmer/faucet/faucet_models.ts @@ -0,0 +1,18 @@ +import type { IResponse } from '../../api_common/response_models'; +import { Buffer } from '../../buffer'; + +export interface IFaucetRequest { + accessManaPledgeID: string; + consensusManaPledgeID: string; + address: string; + nonce: number; +} + +export interface IFaucetResponse extends IResponse { + id?: string; +} + +export interface IFaucetRequestContext { + faucetRequest: IFaucetRequest; + poWBuffer: Buffer; +} diff --git a/packages/vm/wasmlib/ts/wasmclient/goshimmer/goshimmerclient.ts b/packages/vm/wasmlib/ts/wasmclient/goshimmer/goshimmerclient.ts new file mode 100644 index 0000000000..48aeb971e4 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/goshimmer/goshimmerclient.ts @@ -0,0 +1,182 @@ +import { Buffer } from "../buffer"; + +import { IFaucetRequest, IFaucetRequestContext, IFaucetResponse } from "./faucet/faucet_models"; +import { FaucetHelper } from "./faucet/faucet_helper"; + +import { IUnspentOutputsRequest, IUnspentOutputsResponse } from "./models/unspent_outputs"; +import { IAllowedManaPledgeResponse } from "./models/mana"; + +import { PoWWorkerManager } from "./pow_web_worker/pow_worker_manager"; + +import * as requestSender from "../api_common/request_sender"; + +import { Base58, getAddress, IKeyPair } from "../crypto"; + +import { IOnLedger, OnLedgerHelper } from "./models/on_ledger"; +import { ISendTransactionRequest, ISendTransactionResponse, ITransaction, Transaction } from "./models/transaction"; +import { Wallet } from "./wallet/wallet"; +import { Colors } from "../colors"; +import { AgentID, Configuration, Transfer } from ".."; +import { CoreAccountsService } from "../coreaccounts/service"; + +interface GoShimmerClientConfiguration { + APIUrl: string; + SeedUnsafe: Buffer | null; +} + +export class GoShimmerClient { + private coreAccountsService: CoreAccountsService; + private readonly goShimmerConfiguration: GoShimmerClientConfiguration; + private readonly powManager: PoWWorkerManager = new PoWWorkerManager(); + + constructor(configuration : Configuration, coreAccountsService: CoreAccountsService) { + this.coreAccountsService = coreAccountsService; + this.goShimmerConfiguration = { APIUrl: configuration.goShimmerApiUrl, SeedUnsafe: configuration.seed }; + } + + public async getIOTABalance(address: string): Promise { + const iotaBalance = await this.getBalance(address, Colors.IOTA_COLOR_STRING); + return iotaBalance; + } + + private async getBalance(address: string, color: string): Promise { + if (color == Colors.IOTA_COLOR) { + color = Colors.IOTA_COLOR_STRING; + } + + const unspents = await this.unspentOutputs({ addresses: [address] }); + const currentUnspent = unspents.unspentOutputs.find((x) => x.address.base58 == address); + + const balance = currentUnspent!.outputs + .filter( + (o) => + ["ExtendedLockedOutputType", "SigLockedColoredOutputType"].includes(o.output.type) && + typeof o.output.output.balances[color] != "undefined" + ) + .map((uid) => uid.output.output.balances) + .reduce((balance: bigint, output) => (balance += BigInt(output[color])), BigInt(0)); + + return balance; + } + + public async unspentOutputs(request: IUnspentOutputsRequest): Promise { + return requestSender.sendRequest( + this.goShimmerConfiguration.APIUrl, + "post", + "ledgerstate/addresses/unspentOutputs", + request + ); + } + + public async requestFunds(address: string): Promise { + try { + const faucetRequestContext = await this.getFaucetRequest(address); + const response = await this.sendFaucetRequest(faucetRequestContext.faucetRequest); + const success = response.error === undefined && response.id !== undefined; + return success; + } catch (ex: unknown) { + const error = ex as Error; + console.error(error.message); + return false; + } + } + + private async getFaucetRequest(address: string): Promise { + const manaPledge = await this.getAllowedManaPledge(); + + const allowedManagePledge = manaPledge.accessMana?.allowed ? manaPledge.accessMana.allowed[0] : ""; + const consenseusManaPledge = manaPledge.consensusMana?.allowed ? manaPledge.consensusMana?.allowed[0] : ""; + + const body: IFaucetRequest = { + accessManaPledgeID: allowedManagePledge, + consensusManaPledgeID: consenseusManaPledge, + address: address, + nonce: -1, + }; + + const poWBuffer = FaucetHelper.ToBuffer(body); + + body.nonce = await this.powManager.requestProofOfWork(12, poWBuffer); + + const result: IFaucetRequestContext = { + poWBuffer: poWBuffer, + faucetRequest: body, + }; + + return result; + } + + private async getAllowedManaPledge(): Promise { + return requestSender.sendRequest(this.goShimmerConfiguration.APIUrl, "get", "mana/allowedManaPledge"); + } + + private async sendFaucetRequest(faucetRequest: IFaucetRequest): Promise { + const response = await requestSender.sendRequest( + this.goShimmerConfiguration.APIUrl, + "post", + "faucet", + faucetRequest + ); + return response; + } + + public async postOnLedgerRequest( + chainId: string, + payload: IOnLedger, + transfer: bigint = 1n, + keyPair: IKeyPair + ): Promise { + if (transfer <= 0) { + transfer = 1n; + } + + const wallet = new Wallet(this); + + const address = getAddress(keyPair); + const unspents = await wallet.getUnspentOutputs(address); + const consumedOutputs = wallet.determineOutputsToConsume(unspents, transfer); + const { inputs, consumedFunds } = wallet.buildInputs(consumedOutputs); + const outputs = wallet.buildOutputs(address, chainId, transfer, consumedFunds); + + const tx: ITransaction = { + version: 0, + timestamp: BigInt(Date.now()) * 1000000n, + aManaPledge: Base58.encode(Buffer.alloc(32)), + cManaPledge: Base58.encode(Buffer.alloc(32)), + inputs: inputs, + outputs: outputs, + chainId: chainId, + payload: OnLedgerHelper.ToBuffer(payload), + unlockBlocks: [], + }; + + tx.unlockBlocks = wallet.unlockBlocks(tx, keyPair, address, consumedOutputs, inputs); + + const result = Transaction.bytes(tx); + + const response = await this.sendTransaction({ + txn_bytes: result.toString("base64"), + }); + + if (!response || response.error != undefined) throw Error("Transaction error: " + response.error); + return response?.transaction_id ?? ""; + } + + private async sendTransaction(request: ISendTransactionRequest): Promise { + return requestSender.sendRequest( + this.goShimmerConfiguration.APIUrl, + "post", + "ledgerstate/transactions", + request + ); + } + + public async depositIOTAToAccountInChain(keypair: IKeyPair, destinationAgentID: AgentID, amount: bigint) { + const depositfunc = this.coreAccountsService.deposit(); + depositfunc.agentID(destinationAgentID); + depositfunc.transfer(Transfer.iotas(amount)); + depositfunc.sign(keypair); + depositfunc.onLedgerRequest(true); + await depositfunc.post(); + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/goshimmer/models/mana.ts b/packages/vm/wasmlib/ts/wasmclient/goshimmer/models/mana.ts new file mode 100644 index 0000000000..786cd44507 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/goshimmer/models/mana.ts @@ -0,0 +1,13 @@ +import type { IResponse } from '../../api_common/response_models'; + +export interface IAllowedManaPledgeResponse extends IResponse { + accessMana: { + isFilterEnabled: boolean; + allowed?: Array; + }; + + consensusMana: { + isFilterEnabled: boolean; + allowed?: Array; + }; +} diff --git a/packages/vm/wasmlib/ts/wasmclient/goshimmer/models/on_ledger.ts b/packages/vm/wasmlib/ts/wasmclient/goshimmer/models/on_ledger.ts new file mode 100644 index 0000000000..6dead8f361 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/goshimmer/models/on_ledger.ts @@ -0,0 +1,45 @@ +import { Buffer } from "../../buffer"; +import { SimpleBufferCursor } from "../utils/simple_buffer_cursor"; + +export interface OnLedgerArgument { + key: string; + value: number; +} + +export interface IOnLedger { + contract?: number; + entrypoint?: number; + arguments?: OnLedgerArgument[]; + nonce?: number; +} + +export class OnLedgerHelper { + public static ToBuffer(req: IOnLedger): Buffer { + const buffer = new SimpleBufferCursor(Buffer.alloc(0)); + + buffer.writeUInt32LE(0); + buffer.writeUInt32LE(req.contract || 0); + buffer.writeUInt32LE(req.entrypoint || 0); + buffer.writeBytes(Buffer.alloc(1, 0)); + + buffer.writeUInt32LE(req.arguments?.length || 0); + + if (req.arguments) { + req.arguments.sort((lhs, rhs) => lhs.key.localeCompare(rhs.key)); + for (const arg of req.arguments) { + const keyBuffer = Buffer.from(arg.key); + + buffer.writeUInt16LE(keyBuffer.length); + buffer.writeBytes(keyBuffer); + + const valueBuffer = Buffer.alloc(8); + valueBuffer.writeInt32LE(arg.value, 0); + + buffer.writeUInt32LE(valueBuffer.length); + buffer.writeBytes(valueBuffer); + } + } + + return buffer.buffer; + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/goshimmer/models/transaction.ts b/packages/vm/wasmlib/ts/wasmclient/goshimmer/models/transaction.ts new file mode 100644 index 0000000000..479b745f3d --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/goshimmer/models/transaction.ts @@ -0,0 +1,182 @@ +import { Buffer } from "../../buffer"; +import { SimpleBufferCursor } from "../utils/simple_buffer_cursor"; +import { Base58, IKeyPair, ED25519 } from "../../crypto"; + +import type { BuiltOutputResult } from "../wallet/wallet"; + +import { IResponse } from "../../api_common/response_models"; +import { Colors } from "../../colors"; + +export interface ISendTransactionRequest { + txn_bytes: string; +} + +export interface ISendTransactionResponse extends IResponse { + transaction_id?: string; +} + +export interface IUnlockBlock { + type: number; + referenceIndex: number; + publicKey: Buffer; + signature: Buffer; +} + +export interface ITransaction { + /** + * The transaction's version. + */ + version: number; + + /** + * The transaction's timestamp. + */ + timestamp: bigint; + + /** + * The nodeID to pledge access mana. + */ + aManaPledge: string; + + /** + * The nodeID to pledge consensus mana. + */ + cManaPledge: string; + + /** + * The inputs to send. + */ + inputs: string[]; + + payload: Buffer; + + chainId: string; + /** + * The outputs to send. + */ + outputs: BuiltOutputResult; + + /** + * The signatures to send. + */ + unlockBlocks: IUnlockBlock[]; +} + +/** + * Class to help with transactions. + */ +export class Transaction { + /** + * Sign a transaction. + * @param keyPair The key pair to sign with. + * @param buffer The data to sign. + * @returns The signature. + */ + public static sign(keyPair: IKeyPair, buffer: Buffer): Buffer { + return ED25519.privateSign(keyPair, buffer); + } + + /** + * Get the essence for a transaction. + * @param tx The tx to get the essence for. + * @returns The essence of the transaction. + */ + public static essence(tx: ITransaction, payload: Buffer = Buffer.alloc(0)): Buffer { + const essenceBuffer = new SimpleBufferCursor(); + + essenceBuffer.writeInt8(tx.version); + essenceBuffer.writeUInt64LE(tx.timestamp); + essenceBuffer.writeBytes(Base58.decode(tx.aManaPledge)); + essenceBuffer.writeBytes(Base58.decode(tx.cManaPledge)); + + essenceBuffer.writeUInt16LE(tx.inputs.length); + for (const input of tx.inputs) { + essenceBuffer.writeInt8(0); + const decodedInput = Base58.decode(input); + essenceBuffer.writeBytes(decodedInput); + } + + essenceBuffer.writeUInt16LE(Object.keys(tx.outputs).length); + + const outputBuffers: SimpleBufferCursor[] = []; + + for (const address in tx.outputs) { + const outputBuffer = new SimpleBufferCursor(); + + outputBuffer.writeInt8(3); + outputBuffer.writeUInt32LE(tx.outputs[address].length); + + const bufferColors: Buffer[] = []; + + for (const balance of tx.outputs[address]) { + const colorValueBuffer = Buffer.alloc(8); + colorValueBuffer.writeBigUInt64LE(balance.value, 0); + bufferColors.push(Buffer.concat([Colors.IOTA_COLOR_BYTES, colorValueBuffer])); + } + + bufferColors.sort((a, b) => a.compare(b)); + bufferColors.forEach((x) => outputBuffer.writeBytes(x)); + + const decodedAddress = Base58.decode(address); + outputBuffer.writeBytes(decodedAddress); + + if (address == tx.chainId) { + outputBuffer.writeInt8(4); + outputBuffer.writeUInt16LE(tx.payload.length); + outputBuffer.writeBytes(tx.payload); + } else { + outputBuffer.writeInt8(0); + } + + outputBuffers.push(outputBuffer); + } + + outputBuffers.sort((a, b) => a.buffer.compare(b.buffer)); + outputBuffers.forEach((x) => essenceBuffer.writeBytes(x.buffer)); + + essenceBuffer.writeUInt32LE(0); + + return essenceBuffer.buffer; + } + + /** + * Get the bytes for a transaction. + * @param tx The tx to get the bytes for. + * @param essence Existing essence. + * @returns The bytes of the transaction. + */ + public static bytes(tx: ITransaction): Buffer { + const buffer = new SimpleBufferCursor(); + + buffer.writeUInt32LE(1337); + + const essenceBytes = Transaction.essence(tx); + buffer.writeBytes(essenceBytes); + buffer.writeUInt16LE(tx.unlockBlocks.length); + + // TODO: Update this in the next refactoring. + // eslint-disable-next-line @typescript-eslint/no-for-in-array + for (const index in tx.unlockBlocks) { + const ubType = tx.unlockBlocks[index].type; + + buffer.writeInt8(ubType); + + if (ubType === 0) { + buffer.writeInt8(0); + buffer.writeBytes(tx.unlockBlocks[index].publicKey); + buffer.writeBytes(tx.unlockBlocks[index].signature); + + continue; + } + + buffer.writeUInt16LE(tx.unlockBlocks[index].referenceIndex); + } + + const returnBuffer = new SimpleBufferCursor(); + + returnBuffer.writeUInt32LE(buffer.buffer.length); + returnBuffer.writeBytes(buffer.buffer); + + return returnBuffer.buffer; + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/goshimmer/models/unspent_outputs.ts b/packages/vm/wasmlib/ts/wasmclient/goshimmer/models/unspent_outputs.ts new file mode 100644 index 0000000000..1dc53d9243 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/goshimmer/models/unspent_outputs.ts @@ -0,0 +1,68 @@ +import type { IResponse } from '../../api_common/response_models'; +import { ColorCollection } from '../../colors'; + +export interface IUnspentOutputsRequest { + addresses: string[]; +} + +export interface IUnspentOutput { + outputID: { + base58: string; + transactionID: string; + outputIndex: number; + }; + + type: string; + + output: { + balances: { + [color: string]: bigint; + }; + + address: string; + }; + + inclusionState: { + confirmed?: boolean; + rejected?: boolean; + conflicting?: boolean; + }; +} + +export interface IUnspentOutputAddress { + type: string; + base58: string; +} + +export interface IUnspentOutputMap { + address: string; + outputs: { + id: string; + balances: ColorCollection; + inclusionState: { + confirmed?: boolean; + rejected?: boolean; + conflicting?: boolean; + }; + }[]; +} + +export interface IUnspentOutputsResponse extends IResponse { + unspentOutputs: { + address: IUnspentOutputAddress; + outputs: { + output: IUnspentOutput; + + inclusionState: { + confirmed?: boolean; + rejected?: boolean; + conflicting?: boolean; + }; + }[]; + }[]; +} + +export interface ISingleUnspentOutputResponse extends IResponse { + address: IUnspentOutputAddress; + outputs: IUnspentOutput[]; +} diff --git a/packages/vm/wasmlib/ts/wasmclient/goshimmer/pow_web_worker/pow.worker.ts b/packages/vm/wasmlib/ts/wasmclient/goshimmer/pow_web_worker/pow.worker.ts new file mode 100644 index 0000000000..6d2f4bfd01 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/goshimmer/pow_web_worker/pow.worker.ts @@ -0,0 +1,21 @@ +import ProofOfWork from './proof_of_work'; +import type { PowWorkerRequest, PowWorkerResponse } from './pow_worker_manager'; + +const ctx: Worker = self as never; + +ctx.onmessage = (e) => { + const message: PowWorkerRequest = e.data; + if (message.type != 'pow_request') return; + + try { + console.log(`[${message.uuid}] Starting PoW!`); + const nonce = ProofOfWork.calculateProofOfWork(message.difficulty, message.data); + console.log(`[${message.uuid}] PoW Done!`); + + const response: PowWorkerResponse = { type: 'pow_response', data: nonce, uuid: message.uuid }; + ctx.postMessage(response); + } catch (ex) { + ctx.postMessage({ type: 'pow_response', error: ex, uuid: message.uuid }); + console.error('PoW failed!'); + } +}; diff --git a/packages/vm/wasmlib/ts/wasmclient/goshimmer/pow_web_worker/pow_worker_manager.ts b/packages/vm/wasmlib/ts/wasmclient/goshimmer/pow_web_worker/pow_worker_manager.ts new file mode 100644 index 0000000000..18dded42f8 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/goshimmer/pow_web_worker/pow_worker_manager.ts @@ -0,0 +1,54 @@ +import { v4 as uuidv4 } from 'uuid'; +import type { Buffer } from '../../buffer'; +import Worker from 'worker-loader!./pow.worker.ts'; + +export interface PowWorkerRequest { + type: string; + data: Buffer; + uuid: string; + difficulty: number; +} + +export interface PowWorkerResponse { + type: string; + data: number; + uuid: string; + error?: Error; +} + +export class PoWWorkerManager { + private powWorker: Worker = new Worker(); + + public requestProofOfWork(difficulty: number, data: Buffer): Promise { + return new Promise((resolve, reject) => { + if (this.powWorker == null) throw new Error('powWorker not defined'); + + const requestId = uuidv4(); + + const responseHandler = (e: MessageEvent) => { + const message: PowWorkerResponse = e.data; + + if (message.type == 'pow_response' && message.uuid == requestId) { + this.powWorker!.removeEventListener('message', responseHandler); + + if (!message.error) { + resolve(message.data); + } else { + reject(message.error); + } + } + }; + + this.powWorker.addEventListener('message', responseHandler); + + const request: PowWorkerRequest = { + type: 'pow_request', + data: data, + difficulty: difficulty, + uuid: requestId, + }; + + this.powWorker.postMessage(request); + }); + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/goshimmer/pow_web_worker/proof_of_work.ts b/packages/vm/wasmlib/ts/wasmclient/goshimmer/pow_web_worker/proof_of_work.ts new file mode 100644 index 0000000000..81b4cc5aa7 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/goshimmer/pow_web_worker/proof_of_work.ts @@ -0,0 +1,33 @@ +import { blake2b } from 'blakejs'; +import { Buffer } from '../../buffer'; + +export default class ProofOfWork { + public static calculateProofOfWork(target: number, message: Buffer): number { + for (let nonce = 0; ; nonce++) { + const nonceLE = this.numberToUInt64LE(BigInt(nonce)); + const data = Buffer.concat([message, nonceLE]); + + const digest = blake2b(data); + const b = Buffer.alloc(4); + + for (let i = 0; i < 4; i++) { + b[i] = digest[i]; + } + + const leadingZeros = Math.clz32(b.readUInt32BE(0)); + + if (leadingZeros >= target) { + // eslint-disable-next-line no-console + console.log('PoW Single Thread done'); + return nonce; + } + } + } + + private static numberToUInt64LE(n: bigint): Buffer { + const buffer = Buffer.alloc(8); + buffer.writeBigUInt64LE(n, 0); + + return buffer; + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/goshimmer/pow_web_worker/worker-loader.d.ts b/packages/vm/wasmlib/ts/wasmclient/goshimmer/pow_web_worker/worker-loader.d.ts new file mode 100644 index 0000000000..f019a00ac8 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/goshimmer/pow_web_worker/worker-loader.d.ts @@ -0,0 +1,10 @@ +declare module 'worker-loader!*' { + // You need to change `Worker`, if you specified a different value for the `workerType` option + class WebpackWorker extends Worker { + constructor(); + } + + // Uncomment this if you set the `esModule` option to `false` + // export = WebpackWorker; + export default WebpackWorker; +} diff --git a/packages/vm/wasmlib/ts/wasmclient/goshimmer/utils/simple_buffer_cursor.ts b/packages/vm/wasmlib/ts/wasmclient/goshimmer/utils/simple_buffer_cursor.ts new file mode 100644 index 0000000000..2e833db40c --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/goshimmer/utils/simple_buffer_cursor.ts @@ -0,0 +1,89 @@ +import { Buffer } from "../../buffer"; + +export class SimpleBufferCursor { + private _buffer: Buffer; + private _traverse: number; + + get buffer(): Buffer { + return this._buffer; + } + + constructor(buffer: Buffer = Buffer.alloc(0)) { + this._buffer = buffer; + this._traverse = 0; + } + + readIntBE(length: number): number { + const value = this._buffer.readIntBE(this._traverse, length); + this._traverse += length; + + return value; + } + + readUInt32LE(): number { + const value = this._buffer.readUInt32LE(this._traverse); + this._traverse += 4; + + return value; + } + + readUInt64LE(): bigint { + const value = this._buffer.readBigUInt64LE(this._traverse); + this._traverse += 8; + + return value; + } + + readUInt16LE(): number { + const value = this._buffer.readUInt16LE(this._traverse); + this._traverse += 2; + + return value; + } + + readBytes(length: number): Uint8Array { + const subBuffer = this._buffer.subarray(this._traverse, this._traverse + length); + this._traverse += length; + + return subBuffer; + } + + writeIntBE(value: number, length: number): void { + const nBuffer = Buffer.alloc(length); + nBuffer.writeIntBE(value, 0, length); + + this._buffer = Buffer.concat([this._buffer, nBuffer]); + } + + writeInt8(value: number): void { + const nBuffer = Buffer.alloc(1); + nBuffer.writeInt8(value, 0); + + this._buffer = Buffer.concat([this._buffer, nBuffer]); + } + + writeUInt32LE(value: number): void { + const nBuffer = Buffer.alloc(4); + nBuffer.writeUInt32LE(value, 0); + + this._buffer = Buffer.concat([this._buffer, nBuffer]); + } + + writeUInt64LE(value: bigint): void { + const nBuffer = Buffer.alloc(8); + nBuffer.writeBigUInt64LE(value, 0); + + this._buffer = Buffer.concat([this._buffer, nBuffer]); + } + + writeUInt16LE(value: number): void { + const nBuffer = Buffer.alloc(2); + nBuffer.writeUInt16LE(value, 0); + + this._buffer = Buffer.concat([this._buffer, nBuffer]); + } + + writeBytes(bytes: Buffer): void { + this._buffer = Buffer.concat([this._buffer, bytes]); + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/goshimmer/wallet/wallet.ts b/packages/vm/wasmlib/ts/wasmclient/goshimmer/wallet/wallet.ts new file mode 100644 index 0000000000..fb7f51e719 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/goshimmer/wallet/wallet.ts @@ -0,0 +1,231 @@ +import { Base58, IKeyPair } from "../../crypto"; +import { Buffer } from "../../buffer"; +import { ITransaction, Transaction, IUnlockBlock } from "../models/transaction"; +import type { GoShimmerClient } from "../goshimmerclient"; +import type { IWalletAddressOutput, IWalletOutput } from "./wallet_models"; +import { ColorCollection, Colors } from "../../colors"; + +export type BuiltOutputResult = { + [address: string]: { + color: string; + value: bigint; + }[]; +}; + +export type ConsumedOutputs = { + [address: string]: { [outputID: string]: IWalletOutput }; +}; + +export class Wallet { + private goShimmerClient: GoShimmerClient; + constructor(client: GoShimmerClient) { + this.goShimmerClient = client; + } + + private fakeBigBalance(balances: ColorCollection) { + const colorCollection: ColorCollection = {}; + + for (const color in balances) { + colorCollection[color] = BigInt(balances[color]); + } + + return colorCollection; + } + + public async getUnspentOutputs(address: string): Promise> { + const unspents = await this.goShimmerClient.unspentOutputs({ addresses: [address] }); + + const usedAddresses = unspents.unspentOutputs.filter((u) => u.outputs.length > 0); + + const unspentOutputs = usedAddresses.map((uo) => ({ + address: uo.address.base58, + outputs: uo.outputs.map((uid) => ({ + id: uid.output.outputID.base58, + balances: this.fakeBigBalance(uid.output.output.balances), + inclusionState: uid.inclusionState, + })), + })); + + return unspentOutputs; + } + + public determineOutputsToConsume(unspentOutputs: IWalletAddressOutput[], iotas: bigint): ConsumedOutputs { + const outputsToConsume: { [address: string]: { [outputID: string]: IWalletOutput } } = {}; + + let iotasLeft = iotas; + + for (const unspentOutput of unspentOutputs) { + let outputsFromAddressSpent = false; + + for (const output of unspentOutput.outputs) { + let requiredColorFoundInOutput = false; + + if (!output.balances[Colors.IOTA_COLOR_STRING]) { + continue; + } + + const balance = output.balances[Colors.IOTA_COLOR_STRING]; + + if (iotasLeft > 0n) { + if (iotasLeft > balance) { + iotasLeft -= balance; + } else { + iotasLeft = 0n; + } + + requiredColorFoundInOutput = true; + } + + // if we found required tokens in this output + if (requiredColorFoundInOutput) { + // store the output in the outputs to use for the transfer + outputsToConsume[unspentOutput.address] = {}; + outputsToConsume[unspentOutput.address][output.id] = output; + + // mark address as spent + outputsFromAddressSpent = true; + } + } + + if (outputsFromAddressSpent) { + for (const output of unspentOutput.outputs) { + outputsToConsume[unspentOutput.address][output.id] = output; + } + } + } + + return outputsToConsume; + } + + public buildOutputs(remainderAddress: string, destinationAddress: string, iotas: bigint, consumedFunds: ColorCollection): BuiltOutputResult { + const outputsByColor: { [address: string]: ColorCollection } = {}; + + // build outputs for destinations + + if (!outputsByColor[destinationAddress]) { + outputsByColor[destinationAddress] = {}; + } + + if (!outputsByColor[destinationAddress][Colors.IOTA_COLOR_STRING]) { + outputsByColor[destinationAddress][Colors.IOTA_COLOR_STRING] = 0n; + } + const t = outputsByColor[destinationAddress][Colors.IOTA_COLOR_STRING]; + outputsByColor[destinationAddress][Colors.IOTA_COLOR_STRING] += iotas; + + consumedFunds[Colors.IOTA_COLOR_STRING] = BigInt(consumedFunds[Colors.IOTA_COLOR_STRING] ?? 0n) - iotas; + if (consumedFunds[Colors.IOTA_COLOR_STRING] === 0n) { + delete consumedFunds[Colors.IOTA_COLOR_STRING]; + } + + // build outputs for remainder + if (Object.keys(consumedFunds).length > 0) { + if (!remainderAddress) { + throw new Error("No remainder address available"); + } + if (!outputsByColor[remainderAddress]) { + outputsByColor[remainderAddress] = {}; + } + for (const consumed in consumedFunds) { + if (!outputsByColor[remainderAddress][consumed]) { + outputsByColor[remainderAddress][consumed] = 0n; + } + outputsByColor[remainderAddress][consumed] += consumedFunds[consumed]; + } + } + + // construct result + const outputsBySlice: BuiltOutputResult = {}; + + for (const address in outputsByColor) { + outputsBySlice[address] = []; + for (const color in outputsByColor[address]) { + outputsBySlice[address].push({ + color, + value: outputsByColor[address][color], + }); + } + } + + return outputsBySlice; + } + + public buildInputs(outputsToUseAsInputs: { [address: string]: { [outputID: string]: IWalletOutput } }): { + /** + * The inputs to send. + */ + inputs: string[]; + /** + * The fund that were consumed. + */ + consumedFunds: ColorCollection; + } { + const inputs: string[] = []; + const consumedFunds: ColorCollection = {}; + + for (const address in outputsToUseAsInputs) { + for (const outputID in outputsToUseAsInputs[address]) { + inputs.push(outputID); + + for (const color in outputsToUseAsInputs[address][outputID].balances) { + const balance = outputsToUseAsInputs[address][outputID].balances[color]; + + if (!consumedFunds[color]) { + consumedFunds[color] = balance; + } else { + consumedFunds[color] += balance; + } + } + } + } + + inputs.sort((a, b) => Base58.decode(a).compare(Base58.decode(b))); + + return { inputs, consumedFunds }; + } + + public unlockBlocks( + tx: ITransaction, + keyPair: IKeyPair, + address: string, + consumedOutputs: ConsumedOutputs, + builtInputs: string[] + ): Array { + const unlockBlocks: IUnlockBlock[] = []; + const txEssence = Transaction.essence(tx, Buffer.alloc(0)); + + const addressByOutputID: { [outputID: string]: string } = {}; + for (const address in consumedOutputs) { + for (const outputID in consumedOutputs[address]) { + addressByOutputID[outputID] = address; + } + } + + const existingUnlockBlocks: { [address: string]: number } = {}; + // TODO: Update this in the next refactoring. + for (const index in builtInputs) { + const addr = address == addressByOutputID[builtInputs[index]]; + if (addr) { + if (existingUnlockBlocks[address] !== undefined) { + unlockBlocks.push({ + type: 1, + referenceIndex: existingUnlockBlocks[address], + publicKey: Buffer.alloc(0), + signature: Buffer.alloc(0), + }); + continue; + } + + const signatureUnlockBlock = { + type: 0, + referenceIndex: 0, + publicKey: keyPair.publicKey, + signature: Transaction.sign(keyPair, txEssence), + }; + existingUnlockBlocks[address] = unlockBlocks.length; + unlockBlocks.push(signatureUnlockBlock); + } + } + + return unlockBlocks; + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/goshimmer/wallet/wallet_models.ts b/packages/vm/wasmlib/ts/wasmclient/goshimmer/wallet/wallet_models.ts new file mode 100644 index 0000000000..dfe7d41b8d --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/goshimmer/wallet/wallet_models.ts @@ -0,0 +1,40 @@ +import { ColorCollection } from "../../colors"; + +export interface IWalletOutputInclusionState { + solid?: boolean; + confirmed?: boolean; + rejected?: boolean; + liked?: boolean; + conflicting?: boolean; + finalized?: boolean; + preferred?: boolean; +} + +export interface IWalletOutput { + /** + * The id. + */ + id: string; + + /** + * The balances. + */ + balances: ColorCollection; + + /** + * Inclusion state. + */ + inclusionState: IWalletOutputInclusionState; +} + +export interface IWalletAddressOutput { + /** + * The address. + */ + address: string; + + /** + * The outputs. + */ + outputs: IWalletOutput[]; +} diff --git a/packages/vm/wasmlib/ts/wasmclient/index.ts b/packages/vm/wasmlib/ts/wasmclient/index.ts new file mode 100644 index 0000000000..d09441a314 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/index.ts @@ -0,0 +1,17 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +export * from "./arguments"; +export * from "./clientfunc"; +export * from "./clientview"; +export * from "./decoder"; +export * from "./encoder"; +export * from "./event"; +export * from "./results"; +export * from "./service"; +export * from "./serviceclient"; +export * from "./transfer"; +export * from "./types"; +export * from "./waspclient"; +export * from "./goshimmer/goshimmerclient"; +export * from "./configuration"; diff --git a/packages/vm/wasmlib/ts/wasmclient/package-lock.json b/packages/vm/wasmlib/ts/wasmclient/package-lock.json new file mode 100644 index 0000000000..ec06b68e75 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/package-lock.json @@ -0,0 +1,242 @@ +{ + "name": "wasmclient", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "wasmclient", + "version": "1.0.0", + "devDependencies": { + "@types/ws": "^7.4.7", + "base64-js": "^1.5.1", + "blakejs": "^1.1.1", + "ieee754": "^1.2.1", + "node-fetch": "^2.0.0", + "tweetnacl": "^1.0.3", + "typescript": "^4.0.0", + "ws": "^8.2.2" + } + }, + "node_modules/@types/node": { + "version": "17.0.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.6.tgz", + "integrity": "sha512-+XBAjfZmmivILUzO0HwBJoYkAyyySSLg5KCGBDFLomJo0sV6szvVLAf4ANZZ0pfWzgEds5KmGLG9D5hfEqOhaA==", + "dev": true + }, + "node_modules/@types/ws": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", + "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/blakejs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.1.tgz", + "integrity": "sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg==", + "dev": true + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/node-fetch": { + "version": "2.6.6", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz", + "integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", + "dev": true + }, + "node_modules/typescript": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz", + "integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/ws": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.4.0.tgz", + "integrity": "sha512-IHVsKe2pjajSUIl4KYMQOdlyliovpEPquKkqbwswulszzI7r0SfQrxnXdWAEqOlDCLrVSJzo+O1hAwdog2sKSQ==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + }, + "dependencies": { + "@types/node": { + "version": "17.0.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.6.tgz", + "integrity": "sha512-+XBAjfZmmivILUzO0HwBJoYkAyyySSLg5KCGBDFLomJo0sV6szvVLAf4ANZZ0pfWzgEds5KmGLG9D5hfEqOhaA==", + "dev": true + }, + "@types/ws": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", + "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true + }, + "blakejs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.1.tgz", + "integrity": "sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg==", + "dev": true + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, + "node-fetch": { + "version": "2.6.6", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz", + "integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", + "dev": true + }, + "typescript": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz", + "integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==", + "dev": true + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "ws": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.4.0.tgz", + "integrity": "sha512-IHVsKe2pjajSUIl4KYMQOdlyliovpEPquKkqbwswulszzI7r0SfQrxnXdWAEqOlDCLrVSJzo+O1hAwdog2sKSQ==", + "dev": true, + "requires": {} + } + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/package.json b/packages/vm/wasmlib/ts/wasmclient/package.json new file mode 100644 index 0000000000..d3532344e8 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/package.json @@ -0,0 +1,17 @@ +{ + "name": "wasmclient", + "description": "WasmClient, client interface library for ISCP Wasm VM", + "version": "1.0.0", + "author": "Eric Hop", + "dependencies": {}, + "devDependencies": { + "@types/ws": "^7.4.7", + "node-fetch": "^2.0.0", + "ws": "^8.2.2", + "base64-js": "^1.5.1", + "blakejs": "^1.1.1", + "ieee754": "^1.2.1", + "tweetnacl": "^1.0.3", + "typescript": "^4.0.0" + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/results.ts b/packages/vm/wasmlib/ts/wasmclient/results.ts new file mode 100644 index 0000000000..0472c92112 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/results.ts @@ -0,0 +1,34 @@ +// The Results struct is used to gather all arguments for a smart +// contract function call and encode it into a deterministic byte array +import * as wasmclient from "./index"; +import {Buffer} from "./buffer"; + +export class Results extends wasmclient.Decoder { + protected keys = new Map(); + protected res = new Map(); + + protected exists(key: string): boolean { + return this.res.has(key); + } + + protected forEach(keyValue: (key: Buffer, val: Buffer) => void): void { + this.res.forEach((val, key) => { + let keyBuf = this.keys.get(key); + if (keyBuf === undefined) { + wasmclient.panic("missing key"); + return; + } + keyValue(keyBuf, val); + }) + } + + protected get(key: string): Buffer | undefined { + return this.res.get(key); + } + + public set(key: Buffer, val: Buffer) { + const stringKey = key.toString(); + this.keys.set(stringKey, key); + this.res.set(stringKey, val); + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/service.ts b/packages/vm/wasmlib/ts/wasmclient/service.ts new file mode 100644 index 0000000000..efb029f008 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/service.ts @@ -0,0 +1,111 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import * as wasmclient from "./index"; +import {Hash, IKeyPair} from "./crypto"; +import {IOnLedger} from "./goshimmer/models/on_ledger"; +import {Colors} from "./colors"; +import {Buffer} from './buffer'; + +export type EventHandlers = Map void>; + +export class Service { + private serviceClient: wasmclient.ServiceClient; + private webSocket: WebSocket | null = null; + public keyPair: IKeyPair | null = null; + private eventHandlers: EventHandlers | null = null; + public scHname: wasmclient.Hname; + private waspWebSocketUrl: string = ""; + + constructor(client: wasmclient.ServiceClient, scHname: wasmclient.Hname, eventHandlers: EventHandlers) { + this.serviceClient = client; + this.scHname = scHname; + if (eventHandlers.size != 0) { + this.configureWebSocketsEventHandlers(eventHandlers); + } + } + + public async callView(viewName: string, args: wasmclient.Arguments, res: wasmclient.Results): Promise { + await this.serviceClient.waspClient.callView( + this.serviceClient.configuration.chainId, + this.scHname.toString(16), + viewName, + args.encodeCall(), + res + ); + } + + public async postRequest( + hFuncName: wasmclient.Int32, + args: wasmclient.Arguments, + transfer: wasmclient.Transfer, + keyPair: IKeyPair, + onLedger: boolean + ): Promise { + const chainId = this.serviceClient.configuration.chainId; + if (! onLedger) { + // requested off-ledger request + const requestID = await this.serviceClient.waspClient.postOffLedgerRequest(chainId, this.scHname, hFuncName, args, transfer, keyPair); + return requestID; + } + + // requested on-ledger request + const payload: IOnLedger = { + contract: this.scHname, + entrypoint: hFuncName, + //TODO: map args + //arguments : args + }; + const transferAmount = transfer.get(Colors.IOTA_COLOR); + const transactionID = await this.serviceClient.goShimmerClient.postOnLedgerRequest(chainId, payload, transferAmount, keyPair); + if (!transactionID) throw new Error("No transaction id"); + return transactionID; + } + + // overrides default contract name + public serviceContractName(contractName: string): void { + this.scHname = Hash.from(Buffer.from(contractName)).readUInt32LE(0) + } + + public async waitRequest(reqID: wasmclient.RequestID): Promise { + await this.serviceClient.waspClient.waitRequest(this.serviceClient.configuration.chainId, reqID); + } + + private configureWebSocketsEventHandlers(eventHandlers: EventHandlers) { + this.eventHandlers = eventHandlers; + + if ( + this.serviceClient.configuration.waspWebSocketUrl.startsWith("wss://") || + this.serviceClient.configuration.waspWebSocketUrl.startsWith("ws://") + ) + this.waspWebSocketUrl = this.serviceClient.configuration.waspWebSocketUrl; + else this.waspWebSocketUrl = "ws://" + this.serviceClient.configuration.waspWebSocketUrl; + + this.waspWebSocketUrl = this.waspWebSocketUrl.replace("%chainId", this.serviceClient.configuration.chainId); + + if (this.eventHandlers.size > 1) this.connectWebSocket(); + } + + private connectWebSocket(): void { + // eslint-disable-next-line no-console + console.log(`Connecting to Websocket => ${this.waspWebSocketUrl}`); + this.webSocket = new WebSocket(this.waspWebSocketUrl); + this.webSocket.addEventListener("message", (x) => this.handleIncomingMessage(x)); + this.webSocket.addEventListener("close", () => setTimeout(this.connectWebSocket.bind(this), 1000)); + } + + private handleIncomingMessage(message: MessageEvent): void { + // expect vmmsg contract.event|parameters + const msg = message.data.toString().split(" "); + if (msg.length != 4 || msg[0] != "vmmsg") { + return; + } + const topics = msg[3].split("|"); + const topic = topics[0]; + if (this.eventHandlers && this.eventHandlers.has(topic)) { + const eventHandler = this.eventHandlers.get(topic)!; + const eventHandlerMsg = topics.slice(1); + eventHandler(eventHandlerMsg); + } + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/serviceclient.ts b/packages/vm/wasmlib/ts/wasmclient/serviceclient.ts new file mode 100644 index 0000000000..66e93df086 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/serviceclient.ts @@ -0,0 +1,30 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import * as wasmclient from "./index"; +import { Configuration, IConfiguration } from "./configuration"; +import { CoreAccountsService } from "./coreaccounts/service"; + +export class ServiceClient { + waspClient: wasmclient.WaspClient; + goShimmerClient: wasmclient.GoShimmerClient; + configuration: Configuration; + + constructor(configuration: Configuration) { + this.configuration = configuration; + this.waspClient = new wasmclient.WaspClient(configuration.waspApiUrl); + const accountsService = new CoreAccountsService(this); + this.goShimmerClient = new wasmclient.GoShimmerClient(configuration, accountsService); + } + + static default(): ServiceClient { + //TODO use TCP instead of websocket for event listener? + const defaultConfiguration: IConfiguration = { + seed: null, + waspWebSocketUrl: "ws://127.0.0.1:9090", + waspApiUrl: "127.0.0.1:9090", + goShimmerApiUrl: "", + }; + return new ServiceClient(new Configuration(defaultConfiguration)); // "127.0.0.1:5550"); + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/transfer.ts b/packages/vm/wasmlib/ts/wasmclient/transfer.ts new file mode 100644 index 0000000000..267eb32e12 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/transfer.ts @@ -0,0 +1,65 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import * as wasmclient from "./index" +import {Base58} from "./crypto"; +import {Buffer} from "./buffer"; +import { Colors } from "./colors"; + +export class Transfer { + private xfer = new Map(); + + static iotas(amount: wasmclient.Uint64): Transfer { + return Transfer.tokens(Colors.IOTA_COLOR, amount); + } + + static tokens(color: string, amount: wasmclient.Uint64): Transfer { + const transfer = new Transfer(); + transfer.set(color, amount); + return transfer; + } + + set(color: string, amount: wasmclient.Uint64) { + if (color == Colors.IOTA_COLOR) { + color = Colors.IOTA_COLOR_STRING + } + this.xfer.set(color, amount); + } + + get(color: string): wasmclient.Uint64 { + if (color == Colors.IOTA_COLOR) color = Colors.IOTA_COLOR_STRING; + const amount = this.xfer.get(color) ?? 0n; + return amount; + } + + // Encode returns a byte array that encodes the Transfer as follows: + // Sort all nonzero transfers in ascending color order (very important, + // because this data will be part of the data that will be signed, + // so the order needs to be 100% deterministic). Then emit the 4-byte + // transfer count. Next for each color emit the 32-byte color value, + // and then the 8-byte amount. + encode(): wasmclient.Bytes { + const keys = new Array(); + for (const [key, val] of this.xfer) { + // filter out zero transfers + if (val != BigInt(0)) { + keys.push(key); + } + } + keys.sort((lhs, rhs) => lhs.localeCompare(rhs)); + + let buf = Buffer.alloc(4); + buf.writeUInt32LE(keys.length, 0); + for (const key of keys) { + const val = this.xfer.get(key); + if (!val) { + throw new Error("Transfer.encode: missing amount?"); + } + const keyBuf = Base58.decode(key); + const valBuf = Buffer.alloc(8); + valBuf.writeBigUInt64LE(val, 0); + buf = Buffer.concat([buf, keyBuf, valBuf]); + } + return buf; + } +} diff --git a/packages/vm/wasmlib/ts/wasmclient/tsconfig.json b/packages/vm/wasmlib/ts/wasmclient/tsconfig.json new file mode 100644 index 0000000000..6154e4f4be --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "strict": true, + "lib": ["ES2021", "esnext", "dom"], + "target": "ES2021", + "module": "esnext", + "sourceMap": true, + "allowSyntheticDefaultImports": true, + "moduleResolution": "node", + "baseUrl": ".", + "paths": { + "@/*": ["./*"] + }, + }, + "preferBuiltins": true, + "include": ["./**/*.ts"], + "exclude": [ + "node_modules" + ], +} \ No newline at end of file diff --git a/packages/vm/wasmlib/ts/wasmclient/types.ts b/packages/vm/wasmlib/ts/wasmclient/types.ts new file mode 100644 index 0000000000..95484471ef --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/types.ts @@ -0,0 +1,45 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import {Buffer} from "./buffer"; + +export const TYPE_ADDRESS = 1; +export const TYPE_AGENT_ID = 2; +export const TYPE_BOOL = 3; +export const TYPE_BYTES = 4; +export const TYPE_CHAIN_ID = 5; +export const TYPE_COLOR = 6; +export const TYPE_HASH = 7; +export const TYPE_HNAME = 8; +export const TYPE_INT8 = 9; +export const TYPE_INT16 = 10; +export const TYPE_INT32 = 11; +export const TYPE_INT64 = 12; +export const TYPE_MAP = 13; +export const TYPE_REQUEST_ID = 14; +export const TYPE_STRING = 15; + +export type Address = string; +export type AgentID = string; +export type Bool = boolean; +export type Bytes = Buffer; +export type ChainID = string; +export type Color = string; +export type Hash = string; +export type Hname = number; +export type Int8 = number; +export type Int16 = number; +export type Int32 = number; +export type Int64 = bigint; +export type RequestID = string; +export type String = string; +export type Uint8 = number; +export type Uint16 = number; +export type Uint32 = number; +export type Uint64 = bigint; + +export const TYPE_SIZES = new Uint8Array([0, 33, 37, 1, 0, 33, 32, 32, 4, 1, 2, 4, 8, 0, 34, 0]); + +export function panic(err: string) { + throw new Error(err); +} \ No newline at end of file diff --git a/packages/vm/wasmlib/ts/wasmclient/waspclient.ts b/packages/vm/wasmlib/ts/wasmclient/waspclient.ts new file mode 100644 index 0000000000..0e34996400 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmclient/waspclient.ts @@ -0,0 +1,92 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import * as wasmclient from "./index"; +import { Buffer } from "./buffer"; +import { IResponse } from "./api_common/response_models"; +import * as requestSender from "./api_common/request_sender"; +import { Base58, ED25519, Hash, IKeyPair } from "./crypto"; + +interface ICallViewResponse extends IResponse { + Items: [{ Key: string; Value: string }]; +} + +interface IOffLedgerRequest { + Request: string; +} + +export class Item { + Key: string; + Value: string; + + constructor(key: string, value: string) { + this.Key = key; + this.Value = value; + } +} + +export class Items { + Items = new Array(); +} + +export class WaspClient { + private waspAPI: string; + + constructor(waspAPI: string) { + if (waspAPI.startsWith("https://") || waspAPI.startsWith("http://")) this.waspAPI = waspAPI; + else this.waspAPI = "http://" + waspAPI; + } + + public async callView(chainID: string, contractHName: string, entryPoint: string, args: Items, res: wasmclient.Results): Promise { + const result = await requestSender.sendRequestExt( + this.waspAPI, + "post", + `/chain/${chainID}/contract/${contractHName}/callview/${entryPoint}`, + args + ); + if (result?.body !== null && result.body.Items) { + for (const item of result.body.Items) { + const key = Buffer.from(item.Key, "base64"); + const val = Buffer.from(item.Value, "base64"); + res.set(key, val); + } + } + } + + public async postRequest(chainID: string, offLedgerRequest: Buffer): Promise { + const request = { Request: offLedgerRequest.toString("base64") }; + await requestSender.sendRequestExt(this.waspAPI, "post", `/request/${chainID}`, request); + } + + public async waitRequest(chainID: string, reqID: wasmclient.RequestID): Promise { + await requestSender.sendRequestExt(this.waspAPI, "get", `/chain/${chainID}/request/${reqID}/wait`); + } + + public async postOffLedgerRequest( + chainId: string, + scHName: wasmclient.Hname, + hFuncName: wasmclient.Int32, + args: wasmclient.Arguments, + transfer: wasmclient.Transfer, + keyPair: IKeyPair + ): Promise { + // get request essence ready for signing + let essence = Base58.decode(chainId); + const hNames = Buffer.alloc(8); + hNames.writeUInt32LE(scHName, 0); + hNames.writeUInt32LE(hFuncName, 4); + const nonce = Buffer.alloc(8); + nonce.writeBigUInt64LE(BigInt(Math.trunc(performance.now())), 0); + essence = Buffer.concat([essence, hNames, args.encode(), keyPair.publicKey, nonce, transfer.encode()]); + + let buf = Buffer.alloc(1); + const requestTypeOffledger = 1; + buf.writeUInt8(requestTypeOffledger, 0); + buf = Buffer.concat([buf, essence, ED25519.privateSign(keyPair, essence)]); + const hash = Hash.from(buf); + const requestID = Buffer.concat([hash, Buffer.alloc(2)]); + await this.postRequest(chainId, buf); + + return Base58.encode(requestID); + } +} diff --git a/packages/vm/wasmlib/ts/wasmlib/context.ts b/packages/vm/wasmlib/ts/wasmlib/context.ts index 13ab878698..72bcd296b6 100644 --- a/packages/vm/wasmlib/ts/wasmlib/context.ts +++ b/packages/vm/wasmlib/ts/wasmlib/context.ts @@ -319,6 +319,9 @@ export class ScFuncContext extends ScBaseContext implements ScViewCallContext, S // generates a random value from 0 to max (exclusive max) using a deterministic RNG random(max: i64): i64 { + if (max == 0) { + this.panic("random: max parameter should be non-zero"); + } let state = new ScMutableMap(OBJ_ID_STATE); let rnd = state.getBytes(keys.KEY_RANDOM); let seed = rnd.value(); diff --git a/packages/vm/wasmlib/ts/wasmlib/host.ts b/packages/vm/wasmlib/ts/wasmlib/host.ts index a830b80eb0..4337d407fc 100644 --- a/packages/vm/wasmlib/ts/wasmlib/host.ts +++ b/packages/vm/wasmlib/ts/wasmlib/host.ts @@ -37,7 +37,7 @@ export const OBJ_ID_PARAMS: i32 = 3; export const OBJ_ID_RESULTS: i32 = 4; // size in bytes of predefined types, indexed by the TYPE_* consts -const TYPE_SIZES: u8[] = [0, 33, 37, 1, 0, 33, 32, 32, 4, 1, 2, 4, 8, 0, 34, 0]; +export const TYPE_SIZES: u8[] = [0, 33, 37, 1, 0, 33, 32, 32, 4, 1, 2, 4, 8, 0, 34, 0]; // These 4 external functions are funneling the entire WasmLib functionality diff --git a/packages/vm/wasmlib/ts/wasmlib/package-lock.json b/packages/vm/wasmlib/ts/wasmlib/package-lock.json new file mode 100644 index 0000000000..b0e4152706 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmlib/package-lock.json @@ -0,0 +1,58 @@ +{ + "name": "wasmlib", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@assemblyscript/loader": { + "version": "0.19.22", + "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.19.22.tgz", + "integrity": "sha512-ksrMVpPOatD7ZzXCw+c/g3zId5rm8MMnQe7P32dH/qtDrgT9SbQjJYEngRP0YhRF0qrBCga2PtpID7arqphGyg==" + }, + "assemblyscript": { + "version": "0.19.22", + "resolved": "https://registry.npmjs.org/assemblyscript/-/assemblyscript-0.19.22.tgz", + "integrity": "sha512-+Rclbx0+BI3qAe9fjc8XGbSUDaayTtjINnD19I4MmfpT2R43c9YTQERP36676shkPxb1fisDFZeSTL65Da8Q2g==", + "dev": true, + "requires": { + "binaryen": "102.0.0-nightly.20211028", + "long": "^5.2.0", + "source-map-support": "^0.5.20" + } + }, + "binaryen": { + "version": "102.0.0-nightly.20211028", + "resolved": "https://registry.npmjs.org/binaryen/-/binaryen-102.0.0-nightly.20211028.tgz", + "integrity": "sha512-GCJBVB5exbxzzvyt8MGDv/MeUjs6gkXDvf4xOIItRBptYl0Tz5sm1o/uG95YK0L0VeG5ajDu3hRtkBP2kzqC5w==", + "dev": true + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "long": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.0.tgz", + "integrity": "sha512-9RTUNjK60eJbx3uz+TEGF7fUr29ZDxR5QzXcyDpeSfeH28S9ycINflOgOlppit5U+4kNTe83KQnMEerw7GmE8w==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } +} diff --git a/packages/vm/wasmlib/ts/wasmlib/package.json b/packages/vm/wasmlib/ts/wasmlib/package.json index 54a27cd14a..b3d0b9c01d 100644 --- a/packages/vm/wasmlib/ts/wasmlib/package.json +++ b/packages/vm/wasmlib/ts/wasmlib/package.json @@ -9,4 +9,4 @@ "devDependencies": { "assemblyscript": "^0.19.18" } -} \ No newline at end of file +} diff --git a/packages/vm/wasmclient/host.go b/packages/vm/wasmvmhost/host.go similarity index 99% rename from packages/vm/wasmclient/host.go rename to packages/vm/wasmvmhost/host.go index aaf31ba17d..9b48bed8fd 100644 --- a/packages/vm/wasmclient/host.go +++ b/packages/vm/wasmvmhost/host.go @@ -3,7 +3,7 @@ // +build wasm -package wasmclient +package wasmvmhost import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" diff --git a/packages/wal/wal.go b/packages/wal/wal.go new file mode 100644 index 0000000000..5267ea646e --- /dev/null +++ b/packages/wal/wal.go @@ -0,0 +1,214 @@ +package wal + +import ( + "bufio" + "fmt" + "io" + "os" + "path/filepath" + "strconv" + "sync" + + "github.com/iotaledger/hive.go/logger" + "github.com/iotaledger/wasp/packages/chain" + "github.com/iotaledger/wasp/packages/iscp" + "github.com/iotaledger/wasp/packages/state" + "github.com/prometheus/client_golang/prometheus" +) + +type WAL struct { + dir string + log *logger.Logger + metrics *walMetrics + segments map[uint32]*segment + synced map[uint32]bool + mu sync.RWMutex //nolint +} + +type chainWAL struct { + *WAL + chainID *iscp.ChainID +} + +func New(log *logger.Logger, dir string) *WAL { + return &WAL{log: log, dir: dir, metrics: newWALMetrics(), synced: make(map[uint32]bool)} +} + +var _ chain.WAL = &chainWAL{} + +type segmentFile interface { + Stat() (os.FileInfo, error) + io.Writer + io.Closer + io.Reader +} + +type segment struct { + segmentFile + index uint32 + dir string +} + +func (w *WAL) NewChainWAL(chainID *iscp.ChainID) (chain.WAL, error) { + if w == nil { + return &defaultWAL{}, nil + } + w.dir = filepath.Join(w.dir, chainID.Base58()) + if err := os.MkdirAll(w.dir, 0o777); err != nil { + return nil, fmt.Errorf("create dir: %w", err) + } + // read all segments in log + f, err := os.Open(w.dir) + if err != nil { + return nil, fmt.Errorf("could not open wal: %w", err) + } + + w.segments = make(map[uint32]*segment) + files, _ := f.ReadDir(-1) + for _, file := range files { + w.metrics.segments.Inc() + index, _ := strconv.ParseUint(file.Name(), 10, 32) + w.segments[uint32(index)] = &segment{index: uint32(index), dir: w.dir} + } + return &chainWAL{w, chainID}, nil +} + +func (w *chainWAL) Write(bytes []byte) error { + w.mu.Lock() + defer w.mu.Unlock() + + block, err := state.BlockFromBytes(bytes) + if err != nil { + return fmt.Errorf("Invalid block: %w", err) + } + segment, err := w.createSegment(block.BlockIndex()) + if err != nil { + w.metrics.failedWrites.Inc() + return fmt.Errorf("Error writing log: %w", err) + } + n, err := segment.Write(bytes) + if err != nil || len(bytes) != n { + w.metrics.failedReads.Inc() + return fmt.Errorf("Error writing log: %w", err) + } + w.metrics.segments.Inc() + return segment.Close() +} + +func (w *chainWAL) createSegment(i uint32) (*segment, error) { + segName := segmentName(w.dir, i) + f, err := os.OpenFile(segName, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o666) + if err != nil { + return nil, fmt.Errorf("could not create segment: %w", err) + } + s := &segment{index: i, segmentFile: f, dir: w.dir} + w.segments[i] = s + return s, nil +} + +func segmentName(dir string, index uint32) string { + return filepath.Join(dir, fmt.Sprintf("%010d", index)) +} + +func (w *chainWAL) Contains(i uint32) bool { + return w.getSegment(i) != nil +} + +func (w *chainWAL) Read(i uint32) ([]byte, error) { + segment := w.getSegment(i) + if segment == nil { + return nil, fmt.Errorf("block not found in wal") + } + if err := segment.load(); err != nil { + w.metrics.failedReads.Inc() + return nil, fmt.Errorf("Error opening backup file: %w", err) + } + stat, err := segment.Stat() + if err != nil { + w.metrics.failedReads.Inc() + return nil, fmt.Errorf("Error reading backup file: %w", err) + } + blockBytes := make([]byte, stat.Size()) + bufr := bufio.NewReader(segment) + n, err := bufr.Read(blockBytes) + if err != nil || int64(n) != stat.Size() { + w.metrics.failedReads.Inc() + return nil, fmt.Errorf("Error reading backup file: %w", err) + } + return blockBytes, nil +} + +func (w *chainWAL) getSegment(i uint32) *segment { + segment, ok := w.segments[i] + if ok { + return segment + } + return nil +} + +func (s *segment) load() error { + segName := segmentName(s.dir, s.index) + f, err := os.OpenFile(segName, os.O_RDONLY, 0o666) + if err != nil { + return fmt.Errorf("error opening segment: %w", err) + } + s.segmentFile = f + return nil +} + +type defaultWAL struct{} + +var _ chain.WAL = &defaultWAL{} + +func (w *defaultWAL) Write(_ []byte) error { + return nil +} + +func (w *defaultWAL) Read(i uint32) ([]byte, error) { + return nil, fmt.Errorf("Empty wal") +} + +func (w *defaultWAL) Contains(i uint32) bool { + return false +} + +func NewDefault() chain.WAL { + return &defaultWAL{} +} + +type walMetrics struct { + segments prometheus.Counter + failedWrites prometheus.Counter + failedReads prometheus.Counter +} + +var once sync.Once + +func newWALMetrics() *walMetrics { + m := &walMetrics{} + + m.segments = prometheus.NewCounter(prometheus.CounterOpts{ + Name: "wasp_wal_total_segments", + Help: "Total number of segment files", + }) + + m.failedWrites = prometheus.NewCounter(prometheus.CounterOpts{ + Name: "wasp_wal_failed_writes", + Help: "Total number of writes to WAL that failed", + }) + + m.failedReads = prometheus.NewCounter(prometheus.CounterOpts{ + Name: "wasp_wal_failed_reads", + Help: "Total number of reads failed while replaying WAL", + }) + + registerMetrics := func() { + prometheus.MustRegister( + m.segments, + m.failedWrites, + m.failedReads, + ) + } + once.Do(registerMetrics) + return m +} diff --git a/packages/webapi/admapi/activatechain.go b/packages/webapi/admapi/activatechain.go index 5930bc07b1..b9d26292ad 100644 --- a/packages/webapi/admapi/activatechain.go +++ b/packages/webapi/admapi/activatechain.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package admapi import ( @@ -5,18 +8,38 @@ import ( "net/http" "github.com/iotaledger/goshimmer/packages/ledgerstate" + "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/wasp/packages/chains" "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/metrics" + "github.com/iotaledger/wasp/packages/peering" "github.com/iotaledger/wasp/packages/registry" + "github.com/iotaledger/wasp/packages/tcrypto" + "github.com/iotaledger/wasp/packages/vm/core/governance" + "github.com/iotaledger/wasp/packages/wal" "github.com/iotaledger/wasp/packages/webapi/httperrors" + "github.com/iotaledger/wasp/packages/webapi/model" "github.com/iotaledger/wasp/packages/webapi/routes" "github.com/labstack/echo/v4" "github.com/pangpanglabs/echoswagger/v2" ) -func addChainEndpoints(adm echoswagger.ApiGroup, registryProvider registry.Provider, chainsProvider chains.Provider, allMetrics *metrics.Metrics) { - c := &chainWebAPI{registryProvider, chainsProvider, allMetrics} +type chainWebAPI struct { + registry registry.Provider + chains chains.Provider + network peering.NetworkProvider + allMetrics *metrics.Metrics + w *wal.WAL +} + +func addChainEndpoints(adm echoswagger.ApiGroup, registryProvider registry.Provider, chainsProvider chains.Provider, network peering.NetworkProvider, allMetrics *metrics.Metrics, w *wal.WAL) { + c := &chainWebAPI{ + registryProvider, + chainsProvider, + network, + allMetrics, + w, + } adm.POST(routes.ActivateChain(":chainID"), c.handleActivateChain). AddParamPath("", "chainID", "ChainID (base58)"). @@ -25,12 +48,10 @@ func addChainEndpoints(adm echoswagger.ApiGroup, registryProvider registry.Provi adm.POST(routes.DeactivateChain(":chainID"), c.handleDeactivateChain). AddParamPath("", "chainID", "ChainID (base58)"). SetSummary("Deactivate a chain") -} -type chainWebAPI struct { - registry registry.Provider - chains chains.Provider - allMetrics *metrics.Metrics + adm.GET(routes.GetChainInfo(":chainID"), c.handleGetChainInfo). + AddParamPath("", "chainID", "ChainID (base58)"). + SetSummary("Get basic chain info.") } func (w *chainWebAPI) handleActivateChain(c echo.Context) error { @@ -48,7 +69,7 @@ func (w *chainWebAPI) handleActivateChain(c echo.Context) error { } log.Debugw("calling Chains.Activate", "chainID", rec.ChainID.String()) - if err := w.chains().Activate(rec, w.registry, w.allMetrics); err != nil { + if err := w.chains().Activate(rec, w.registry, w.allMetrics, w.w); err != nil { return err } @@ -76,3 +97,150 @@ func (w *chainWebAPI) handleDeactivateChain(c echo.Context) error { return c.NoContent(http.StatusOK) } + +func (w *chainWebAPI) handleGetChainInfo(c echo.Context) error { + scAddress, err := ledgerstate.AddressFromBase58EncodedString(c.Param("chainID")) + if err != nil { + return httperrors.BadRequest(fmt.Sprintf("Invalid chain id: %s", c.Param("chainID"))) + } + chainID, err := iscp.ChainIDFromAddress(scAddress) + if err != nil { + return err + } + + chain := w.chains().Get(chainID, true) + committeeInfo := chain.GetCommitteeInfo() + chainRecord, err := w.registry().GetChainRecordByChainID(chainID) + if err != nil { + return err + } + dkShare, err := w.registry().LoadDKShare(committeeInfo.Address) + if err != nil { + return err + } + + chainNodes := chain.GetChainNodes() + peeringStatus := make(map[ed25519.PublicKey]peering.PeerStatusProvider) + for _, n := range w.network.PeerStatus() { + peeringStatus[*n.PubKey()] = n + } + candidateNodes := make(map[ed25519.PublicKey]*governance.AccessNodeInfo) + for _, n := range chain.GetCandidateNodes() { + pubKey, _, err := ed25519.PublicKeyFromBytes(n.NodePubKey) + if err != nil { + return err + } + candidateNodes[pubKey] = n + } + + inChainNodes := make(map[ed25519.PublicKey]bool) + + // + // Committee nodes. + cmtNodes := makeCmtNodes(dkShare, peeringStatus, candidateNodes, inChainNodes) + + // + // Access nodes: accepted as access nodes and not included in the committee. + acnNodes := makeAcnNodes(dkShare, chainNodes, peeringStatus, candidateNodes, inChainNodes) + + // + // Candidate nodes have suplied applications, but are not included + // in the committee and to the set of the access nodes. + cndNodes, err := makeCndNodes(peeringStatus, candidateNodes, inChainNodes) + if err != nil { + return err + } + + res := model.ChainInfo{ + ChainID: model.ChainID(chainID.Base58()), + Active: chainRecord.Active, + StateAddress: model.NewAddress(committeeInfo.Address), + CommitteeNodes: cmtNodes, + AccessNodes: acnNodes, + CandidateNodes: cndNodes, + } + + return c.JSON(http.StatusOK, res) +} + +func makeCmtNodes( + dkShare *tcrypto.DKShare, + peeringStatus map[ed25519.PublicKey]peering.PeerStatusProvider, + candidateNodes map[ed25519.PublicKey]*governance.AccessNodeInfo, + inChainNodes map[ed25519.PublicKey]bool, +) []*model.ChainNodeStatus { + cmtNodes := make([]*model.ChainNodeStatus, 0) + for _, cmtNodePubKey := range dkShare.NodePubKeys { + cmtNodes = append(cmtNodes, makeChainNodeStatus(cmtNodePubKey, peeringStatus, candidateNodes)) + inChainNodes[*cmtNodePubKey] = true + } + return cmtNodes +} + +func makeAcnNodes( + dkShare *tcrypto.DKShare, + chainNodes []peering.PeerStatusProvider, + peeringStatus map[ed25519.PublicKey]peering.PeerStatusProvider, + candidateNodes map[ed25519.PublicKey]*governance.AccessNodeInfo, + inChainNodes map[ed25519.PublicKey]bool, +) []*model.ChainNodeStatus { + acnNodes := make([]*model.ChainNodeStatus, 0) + for _, chainNode := range chainNodes { + acnPubKey := chainNode.PubKey() + skip := false + for _, cmtNodePubKey := range dkShare.NodePubKeys { + if *acnPubKey == *cmtNodePubKey { + skip = true + break + } + } + if skip { + continue + } + acnNodes = append(acnNodes, makeChainNodeStatus(acnPubKey, peeringStatus, candidateNodes)) + inChainNodes[*acnPubKey] = true + } + return acnNodes +} + +func makeCndNodes( + peeringStatus map[ed25519.PublicKey]peering.PeerStatusProvider, + candidateNodes map[ed25519.PublicKey]*governance.AccessNodeInfo, + inChainNodes map[ed25519.PublicKey]bool, +) ([]*model.ChainNodeStatus, error) { + cndNodes := make([]*model.ChainNodeStatus, 0) + for _, c := range candidateNodes { + pubKey, _, err := ed25519.PublicKeyFromBytes(c.NodePubKey) + if err != nil { + return nil, err + } + if _, ok := inChainNodes[pubKey]; ok { + continue // Only include unused candidates here. + } + cndNodes = append(cndNodes, makeChainNodeStatus(&pubKey, peeringStatus, candidateNodes)) + } + return cndNodes, nil +} + +func makeChainNodeStatus( + pubKey *ed25519.PublicKey, + peeringStatus map[ed25519.PublicKey]peering.PeerStatusProvider, + candidateNodes map[ed25519.PublicKey]*governance.AccessNodeInfo, +) *model.ChainNodeStatus { + cns := model.ChainNodeStatus{ + Node: model.PeeringNodeStatus{ + PubKey: pubKey.String(), + }, + } + if n, ok := peeringStatus[*pubKey]; ok { + cns.Node.NetID = n.NetID() + cns.Node.IsAlive = n.IsAlive() + cns.Node.NumUsers = n.NumUsers() + } + if n, ok := candidateNodes[*pubKey]; ok { + cns.ForCommittee = n.ForCommittee + cns.ForAccess = true + cns.AccessAPI = n.AccessAPI + } + return &cns +} diff --git a/packages/webapi/admapi/chainnodeconnmetrics.go b/packages/webapi/admapi/chainmetrics.go similarity index 52% rename from packages/webapi/admapi/chainnodeconnmetrics.go rename to packages/webapi/admapi/chainmetrics.go index cc7f442458..ecf32d8137 100644 --- a/packages/webapi/admapi/chainnodeconnmetrics.go +++ b/packages/webapi/admapi/chainmetrics.go @@ -5,6 +5,7 @@ import ( "net/http" "time" + "github.com/iotaledger/wasp/packages/chain" "github.com/iotaledger/wasp/packages/chains" "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/webapi/httperrors" @@ -14,7 +15,13 @@ import ( "github.com/pangpanglabs/echoswagger/v2" ) -func addChainStatsEndpoints(adm echoswagger.ApiGroup, chainsProvider chains.Provider) { +func addChainMetricsEndpoints(adm echoswagger.ApiGroup, chainsProvider chains.Provider) { + cms := &chainMetricsService{chainsProvider} + addChainNodeConnMetricsEndpoints(adm, cms) + addChainConsensusMetricsEndpoints(adm, cms) +} + +func addChainNodeConnMetricsEndpoints(adm echoswagger.ApiGroup, cms *chainMetricsService) { chainExample := &model.NodeConnectionMessagesMetrics{ OutPullState: &model.NodeConnectionMessageMetrics{ Total: 15, @@ -66,30 +73,56 @@ func addChainStatsEndpoints(adm echoswagger.ApiGroup, chainsProvider chains.Prov }, } - s := &chainStatsService{chainsProvider} + adm.GET(routes.GetChainsNodeConnectionMetrics(), cms.handleGetChainsNodeConnMetrics). + SetSummary("Get cummulative chains node connection metrics"). + AddResponse(http.StatusOK, "Chains Metrics", example, nil) + + adm.GET(routes.GetChainNodeConnectionMetrics(":chainID"), cms.handleGetChainNodeConnMetrics). + SetSummary("Get chain node connection metrics for the given chain ID"). + AddParamPath("", "chainID", "ChainID (base58)"). + AddResponse(http.StatusOK, "Chain Metrics", chainExample, nil) +} + +func addChainConsensusMetricsEndpoints(adm echoswagger.ApiGroup, cms *chainMetricsService) { + example := &model.ConsensusWorkflowStatus{ + FlagStateReceived: true, + FlagBatchProposalSent: true, + FlagConsensusBatchKnown: true, + FlagVMStarted: false, + FlagVMResultSigned: false, + FlagTransactionFinalized: false, + FlagTransactionPosted: false, + FlagTransactionSeen: false, + FlagInProgress: true, - adm.GET(routes.GetChainsNodeConnectionMetrics(), s.handleGetChainsStats). - SetSummary("Get cummulative chains state statistics"). - AddResponse(http.StatusOK, "Chains Stats", example, nil) + TimeBatchProposalSent: time.Now().Add(-10 * time.Second), + TimeConsensusBatchKnown: time.Now().Add(-5 * time.Second), + TimeVMStarted: time.Time{}, + TimeVMResultSigned: time.Time{}, + TimeTransactionFinalized: time.Time{}, + TimeTransactionPosted: time.Time{}, + TimeTransactionSeen: time.Time{}, + TimeCompleted: time.Time{}, + } - adm.GET(routes.GetChainNodeConnectionMetrics(":chainID"), s.handleGetChainStats). + adm.GET(routes.GetChainConsensusWorkflowStatus(":chainID"), cms.handleGetChainConsensusWorkflowStatus). SetSummary("Get chain state statistics for the given chain ID"). AddParamPath("", "chainID", "ChainID (base58)"). - AddResponse(http.StatusOK, "Chain Stats", chainExample, nil) + AddResponse(http.StatusOK, "Chain Stats", example, nil) } -type chainStatsService struct { +type chainMetricsService struct { chains chains.Provider } -func (cssT *chainStatsService) handleGetChainsStats(c echo.Context) error { +func (cssT *chainMetricsService) handleGetChainsNodeConnMetrics(c echo.Context) error { metrics := cssT.chains().GetNodeConnectionMetrics() metricsModel := model.NewNodeConnectionMetrics(metrics) return c.JSON(http.StatusOK, metricsModel) } -func (cssT *chainStatsService) handleGetChainStats(c echo.Context) error { +func (cssT *chainMetricsService) handleGetChainNodeConnMetrics(c echo.Context) error { chainID, err := iscp.ChainIDFromBase58(c.Param("chainID")) if err != nil { return httperrors.BadRequest(err.Error()) @@ -103,3 +136,26 @@ func (cssT *chainStatsService) handleGetChainStats(c echo.Context) error { return c.JSON(http.StatusOK, metricsModel) } + +func (cssT *chainMetricsService) handleGetChainConsensusWorkflowStatus(c echo.Context) error { + theChain, err := cssT.getChain(c) + if err != nil { + return err + } + status := theChain.GetConsensusWorkflowStatus() + statusModel := model.NewConsensusWorkflowStatus(status) + + return c.JSON(http.StatusOK, statusModel) +} + +func (cssT *chainMetricsService) getChain(c echo.Context) (chain.Chain, error) { + chainID, err := iscp.ChainIDFromBase58(c.Param("chainID")) + if err != nil { + return nil, httperrors.BadRequest(err.Error()) + } + theChain := cssT.chains().Get(chainID) + if theChain == nil { + return nil, httperrors.NotFound(fmt.Sprintf("Active chain %s not found", chainID)) + } + return theChain, nil +} diff --git a/packages/webapi/admapi/chainrecord.go b/packages/webapi/admapi/chainrecord.go index 3695386308..3abe182b86 100644 --- a/packages/webapi/admapi/chainrecord.go +++ b/packages/webapi/admapi/chainrecord.go @@ -55,7 +55,10 @@ func (s *chainRecordService) handlePutChainRecord(c echo.Context) error { return err } if bd2 != nil { - return httperrors.Conflict(fmt.Sprintf("Record already exists: %s", bd.ChainID.String())) + // Make this call idempotent. + // Record has no information apart from the ChainID and activation status. + // So just keep the existing, if it exists. + return c.NoContent(http.StatusCreated) } if err := reg.SaveChainRecord(bd); err != nil { return err diff --git a/packages/webapi/admapi/committeerecord.go b/packages/webapi/admapi/committeerecord.go deleted file mode 100644 index 998f6bb2a7..0000000000 --- a/packages/webapi/admapi/committeerecord.go +++ /dev/null @@ -1,112 +0,0 @@ -package admapi - -import ( - "fmt" - "net/http" - "strconv" - - "github.com/iotaledger/goshimmer/packages/ledgerstate" - "github.com/iotaledger/wasp/packages/chains" - "github.com/iotaledger/wasp/packages/iscp" - "github.com/iotaledger/wasp/packages/registry" - "github.com/iotaledger/wasp/packages/webapi/httperrors" - "github.com/iotaledger/wasp/packages/webapi/model" - "github.com/iotaledger/wasp/packages/webapi/routes" - "github.com/labstack/echo/v4" - "github.com/pangpanglabs/echoswagger/v2" -) - -func addCommitteeRecordEndpoints(adm echoswagger.ApiGroup, registryProvider registry.Provider, chainsProvider chains.Provider) { - rnd1 := iscp.RandomChainID() - example := model.CommitteeRecord{ - Address: model.NewAddress(rnd1.AsAddress()), - Nodes: []string{"wasp1.example.org:4000", "wasp2.example.org:4000", "wasp3.example.org:4000"}, - } - - s := &committeeRecordService{registryProvider, chainsProvider} - - adm.POST(routes.PutCommitteeRecord(), s.handlePutCommitteeRecord). - SetSummary("Create a new committee record"). - AddParamBody(example, "Record", "Committee record", true) - - adm.GET(routes.GetCommitteeRecord(":address"), s.handleGetCommitteeRecord). - SetSummary("Find the committee record for the given address"). - AddParamPath("", "address", "Address (base58)"). - AddResponse(http.StatusOK, "Committee Record", example, nil) - - adm.GET(routes.GetCommitteeForChain(":chainID"), s.handleGetCommitteeForChain). - SetSummary("Find the committee record that manages the given chain"). - AddParamPath("", "chainID", "ChainID (base58)"). - AddResponse(http.StatusOK, "Committee Record", example, nil) -} - -type committeeRecordService struct { - registry registry.Provider - chains chains.Provider -} - -func (s *committeeRecordService) handlePutCommitteeRecord(c echo.Context) error { - var req model.CommitteeRecord - - if err := c.Bind(&req); err != nil { - return httperrors.BadRequest("Invalid request body") - } - - cr := req.Record() - - defaultRegistry := s.registry() - bd2, err := defaultRegistry.GetCommitteeRecord(cr.Address) - if err != nil { - return err - } - if bd2 != nil { - return httperrors.Conflict(fmt.Sprintf("Record already exists: %s", cr.Address.Base58())) - } - // TODO if I am not among committee nodes, should not save - if err := defaultRegistry.SaveCommitteeRecord(cr); err != nil { - return err - } - - log.Infof("Committee record saved. Address: %s", cr.String()) - - return c.NoContent(http.StatusCreated) -} - -func (s *committeeRecordService) handleGetCommitteeRecord(c echo.Context) error { - address, err := ledgerstate.AddressFromBase58EncodedString(c.Param("address")) - if err != nil { - return httperrors.BadRequest(err.Error()) - } - cr, err := s.registry().GetCommitteeRecord(address) - if err != nil { - return err - } - if cr == nil { - return httperrors.NotFound(fmt.Sprintf("Record not found: %s", address)) - } - return c.JSON(http.StatusOK, model.NewCommitteeRecord(cr)) -} - -func (s *committeeRecordService) handleGetCommitteeForChain(c echo.Context) error { - chainID, err := iscp.ChainIDFromBase58(c.Param("chainID")) - if err != nil { - return httperrors.BadRequest(err.Error()) - } - includeDeactivated, _ := strconv.ParseBool(c.QueryParam("includeDeactivated")) - chain := s.chains().Get(chainID, includeDeactivated) - if chain == nil { - return httperrors.NotFound(fmt.Sprintf("Active chain %s not found", chainID)) - } - committeeInfo := chain.GetCommitteeInfo() - if committeeInfo == nil { - return httperrors.NotFound(fmt.Sprintf("Committee info for chain %s is not available", chainID)) - } - cr, err := s.registry().GetCommitteeRecord(committeeInfo.Address) - if err != nil { - return err - } - if cr == nil { - return httperrors.NotFound(fmt.Sprintf("Committee record not found for address: %s", committeeInfo.Address.Base58())) - } - return c.JSON(http.StatusOK, model.NewCommitteeRecord(cr)) -} diff --git a/packages/webapi/admapi/dkshares.go b/packages/webapi/admapi/dkshares.go index 12e14778ed..220c7a78bb 100644 --- a/packages/webapi/admapi/dkshares.go +++ b/packages/webapi/admapi/dkshares.go @@ -26,7 +26,6 @@ import ( func addDKSharesEndpoints(adm echoswagger.ApiGroup, registryProvider registry.Provider, nodeProvider dkg.NodeProvider) { requestExample := model.DKSharesPostRequest{ - PeerNetIDs: []string{"wasp1:4000", "wasp2:4000", "wasp3:4000", "wasp4:4000"}, PeerPubKeys: []string{base64.StdEncoding.EncodeToString([]byte("key"))}, Threshold: 3, TimeoutMS: 10000, @@ -36,11 +35,12 @@ func addDKSharesEndpoints(adm echoswagger.ApiGroup, registryProvider registry.Pr Address: addr1.Base58(), SharedPubKey: base64.StdEncoding.EncodeToString([]byte("key")), PubKeyShares: []string{base64.StdEncoding.EncodeToString([]byte("key"))}, + PeerPubKeys: []string{base64.StdEncoding.EncodeToString([]byte("key"))}, Threshold: 3, PeerIndex: nil, } - s := &dkSharesService{registryProvider, nodeProvider} + s := &dkSharesService{registry: registryProvider, dkgNode: nodeProvider} adm.POST(routes.DKSharesPost(), s.handleDKSharesPost). AddParamBody(requestExample, "DKSharesPostRequest", "Request parameters", true). @@ -66,23 +66,24 @@ func (s *dkSharesService) handleDKSharesPost(c echo.Context) error { return httperrors.BadRequest("Invalid request body.") } - if req.PeerPubKeys != nil && len(req.PeerNetIDs) != len(req.PeerPubKeys) { - return httperrors.BadRequest("Inconsistent PeerNetIDs and PeerPubKeys.") + if req.PeerPubKeys == nil || len(req.PeerPubKeys) < 1 { + return httperrors.BadRequest("PeerPubKeys are mandatory") } - var peerPubKeys []ed25519.PublicKey + var peerPubKeys []*ed25519.PublicKey if req.PeerPubKeys != nil { - peerPubKeys = make([]ed25519.PublicKey, len(req.PeerPubKeys)) + peerPubKeys = make([]*ed25519.PublicKey, len(req.PeerPubKeys)) for i := range req.PeerPubKeys { - if peerPubKeys[i], err = ed25519.PublicKeyFromString(req.PeerPubKeys[i]); err != nil { + peerPubKey, err := ed25519.PublicKeyFromString(req.PeerPubKeys[i]) + if err != nil { return httperrors.BadRequest(fmt.Sprintf("Invalid PeerPubKeys[%v]=%v", i, req.PeerPubKeys[i])) } + peerPubKeys[i] = &peerPubKey } } var dkShare *tcrypto.DKShare dkShare, err = s.dkgNode().GenerateDistributedKey( - req.PeerNetIDs, peerPubKeys, req.Threshold, 1*time.Second, @@ -138,10 +139,16 @@ func makeDKSharesInfo(dkShare *tcrypto.DKShare) (*model.DKSharesInfo, error) { pubKeyShares[i] = base64.StdEncoding.EncodeToString(b) } + peerPubKeys := make([]string, len(dkShare.NodePubKeys)) + for i := range dkShare.NodePubKeys { + peerPubKeys[i] = base64.StdEncoding.EncodeToString(dkShare.NodePubKeys[i].Bytes()) + } + return &model.DKSharesInfo{ Address: dkShare.Address.Base58(), SharedPubKey: sharedPubKey, PubKeyShares: pubKeyShares, + PeerPubKeys: peerPubKeys, Threshold: dkShare.T, PeerIndex: dkShare.Index, }, nil diff --git a/packages/webapi/admapi/endpoints.go b/packages/webapi/admapi/endpoints.go index 83df3e783b..2358e8bfe3 100644 --- a/packages/webapi/admapi/endpoints.go +++ b/packages/webapi/admapi/endpoints.go @@ -14,6 +14,7 @@ import ( "github.com/iotaledger/wasp/packages/parameters" "github.com/iotaledger/wasp/packages/peering" "github.com/iotaledger/wasp/packages/registry" + "github.com/iotaledger/wasp/packages/wal" "github.com/labstack/echo/v4" "github.com/pangpanglabs/echoswagger/v2" ) @@ -34,6 +35,7 @@ func AddEndpoints( nodeProvider dkg.NodeProvider, shutdown ShutdownFunc, metrics *metricspkg.Metrics, + w *wal.WAL, ) { initLogger() @@ -46,10 +48,10 @@ func AddEndpoints( } addShutdownEndpoint(adm, shutdown) + addNodeOwnerEndpoints(adm, registryProvider) addChainRecordEndpoints(adm, registryProvider) - addChainStatsEndpoints(adm, chainsProvider) - addCommitteeRecordEndpoints(adm, registryProvider, chainsProvider) - addChainEndpoints(adm, registryProvider, chainsProvider, metrics) + addChainMetricsEndpoints(adm, chainsProvider) + addChainEndpoints(adm, registryProvider, chainsProvider, network, metrics, w) addDKSharesEndpoints(adm, registryProvider, nodeProvider) addPeeringEndpoints(adm, network, tnm) } diff --git a/packages/webapi/admapi/node_owner.go b/packages/webapi/admapi/node_owner.go new file mode 100644 index 0000000000..3e055338fc --- /dev/null +++ b/packages/webapi/admapi/node_owner.go @@ -0,0 +1,88 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package admapi + +import ( + "bytes" + "net/http" + + "github.com/iotaledger/goshimmer/packages/ledgerstate" + "github.com/iotaledger/wasp/packages/parameters" + "github.com/iotaledger/wasp/packages/registry" + "github.com/iotaledger/wasp/packages/vm/core/governance" + "github.com/iotaledger/wasp/packages/webapi/httperrors" + "github.com/iotaledger/wasp/packages/webapi/model" + "github.com/iotaledger/wasp/packages/webapi/routes" + "github.com/labstack/echo/v4" + "github.com/pangpanglabs/echoswagger/v2" +) + +func addNodeOwnerEndpoints(adm echoswagger.ApiGroup, registryProvider registry.Provider) { + addCtx := func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + c.Set("reg", registryProvider) + return next(c) + } + } + reqExample := model.NodeOwnerCertificateRequest{ + NodePubKey: model.NewBytes([]byte{0, 1, 17}), + OwnerAddress: model.Address("any_address"), + } + resExample := model.NodeOwnerCertificateResponse{ + Certificate: model.NewBytes([]byte{0, 1, 17, 19}), + } + adm.POST(routes.AdmNodeOwnerCertificate(), handleAdmNodeOwnerCertificate, addCtx). + AddParamBody(reqExample, "Request", "Certificate request", true). + AddResponse(http.StatusOK, "Generated certificate.", resExample, nil). + SetSummary("Provides a certificate, if the node recognizes the owner.") +} + +func handleAdmNodeOwnerCertificate(c echo.Context) error { + registryProvider := c.Get("reg").(registry.Provider) + + var req model.NodeOwnerCertificateRequest + if err := c.Bind(&req); err != nil { + return httperrors.BadRequest("Invalid request body") + } + reqOwnerAddress := req.OwnerAddress.Address() + reqNodePubKeyBytes := req.NodePubKey.Bytes() + + nodeIdentity, err := registryProvider().GetNodeIdentity() + if err != nil { + return err + } + + // + // Check, if supplied node PubKey matches. + if !bytes.Equal(nodeIdentity.PublicKey.Bytes(), reqNodePubKeyBytes) { + return &httperrors.HTTPError{Code: 400, Message: "Wrong NodePubKey"} + } + + // + // Check, if owner is presented in the configuration. + nodeOwnerAddresses := parameters.GetStringSlice(parameters.NodeOwnerAddresses) + ownerAuthorized := false + for _, nodeOwnerAddress := range nodeOwnerAddresses { + nodeOwnerAddress, err := ledgerstate.AddressFromBase58EncodedString(nodeOwnerAddress) + if err != nil { + continue + } + if bytes.Equal(reqOwnerAddress.Bytes(), nodeOwnerAddress.Bytes()) { + ownerAuthorized = true + break + } + } + if !ownerAuthorized { + return &httperrors.HTTPError{Code: 403, Message: "unauthorized"} + } + + // + // Create the certificate. It consists of signature only. The data is not included. + cert := governance.NewNodeOwnershipCertificate(nodeIdentity, reqOwnerAddress) + resp := model.NodeOwnerCertificateResponse{ + Certificate: model.NewBytes(cert.Bytes()), + } + + return c.JSON(http.StatusOK, resp) +} diff --git a/packages/webapi/endpoints.go b/packages/webapi/endpoints.go index 24e4af5ea5..0c35c3e5e6 100644 --- a/packages/webapi/endpoints.go +++ b/packages/webapi/endpoints.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package webapi import ( @@ -11,6 +14,7 @@ import ( "github.com/iotaledger/wasp/packages/parameters" "github.com/iotaledger/wasp/packages/peering" "github.com/iotaledger/wasp/packages/registry" + "github.com/iotaledger/wasp/packages/wal" "github.com/iotaledger/wasp/packages/webapi/admapi" "github.com/iotaledger/wasp/packages/webapi/info" "github.com/iotaledger/wasp/packages/webapi/reqstatus" @@ -33,6 +37,7 @@ func Init( nodeProvider dkg.NodeProvider, shutdown admapi.ShutdownFunc, metrics *metricspkg.Metrics, + w *wal.WAL, ) { log = logger.NewLogger("WebAPI") @@ -50,6 +55,7 @@ func Init( chainsProvider.ChainProvider(), webapiutil.GetAccountBalance, webapiutil.HasRequestBeenProcessed, + network.Self().PubKey(), time.Duration(parameters.GetInt(parameters.OffledgerAPICacheTTL))*time.Second, log, ) @@ -65,6 +71,7 @@ func Init( nodeProvider, shutdown, metrics, + w, ) log.Infof("added web api endpoints") } diff --git a/packages/webapi/model/chain_info.go b/packages/webapi/model/chain_info.go new file mode 100644 index 0000000000..76df19c84f --- /dev/null +++ b/packages/webapi/model/chain_info.go @@ -0,0 +1,20 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package model + +type ChainInfo struct { + ChainID ChainID `swagger:"desc(ChainID (base58-encoded))"` + Active bool `swagger:"desc(Whether or not the chain is active)"` + StateAddress Address `swagger:"desc(State address, if we are part of it.)"` + CommitteeNodes []*ChainNodeStatus `swagger:"desc(Committee nodes and their peering info.)"` + AccessNodes []*ChainNodeStatus `swagger:"desc(Access nodes and their peering info.)"` + CandidateNodes []*ChainNodeStatus `swagger:"desc(Candidate nodes and their peering info.)"` +} + +type ChainNodeStatus struct { + Node PeeringNodeStatus + ForCommittee bool + ForAccess bool + AccessAPI string +} diff --git a/packages/webapi/model/chain_record.go b/packages/webapi/model/chain_record.go index 8b5860bda9..e23440db39 100644 --- a/packages/webapi/model/chain_record.go +++ b/packages/webapi/model/chain_record.go @@ -1,18 +1,19 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package model import "github.com/iotaledger/wasp/packages/registry" type ChainRecord struct { - ChainID ChainID `swagger:"desc(ChainID (base58-encoded))"` - Active bool `swagger:"desc(Whether or not the chain is active)"` - Peers []string `swagger:"desc(List of peers/access nodes (network IDs))"` + ChainID ChainID `swagger:"desc(ChainID (base58-encoded))"` + Active bool `swagger:"desc(Whether or not the chain is active)"` } func NewChainRecord(rec *registry.ChainRecord) *ChainRecord { return &ChainRecord{ ChainID: NewChainID(rec.ChainID), Active: rec.Active, - Peers: rec.Peers, } } @@ -20,6 +21,5 @@ func (bd *ChainRecord) Record() *registry.ChainRecord { return ®istry.ChainRecord{ ChainID: bd.ChainID.ChainID(), Active: bd.Active, - Peers: bd.Peers, } } diff --git a/packages/webapi/model/committee_record.go b/packages/webapi/model/committee_record.go deleted file mode 100644 index 0f1c297c09..0000000000 --- a/packages/webapi/model/committee_record.go +++ /dev/null @@ -1,22 +0,0 @@ -package model - -import "github.com/iotaledger/wasp/packages/registry" - -type CommitteeRecord struct { - Address Address `swagger:"desc(Committee address (base58-encoded))"` - Nodes []string `swagger:"desc(List of committee nodes (network IDs))"` -} - -func NewCommitteeRecord(bd *registry.CommitteeRecord) *CommitteeRecord { - return &CommitteeRecord{ - Address: NewAddress(bd.Address), - Nodes: bd.Nodes, - } -} - -func (bd *CommitteeRecord) Record() *registry.CommitteeRecord { - return ®istry.CommitteeRecord{ - Address: bd.Address.Address(), - Nodes: bd.Nodes, - } -} diff --git a/packages/webapi/model/consensus_metrics.go b/packages/webapi/model/consensus_metrics.go new file mode 100644 index 0000000000..be1841eed4 --- /dev/null +++ b/packages/webapi/model/consensus_metrics.go @@ -0,0 +1,51 @@ +package model + +import ( + "time" + + "github.com/iotaledger/wasp/packages/chain" +) + +type ConsensusWorkflowStatus struct { + FlagStateReceived bool `swagger:"desc(Shows if state output is received in current consensus iteration)"` + FlagBatchProposalSent bool `swagger:"desc(Shows if batch proposal is sent out in current consensus iteration)"` + FlagConsensusBatchKnown bool `swagger:"desc(Shows if consensus on batch is reached and known in current consensus iteration)"` + FlagVMStarted bool `swagger:"desc(Shows if virtual machine is started in current consensus iteration)"` + FlagVMResultSigned bool `swagger:"desc(Shows if virtual machine has returned its results in current consensus iteration)"` + FlagTransactionFinalized bool `swagger:"desc(Shows if consensus on transaction is reached in current consensus iteration)"` + FlagTransactionPosted bool `swagger:"desc(Shows if transaction is posted to L1 in current consensus iteration)"` + FlagTransactionSeen bool `swagger:"desc(Shows if L1 reported that it has seen the transaction of current consensus iteration)"` + FlagInProgress bool `swagger:"desc(Shows if consensus algorithm is still not completed in current consensus iteration)"` + + TimeBatchProposalSent time.Time `swagger:"desc(Shows when batch proposal was last sent out in current consensus iteration)"` + TimeConsensusBatchKnown time.Time `swagger:"desc(Shows when ACS results of consensus on batch was last received in current consensus iteration)"` + TimeVMStarted time.Time `swagger:"desc(Shows when virtual machine was last started in current consensus iteration)"` + TimeVMResultSigned time.Time `swagger:"desc(Shows when virtual machine results were last received and signed in current consensus iteration)"` + TimeTransactionFinalized time.Time `swagger:"desc(Shows when algorithm last noted that all the data for consensus on transaction had been received in current consensus iteration)"` + TimeTransactionPosted time.Time `swagger:"desc(Shows when transaction was last posted to L1 in current consensus iteration)"` + TimeTransactionSeen time.Time `swagger:"desc(Shows when algorithm last noted that transaction hadd been seen by L1 in current consensus iteration)"` + TimeCompleted time.Time `swagger:"desc(Shows when algorithm was last completed in current consensus iteration)"` +} + +func NewConsensusWorkflowStatus(status chain.ConsensusWorkflowStatus) *ConsensusWorkflowStatus { + return &ConsensusWorkflowStatus{ + FlagStateReceived: status.IsStateReceived(), + FlagBatchProposalSent: status.IsBatchProposalSent(), + FlagConsensusBatchKnown: status.IsConsensusBatchKnown(), + FlagVMStarted: status.IsVMStarted(), + FlagVMResultSigned: status.IsVMResultSigned(), + FlagTransactionFinalized: status.IsTransactionFinalized(), + FlagTransactionPosted: status.IsTransactionPosted(), + FlagTransactionSeen: status.IsTransactionSeen(), + FlagInProgress: status.IsInProgress(), + + TimeBatchProposalSent: status.GetBatchProposalSentTime(), + TimeConsensusBatchKnown: status.GetConsensusBatchKnownTime(), + TimeVMStarted: status.GetVMStartedTime(), + TimeVMResultSigned: status.GetVMResultSignedTime(), + TimeTransactionFinalized: status.GetTransactionFinalizedTime(), + TimeTransactionPosted: status.GetTransactionPostedTime(), + TimeTransactionSeen: status.GetTransactionSeenTime(), + TimeCompleted: status.GetCompletedTime(), + } +} diff --git a/packages/webapi/model/dkshares.go b/packages/webapi/model/dkshares.go index d76f71cb8a..4e8388360b 100644 --- a/packages/webapi/model/dkshares.go +++ b/packages/webapi/model/dkshares.go @@ -5,7 +5,6 @@ package model // DKSharesPostRequest is a POST request for creating new DKShare. type DKSharesPostRequest struct { - PeerNetIDs []string `json:"peerNetIDs" swagger:"desc(NetIDs of the nodes sharing the key.)"` PeerPubKeys []string `json:"peerPubKeys" swagger:"desc(Optional, base64 encoded public keys of the peers generating the DKS.)"` Threshold uint16 `json:"threshold" swagger:"desc(Should be =< len(PeerPubKeys))"` TimeoutMS uint32 `json:"timeoutMS" swagger:"desc(Timeout in milliseconds.)"` @@ -16,6 +15,7 @@ type DKSharesInfo struct { Address string `json:"address" swagger:"desc(New generated shared address.)"` SharedPubKey string `json:"sharedPubKey" swagger:"desc(Shared public key (base64-encoded).)"` PubKeyShares []string `json:"pubKeyShares" swagger:"desc(Public key shares for all the peers (base64-encoded).)"` + PeerPubKeys []string `json:"peerPubKeys" swagger:"desc(Public keys of the nodes sharing the key (base64-encoded).)"` Threshold uint16 `json:"threshold"` PeerIndex *uint16 `json:"peerIndex" swagger:"desc(Index of the node returning the share, if it is a member of the sharing group.)"` } diff --git a/packages/webapi/model/node_owner_certificate.go b/packages/webapi/model/node_owner_certificate.go new file mode 100644 index 0000000000..c6f3fb071b --- /dev/null +++ b/packages/webapi/model/node_owner_certificate.go @@ -0,0 +1,13 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package model + +type NodeOwnerCertificateRequest struct { + NodePubKey Bytes `swagger:"desc(Node pub key. (base64))"` + OwnerAddress Address `swagger:"desc(Node owner address. (base64))"` +} + +type NodeOwnerCertificateResponse struct { + Certificate Bytes `swagger:"desc(Certificate stating the ownership. (base64))"` +} diff --git a/packages/webapi/request/request.go b/packages/webapi/request/request.go index 385fbb039a..a21626e87b 100644 --- a/packages/webapi/request/request.go +++ b/packages/webapi/request/request.go @@ -7,6 +7,7 @@ import ( "strings" "time" + "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/hive.go/marshalutil" "github.com/iotaledger/wasp/packages/chain" @@ -33,6 +34,7 @@ func AddEndpoints( getChain chains.ChainProvider, getChainBalance getAccountBalanceFn, hasRequestBeenProcessed hasRequestBeenProcessedFn, + nodePubKey *ed25519.PublicKey, cacheTTL time.Duration, log *logger.Logger, ) { @@ -41,6 +43,7 @@ func AddEndpoints( getAccountBalance: getChainBalance, hasRequestBeenProcessed: hasRequestBeenProcessed, requestsCache: expiringcache.New(cacheTTL), + nodePubKey: nodePubKey, log: log, } server.POST(routes.NewRequest(":chainID"), instance.handleNewRequest). @@ -59,6 +62,7 @@ type offLedgerReqAPI struct { getAccountBalance getAccountBalanceFn hasRequestBeenProcessed hasRequestBeenProcessedFn requestsCache *expiringcache.ExpiringCache + nodePubKey *ed25519.PublicKey log *logger.Logger } @@ -120,7 +124,7 @@ func (o *offLedgerReqAPI) handleNewRequest(c echo.Context) error { ChainID: ch.ID(), Req: offLedgerReq, }, - SenderNetID: "", + SenderPubKey: o.nodePubKey, }) return c.NoContent(http.StatusAccepted) diff --git a/packages/webapi/request/request_test.go b/packages/webapi/request/request_test.go index 028c8295e6..ecf7553448 100644 --- a/packages/webapi/request/request_test.go +++ b/packages/webapi/request/request_test.go @@ -72,6 +72,10 @@ func (m *mockedChain) GetNodeConnectionMetrics() nodeconnmetrics.NodeConnectionM panic("implement me") } +func (m *mockedChain) GetConsensusWorkflowStatus() chain.ConsensusWorkflowStatus { + panic("implement me") +} + // private methods func createMockedGetChain(t *testing.T) chains.ChainProvider { diff --git a/packages/webapi/routes/routes.go b/packages/webapi/routes/routes.go index 1cbcc0e815..e7b741fbad 100644 --- a/packages/webapi/routes/routes.go +++ b/packages/webapi/routes/routes.go @@ -35,6 +35,10 @@ func DeactivateChain(chainID string) string { return "/adm/chain/" + chainID + "/deactivate" } +func GetChainInfo(chainID string) string { + return "/adm/chain/" + chainID + "/info" +} + func ListChainRecords() string { return "/adm/chainrecords" } @@ -47,14 +51,6 @@ func GetChainRecord(chainID string) string { return "/adm/chainrecord/" + chainID } -func PutCommitteeRecord() string { - return "/adm/committeerecord" -} - -func GetCommitteeRecord(addr string) string { - return "/adm/committeerecord/" + addr -} - func GetChainsNodeConnectionMetrics() string { return "/adm/chain/nodeconn/metrics" } @@ -63,8 +59,8 @@ func GetChainNodeConnectionMetrics(chainID string) string { return "/adm/chain/" + chainID + "/nodeconn/metrics" } -func GetCommitteeForChain(chainID string) string { - return "/adm/chain/" + chainID + "/committeerecord" +func GetChainConsensusWorkflowStatus(chainID string) string { + return "/adm/chain/" + chainID + "/consensus/status" } func DKSharesPost() string { @@ -103,6 +99,10 @@ func PeeringTrustedDelete(pubKey string) string { return PeeringTrustedGet(pubKey) } +func AdmNodeOwnerCertificate() string { + return "/adm/node/owner/certificate" +} + func Shutdown() string { return "/adm/shutdown" } diff --git a/plugins/chains/plugin.go b/plugins/chains/plugin.go index 252423ff76..735a0df90d 100644 --- a/plugins/chains/plugin.go +++ b/plugins/chains/plugin.go @@ -18,6 +18,7 @@ import ( "github.com/iotaledger/wasp/plugins/peering" "github.com/iotaledger/wasp/plugins/processors" "github.com/iotaledger/wasp/plugins/registry" + "github.com/iotaledger/wasp/plugins/wal" ) const PluginName = "Chains" @@ -52,7 +53,7 @@ func run(_ *node.Plugin) { allMetrics = metrics.AllMetrics() } allChains.SetNodeConn(nodeconnimpl.NewNodeConnection(nodeconn.NodeConnection(), allMetrics.GetNodeConnectionMetrics(), log)) - if err := allChains.ActivateAllFromRegistry(registry.DefaultRegistry, allMetrics); err != nil { + if err := allChains.ActivateAllFromRegistry(registry.DefaultRegistry, allMetrics, wal.GetWAL()); err != nil { log.Errorf("failed to read chain activation records from registry: %v", err) return } diff --git a/plugins/config/plugin.go b/plugins/config/plugin.go index 04fc726101..87c44208ab 100644 --- a/plugins/config/plugin.go +++ b/plugins/config/plugin.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package config import ( diff --git a/plugins/dashboard/plugin.go b/plugins/dashboard/plugin.go index ce99ef1522..e0c703b325 100644 --- a/plugins/dashboard/plugin.go +++ b/plugins/dashboard/plugin.go @@ -123,6 +123,14 @@ func (w *waspServices) GetNodeConnectionMetrics() (nodeconnmetrics.NodeConnectio return chs.GetNodeConnectionMetrics(), nil } +func (w *waspServices) GetChainConsensusWorkflowStatus(chainID *iscp.ChainID) (chain.ConsensusWorkflowStatus, error) { + ch := chains.AllChains().Get(chainID) + if ch == nil { + return nil, echo.NewHTTPError(http.StatusNotFound, "Chain not found") + } + return ch.GetConsensusWorkflowStatus(), nil +} + func (w *waspServices) CallView(chainID *iscp.ChainID, scName, funName string, params dict.Dict) (dict.Dict, error) { ch := chains.AllChains().Get(chainID) if ch == nil { diff --git a/plugins/wal/plugin.go b/plugins/wal/plugin.go new file mode 100644 index 0000000000..0666c754cc --- /dev/null +++ b/plugins/wal/plugin.go @@ -0,0 +1,35 @@ +package wal + +import ( + "github.com/iotaledger/hive.go/logger" + "github.com/iotaledger/hive.go/node" + "github.com/iotaledger/wasp/packages/parameters" + "github.com/iotaledger/wasp/packages/wal" +) + +const PluginName = "Wal" + +var ( + log *logger.Logger + w *wal.WAL +) + +func Init() *node.Plugin { + return node.NewPlugin(PluginName, node.Enabled, configure, run) +} + +func configure(_ *node.Plugin) { + if !parameters.GetBool(parameters.WALEnabled) { + return + } + log = logger.NewLogger(PluginName) + walDir := parameters.GetString(parameters.WALDirectory) + w = wal.New(log, walDir) +} + +func run(_ *node.Plugin) { +} + +func GetWAL() *wal.WAL { + return w +} diff --git a/plugins/webapi/plugin.go b/plugins/webapi/plugin.go index 3f29aea4aa..80d17a493a 100644 --- a/plugins/webapi/plugin.go +++ b/plugins/webapi/plugin.go @@ -22,6 +22,7 @@ import ( "github.com/iotaledger/wasp/plugins/metrics" "github.com/iotaledger/wasp/plugins/peering" "github.com/iotaledger/wasp/plugins/registry" + "github.com/iotaledger/wasp/plugins/wal" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" "github.com/pangpanglabs/echoswagger/v2" @@ -86,6 +87,7 @@ func configure(*node.Plugin) { dkg.DefaultNode, gracefulshutdown.Shutdown, allMetrics, + wal.GetWAL(), ) } diff --git a/tools/cluster/cluster.go b/tools/cluster/cluster.go index ae88e61b2c..4a3fa0e71a 100644 --- a/tools/cluster/cluster.go +++ b/tools/cluster/cluster.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package cluster import ( @@ -17,12 +20,14 @@ import ( "github.com/iotaledger/goshimmer/packages/ledgerstate" "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/wasp/client" + "github.com/iotaledger/wasp/client/chainclient" "github.com/iotaledger/wasp/client/goshimmer" "github.com/iotaledger/wasp/client/multiclient" "github.com/iotaledger/wasp/packages/apilib" "github.com/iotaledger/wasp/packages/iscp/colored" "github.com/iotaledger/wasp/packages/testutil/testkey" "github.com/iotaledger/wasp/packages/util" + "github.com/iotaledger/wasp/packages/vm/core/governance" "github.com/iotaledger/wasp/packages/webapi/model" "github.com/iotaledger/wasp/packages/webapi/routes" "github.com/iotaledger/wasp/tools/cluster/mocknode" @@ -31,10 +36,11 @@ import ( ) type Cluster struct { - Name string - Config *ClusterConfig - Started bool - DataPath string + Name string + Config *ClusterConfig + Started bool + DataPath string + ValidatorSeed *seed.Seed // Default identity for validators, chain owners, etc. goshimmer *mocknode.MockNode waspCmds []*exec.Cmd @@ -42,12 +48,17 @@ type Cluster struct { func New(name string, config *ClusterConfig) *Cluster { return &Cluster{ - Name: name, - Config: config, - waspCmds: make([]*exec.Cmd, config.Wasp.NumNodes), + Name: name, + Config: config, + ValidatorSeed: seed.NewSeed(), + waspCmds: make([]*exec.Cmd, config.Wasp.NumNodes), } } +func (clu *Cluster) ValidatorAddress() ledgerstate.Address { + return clu.ValidatorSeed.Address(0).Address() +} + func (clu *Cluster) NewKeyPairWithFunds() (*ed25519.KeyPair, ledgerstate.Address, error) { key, addr := testkey.GenKeyAddr() err := clu.GoshimmerClient().RequestFunds(addr) @@ -102,10 +113,18 @@ func (clu *Cluster) RunDKG(committeeNodes []int, threshold uint16, timeout ...ti threshold = (uint16(len(committeeNodes))*2)/3 + 1 } apiHosts := clu.Config.APIHosts(committeeNodes) - peeringHosts := clu.Config.PeeringHosts(committeeNodes) + + peerPubKeys := make([]string, 0) + for _, i := range committeeNodes { + peeringNodeInfo, err := clu.WaspClient(i).GetPeeringSelf() + if err != nil { + return nil, err + } + peerPubKeys = append(peerPubKeys, peeringNodeInfo.PubKey) + } dkgInitiatorIndex := uint16(rand.Intn(len(apiHosts))) - return apilib.RunDKG(apiHosts, peeringHosts, threshold, dkgInitiatorIndex, timeout...) + return apilib.RunDKG(apiHosts, peerPubKeys, threshold, dkgInitiatorIndex, timeout...) } func (clu *Cluster) DeployChainWithDKG(description string, allPeers, committeeNodes []int, quorum uint16) (*Chain, error) { @@ -117,15 +136,13 @@ func (clu *Cluster) DeployChainWithDKG(description string, allPeers, committeeNo } func (clu *Cluster) DeployChain(description string, allPeers, committeeNodes []int, quorum uint16, stateAddr ledgerstate.Address) (*Chain, error) { - ownerSeed := seed.NewSeed() - if len(allPeers) == 0 { allPeers = clu.Config.AllNodes() } chain := &Chain{ Description: description, - OriginatorSeed: ownerSeed, + OriginatorSeed: clu.ValidatorSeed, AllPeers: allPeers, CommitteeNodes: committeeNodes, Quorum: quorum, @@ -139,29 +156,81 @@ func (clu *Cluster) DeployChain(description string, allPeers, committeeNodes []i return nil, xerrors.Errorf("DeployChain: %w", err) } - chainid, err := apilib.DeployChain(apilib.CreateChainParams{ - Node: clu.GoshimmerClient(), - AllAPIHosts: chain.AllAPIHosts(), - AllPeeringHosts: chain.AllPeeringHosts(), - CommitteeAPIHosts: chain.CommitteeAPIHosts(), - CommitteePeeringHosts: chain.CommitteePeeringHosts(), - N: uint16(len(committeeNodes)), - T: quorum, - OriginatorKeyPair: chain.OriginatorKeyPair(), - Description: description, - Textout: os.Stdout, - Prefix: "[cluster] ", + committeePubKeys := make([]string, 0) + for _, i := range chain.CommitteeNodes { + peeringNode, err := clu.WaspClient(i).GetPeeringSelf() + if err != nil { + return nil, err + } + committeePubKeys = append(committeePubKeys, peeringNode.PubKey) + } + + chainID, err := apilib.DeployChain(apilib.CreateChainParams{ + Node: clu.GoshimmerClient(), + CommitteeAPIHosts: chain.CommitteeAPIHosts(), + CommitteePubKeys: committeePubKeys, + N: uint16(len(committeeNodes)), + T: quorum, + OriginatorKeyPair: chain.OriginatorKeyPair(), + Description: description, + Textout: os.Stdout, + Prefix: "[cluster] ", }, stateAddr) if err != nil { return nil, xerrors.Errorf("DeployChain: %w", err) } chain.StateAddress = stateAddr - chain.ChainID = chainid + chain.ChainID = chainID + + // + // Register all non-committee nodes as access nodes. + for _, a := range allPeers { + if err := clu.AddAccessNode(a, chain); err != nil { + return nil, err + } + } return chain, nil } +// AddAccessNode introduces node at accessNodeIndex as an access node to the chain. +// This is done by activating the chain on the node and asking the governance contract +// to consider it as an access node. +func (clu *Cluster) AddAccessNode(accessNodeIndex int, chain *Chain) error { + waspClient := clu.WaspClient(accessNodeIndex) + if err := apilib.ActivateChainOnAccessNodes(clu.Config.APIHosts([]int{accessNodeIndex}), chain.ChainID); err != nil { + return err + } + accessNodePeering, err := waspClient.GetPeeringSelf() + if err != nil { + return err + } + accessNodePubKey, err := ed25519.PublicKeyFromString(accessNodePeering.PubKey) + if err != nil { + return err + } + cert, err := waspClient.NodeOwnershipCertificate(accessNodePubKey, chain.OriginatorAddress()) + if err != nil { + return err + } + scArgs := governance.AccessNodeInfo{ + NodePubKey: accessNodePubKey.Bytes(), + ValidatorAddr: chain.OriginatorAddress().Bytes(), + Certificate: cert.Bytes(), + ForCommittee: false, + AccessAPI: clu.Config.APIHost(accessNodeIndex), + } + scParams := chainclient.NewPostRequestParams(scArgs.ToAddCandidateNodeParams()).WithIotas(1) + govClient := chain.SCClient(governance.Contract.Hname(), chain.OriginatorKeyPair()) + tx, err := govClient.PostRequest(governance.FuncAddCandidateNode.Name, *scParams) + if err != nil { + return err + } + fmt.Printf("[cluster] Governance::AddCandidateNode, Posted TX, id=%v, args=%+v\n", tx.ID(), scArgs) + return nil +} + func (clu *Cluster) IsGoshimmerUp() bool { return clu.goshimmer != nil } @@ -217,7 +286,7 @@ func (clu *Cluster) InitDataPath(templatesPath, dataPath string, removeExisting waspNodeDataPath(dataPath, i), path.Join(templatesPath, "wasp-config-template.json"), templates.WaspConfig, - clu.Config.WaspConfigTemplateParams(i), + clu.Config.WaspConfigTemplateParams(i, clu.ValidatorAddress()), i, modifyConfig, ) @@ -555,7 +624,7 @@ func dumpBalancesByColor(actual, expect colored.Balances) (string, bool) { assertionOk = false isOk = "FAIL" } - ret += fmt.Sprintf(" %s: %d (%d) %s\n", col, act, expect[col], isOk) + ret += fmt.Sprintf(" %s: %d (%d) %s\n", col.String(), act, expect[col], isOk) } lst = lst[:0] for col := range actual { diff --git a/tools/cluster/config.go b/tools/cluster/config.go index a9bfd3f57a..16a0f38d1b 100644 --- a/tools/cluster/config.go +++ b/tools/cluster/config.go @@ -5,8 +5,8 @@ import ( "fmt" "os" "path" - "strings" + "github.com/iotaledger/goshimmer/packages/ledgerstate" "github.com/iotaledger/wasp/tools/cluster/templates" ) @@ -131,14 +131,6 @@ func (c *ClusterConfig) PeeringHosts(nodeIndexes ...[]int) []string { return c.waspHosts(nodes, func(i int) string { return c.PeeringHost(i) }) } -func (c *ClusterConfig) NeighborsString() string { - ret := make([]string, c.Wasp.NumNodes) - for i := range ret { - ret[i] = "\"" + c.PeeringHost(i) + "\"" - } - return strings.Join(ret, ",") -} - func (c *ClusterConfig) PeeringHost(nodeIndex int) string { return fmt.Sprintf("127.0.0.1:%d", c.PeeringPort(nodeIndex)) } @@ -189,17 +181,17 @@ func (c *ClusterConfig) PrometheusPort(nodeIndex int) int { return c.Wasp.FirstMetricsPort + nodeIndex } -func (c *ClusterConfig) WaspConfigTemplateParams(i int) *templates.WaspConfigParams { +func (c *ClusterConfig) WaspConfigTemplateParams(i int, ownerAddress ledgerstate.Address) *templates.WaspConfigParams { return &templates.WaspConfigParams{ APIPort: c.APIPort(i), DashboardPort: c.DashboardPort(i), PeeringPort: c.PeeringPort(i), NanomsgPort: c.NanomsgPort(i), - Neighbors: c.NeighborsString(), TxStreamPort: c.TxStreamPort(i), ProfilingPort: c.ProfilingPort(i), TxStreamHost: c.TxStreamHost(i), MetricsPort: c.PrometheusPort(i), + OwnerAddress: ownerAddress.Base58(), OffledgerBroadcastUpToNPeers: 10, } } diff --git a/tools/cluster/templates/waspconfig.go b/tools/cluster/templates/waspconfig.go index c5875d905b..41e9467527 100644 --- a/tools/cluster/templates/waspconfig.go +++ b/tools/cluster/templates/waspconfig.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package templates type WaspConfigParams struct { @@ -5,12 +8,12 @@ type WaspConfigParams struct { DashboardPort int PeeringPort int NanomsgPort int - Neighbors string TxStreamPort int TxStreamHost string ProfilingPort int MetricsPort int OffledgerBroadcastUpToNPeers int + OwnerAddress string } const WaspConfig = ` @@ -36,7 +39,8 @@ const WaspConfig = ` }, "node": { "disablePlugins": [], - "enablePlugins": [] + "enablePlugins": [], + "ownerAddresses": ["{{.OwnerAddress}}"] }, "webapi": { "bindAddress": "0.0.0.0:{{.APIPort}}" @@ -46,8 +50,7 @@ const WaspConfig = ` }, "peering":{ "port": {{.PeeringPort}}, - "netid": "127.0.0.1:{{.PeeringPort}}", - "neighbors": [{{.Neighbors}}] + "netid": "127.0.0.1:{{.PeeringPort}}" }, "nodeconn": { "address": "{{.TxStreamHost}}:{{.TxStreamPort}}" @@ -66,6 +69,10 @@ const WaspConfig = ` "metrics": { "bindAddress": "0.0.0.0:{{.MetricsPort}}", "enabled": false + }, + "wal": { + "directory": "wal", + "enabled": true } } ` diff --git a/tools/cluster/tests/account_test.go b/tools/cluster/tests/account_test.go index 32e4e2e8c2..4f0c2bd3e4 100644 --- a/tools/cluster/tests/account_test.go +++ b/tools/cluster/tests/account_test.go @@ -54,6 +54,7 @@ func TestBasicAccountsNLow(t *testing.T) { } func (e *chainEnv) testBasicAccounts(counter *cluster.MessageCounter) { + chainNodeCount := uint64(len(e.chain.AllPeers)) hname := iscp.Hn(incCounterSCName) description := "testing contract deployment with inccounter" programHash1 := inccounter.Contract.ProgramHash @@ -92,8 +93,8 @@ func (e *chainEnv) testBasicAccounts(counter *cluster.MessageCounter) { require.EqualValues(e.t, 42, counterValue) } - if !e.clu.VerifyAddressBalances(e.chain.ChainID.AsAddress(), ledgerstate.DustThresholdAliasOutputIOTA+2, - colored.NewBalancesForIotas(ledgerstate.DustThresholdAliasOutputIOTA+2), "chain after deployment") { + if !e.clu.VerifyAddressBalances(e.chain.ChainID.AsAddress(), ledgerstate.DustThresholdAliasOutputIOTA+2+chainNodeCount, + colored.NewBalancesForIotas(ledgerstate.DustThresholdAliasOutputIOTA+2+chainNodeCount), "chain after deployment") { e.t.Fail() } @@ -119,8 +120,8 @@ func (e *chainEnv) testBasicAccounts(counter *cluster.MessageCounter) { e.t.Fail() } - if !e.clu.VerifyAddressBalances(e.chain.ChainID.AsAddress(), ledgerstate.DustThresholdAliasOutputIOTA+transferIotas+2, - colored.NewBalancesForIotas(ledgerstate.DustThresholdAliasOutputIOTA+transferIotas+2), "chain after") { + if !e.clu.VerifyAddressBalances(e.chain.ChainID.AsAddress(), ledgerstate.DustThresholdAliasOutputIOTA+transferIotas+2+chainNodeCount, + colored.NewBalancesForIotas(ledgerstate.DustThresholdAliasOutputIOTA+transferIotas+2+chainNodeCount), "chain after") { e.t.Fail() } agentID := iscp.NewAgentID(e.chain.ChainID.AsAddress(), hname) @@ -154,6 +155,7 @@ func TestBasic2Accounts(t *testing.T) { root.ParamName: incCounterSCName, }) require.NoError(t, err) + chainNodeCount := uint64(len(chain.AllPeers)) if !counter.WaitUntilExpectationsMet() { t.Fail() @@ -181,16 +183,16 @@ func TestBasic2Accounts(t *testing.T) { require.EqualValues(t, 42, counterValue) } - if !e.clu.VerifyAddressBalances(chain.ChainID.AsAddress(), ledgerstate.DustThresholdAliasOutputIOTA+2, - colored.NewBalancesForIotas(ledgerstate.DustThresholdAliasOutputIOTA+2), "chain after deployment") { + if !e.clu.VerifyAddressBalances(chain.ChainID.AsAddress(), ledgerstate.DustThresholdAliasOutputIOTA+2+chainNodeCount, + colored.NewBalancesForIotas(ledgerstate.DustThresholdAliasOutputIOTA+2+chainNodeCount), "chain after deployment") { t.Fail() } originatorSigScheme := chain.OriginatorKeyPair() originatorAddress := chain.OriginatorAddress() - if !e.clu.VerifyAddressBalances(originatorAddress, solo.Saldo-ledgerstate.DustThresholdAliasOutputIOTA-2, - colored.NewBalancesForIotas(solo.Saldo-ledgerstate.DustThresholdAliasOutputIOTA-2), + if !e.clu.VerifyAddressBalances(originatorAddress, solo.Saldo-ledgerstate.DustThresholdAliasOutputIOTA-2-chainNodeCount, + colored.NewBalancesForIotas(solo.Saldo-ledgerstate.DustThresholdAliasOutputIOTA-2-chainNodeCount), "originator after deployment") { t.Fail() } @@ -217,16 +219,16 @@ func TestBasic2Accounts(t *testing.T) { require.NoError(t, err) require.EqualValues(t, 43, counterValue) } - if !e.clu.VerifyAddressBalances(originatorAddress, solo.Saldo-ledgerstate.DustThresholdAliasOutputIOTA-2, - colored.NewBalancesForIotas(solo.Saldo-ledgerstate.DustThresholdAliasOutputIOTA-2), + if !e.clu.VerifyAddressBalances(originatorAddress, solo.Saldo-ledgerstate.DustThresholdAliasOutputIOTA-2-chainNodeCount, + colored.NewBalancesForIotas(solo.Saldo-ledgerstate.DustThresholdAliasOutputIOTA-2-chainNodeCount), "originator after") { t.Fail() } if !e.clu.VerifyAddressBalances(myWalletAddr, solo.Saldo-transferIotas, colored.NewBalancesForIotas(solo.Saldo-transferIotas), "myWalletAddr after") { t.Fail() } - if !e.clu.VerifyAddressBalances(chain.ChainID.AsAddress(), ledgerstate.DustThresholdAliasOutputIOTA+2+transferIotas, - colored.NewBalancesForIotas(ledgerstate.DustThresholdAliasOutputIOTA+2+transferIotas), + if !e.clu.VerifyAddressBalances(chain.ChainID.AsAddress(), ledgerstate.DustThresholdAliasOutputIOTA+2+transferIotas+chainNodeCount, + colored.NewBalancesForIotas(ledgerstate.DustThresholdAliasOutputIOTA+2+transferIotas+chainNodeCount), "chain after") { t.Fail() } @@ -255,8 +257,8 @@ func TestBasic2Accounts(t *testing.T) { actual = chEnv.getBalanceOnChain(agentID, colored.IOTA) require.EqualValues(t, 0, actual) - if !e.clu.VerifyAddressBalances(originatorAddress, solo.Saldo-ledgerstate.DustThresholdAliasOutputIOTA-3, - colored.NewBalancesForIotas(solo.Saldo-ledgerstate.DustThresholdAliasOutputIOTA-3), + if !e.clu.VerifyAddressBalances(originatorAddress, solo.Saldo-ledgerstate.DustThresholdAliasOutputIOTA-3-chainNodeCount, + colored.NewBalancesForIotas(solo.Saldo-ledgerstate.DustThresholdAliasOutputIOTA-3-chainNodeCount), "originator after withdraw: "+originatorAddress.String()) { t.Fail() } diff --git a/tools/cluster/tests/advanced_inccounter_test.go b/tools/cluster/tests/advanced_inccounter_test.go index a91a24f3ca..d9fd967fc5 100644 --- a/tools/cluster/tests/advanced_inccounter_test.go +++ b/tools/cluster/tests/advanced_inccounter_test.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package tests import ( @@ -119,9 +122,13 @@ func testAccessNodesOnLedger(t *testing.T, numRequests, numValidatorNodes, clust require.NoError(t, err) } - waitUntil(t, e.counterEquals(int64(numRequests)), util.MakeRange(0, clusterSize), 40*time.Second) + waitUntil(t, e.counterEquals(int64(numRequests)), util.MakeRange(0, clusterSize), 40*time.Second, "a required number of testAccessNodesOnLedger requests") - e.printBlocks(numRequests + 3) + e.printBlocks( + numRequests + // The actual IncCounter requests. + 3 + // Initial State + IncCounter SC Deploy + ??? + clusterSize, // Access node applications. + ) } func TestAccessNodesOffLedger(t *testing.T) { @@ -165,7 +172,7 @@ func TestAccessNodesOffLedger(t *testing.T) { t.Run("cluster=30,N=15,req=8", func(t *testing.T) { testutil.RunHeavy(t) - const waitFor = 60 * time.Second + const waitFor = 180 * time.Second const numRequests = 8 const numValidatorNodes = 15 const clusterSize = 30 @@ -174,7 +181,7 @@ func TestAccessNodesOffLedger(t *testing.T) { t.Run("cluster=30,N=20,req=8", func(t *testing.T) { testutil.RunHeavy(t) - const waitFor = 60 * time.Second + const waitFor = 300 * time.Second const numRequests = 8 const numValidatorNodes = 20 const clusterSize = 30 @@ -212,7 +219,11 @@ func testAccessNodesOffLedger(t *testing.T, numRequests, numValidatorNodes, clus waitUntil(t, e.counterEquals(int64(numRequests)), util.MakeRange(0, clusterSize), to, "requests counted") - e.printBlocks(numRequests + 4) + e.printBlocks( + numRequests + // The actual IncCounter requests. + 4 + // ??? + clusterSize, // Access nodes applications. + ) } // extreme test @@ -245,7 +256,11 @@ func TestAccessNodesMany(t *testing.T) { waitUntil(t, e.counterEquals(int64(requestsCumulative)), e.clu.Config.AllNodes(), 60*time.Second, logMsg) requestsCount *= requestsCountProgression } - e.printBlocks(posted + 3) + e.printBlocks( + posted + // The actual SC requests. + 3 + // ??? + clusterSize, // GOV: Access Node Applications. + ) } // cluster of 10 access nodes and two overlapping committees diff --git a/tools/cluster/tests/transfer_test.go b/tools/cluster/tests/transfer_test.go index b696da0241..15ccc66374 100644 --- a/tools/cluster/tests/transfer_test.go +++ b/tools/cluster/tests/transfer_test.go @@ -18,6 +18,7 @@ func TestDepositWithdraw(t *testing.T) { chain, err := e.clu.DeployDefaultChain() require.NoError(t, err) + chainNodeCount := uint64(len(chain.AllPeers)) chEnv := newChainEnv(t, e.clu, chain) @@ -30,13 +31,13 @@ func TestDepositWithdraw(t *testing.T) { "myAddress begin") { t.Fail() } - if !e.clu.VerifyAddressBalances(chain.OriginatorAddress(), solo.Saldo-ledgerstate.DustThresholdAliasOutputIOTA-1, - colored.NewBalancesForIotas(solo.Saldo-ledgerstate.DustThresholdAliasOutputIOTA-1), + if !e.clu.VerifyAddressBalances(chain.OriginatorAddress(), solo.Saldo-ledgerstate.DustThresholdAliasOutputIOTA-1-chainNodeCount, + colored.NewBalancesForIotas(solo.Saldo-ledgerstate.DustThresholdAliasOutputIOTA-1-chainNodeCount), "originatorAddress begin") { t.Fail() } - if !e.clu.VerifyAddressBalances(chain.ChainAddress(), ledgerstate.DustThresholdAliasOutputIOTA+1, - colored.NewBalancesForIotas(ledgerstate.DustThresholdAliasOutputIOTA+1), + if !e.clu.VerifyAddressBalances(chain.ChainAddress(), ledgerstate.DustThresholdAliasOutputIOTA+1+chainNodeCount, + colored.NewBalancesForIotas(ledgerstate.DustThresholdAliasOutputIOTA+1+chainNodeCount), "chainAddress begin") { t.Fail() } diff --git a/tools/cluster/tests/util.go b/tools/cluster/tests/util.go index 4a6fa8bd9f..76a2368139 100644 --- a/tools/cluster/tests/util.go +++ b/tools/cluster/tests/util.go @@ -157,7 +157,7 @@ func (e *chainEnv) printAccounts(title string) { for aid, bals := range allBalances { s += fmt.Sprintf(" %s\n", aid.String()) for k, v := range bals { - s += fmt.Sprintf(" %s: %d\n", k, v) + s += fmt.Sprintf(" %s: %d\n", k.String(), v) } } fmt.Println(s) diff --git a/tools/cluster/tests/wal_test.go b/tools/cluster/tests/wal_test.go new file mode 100644 index 0000000000..d75ceeebe2 --- /dev/null +++ b/tools/cluster/tests/wal_test.go @@ -0,0 +1,76 @@ +package tests + +import ( + "os" + "path" + "strconv" + "testing" + + "github.com/iotaledger/wasp/packages/kv/codec" + "github.com/iotaledger/wasp/packages/kv/dict" + "github.com/iotaledger/wasp/packages/state" + "github.com/iotaledger/wasp/packages/vm/core/blocklog" + "github.com/stretchr/testify/require" +) + +func TestWriteToWAL(t *testing.T) { + e := setupWithNoChain(t, 1) + + chain, err := e.clu.DeployDefaultChain() + require.NoError(t, err) + require.NoError(t, err) + + walDir := walDirFromDataPath(e.clu.DataPath, chain.ChainID.Base58()) + require.True(t, walDirectoryCreated(walDir)) + + blockIndex, _ := chain.BlockIndex(0) + checkCreatedFilenameMatchesBlockIndex(t, walDir, blockIndex) + + segName := latestSegName(walDir) + segPath := path.Join(walDir, segName) + blockBytes := getBytesFromSegment(t, segPath) + block, err := state.BlockFromBytes(blockBytes) + require.NoError(t, err) + require.EqualValues(t, blockIndex, block.BlockIndex()) + + v, err := chain.Cluster.WaspClient(0).CallView( + chain.ChainID, blocklog.Contract.Hname(), blocklog.FuncGetBlockInfo.Name, + dict.Dict{ + blocklog.ParamBlockIndex: codec.EncodeUint32(blockIndex), + }) + require.NoError(t, err) + + blockInfo, err := blocklog.BlockInfoFromBytes(blockIndex, v.MustGet(blocklog.ParamBlockInfo)) + require.NoError(t, err) + + require.EqualValues(t, blockInfo.BlockIndex, block.BlockIndex()) + require.EqualValues(t, blockInfo.Timestamp, block.Timestamp()) + require.EqualValues(t, blockInfo.PreviousStateHash.Bytes(), block.PreviousStateHash().Bytes()) +} + +func walDirectoryCreated(walDir string) bool { + _, err := os.Stat(walDir) + return !os.IsNotExist(err) +} + +func walDirFromDataPath(dataPath, chainID string) string { + return path.Join(dataPath, "wasp0", "wal", chainID) +} + +func checkCreatedFilenameMatchesBlockIndex(t *testing.T, walDir string, blockIndex uint32) { + latestSegmentName := latestSegName(walDir) + index, _ := strconv.ParseUint(latestSegmentName, 10, 32) + t.Logf("Index: %d", index) + require.EqualValues(t, blockIndex, index) +} + +func latestSegName(walDir string) string { + files, _ := os.ReadDir(walDir) + return files[len(files)-1].Name() +} + +func getBytesFromSegment(t *testing.T, segPath string) []byte { + data, err := os.ReadFile(segPath) + require.NoError(t, err) + return data +} diff --git a/tools/cluster/tests/wasm/inccounter_bg.wasm b/tools/cluster/tests/wasm/inccounter_bg.wasm index c577e6e18f..8f2f783f82 100644 Binary files a/tools/cluster/tests/wasm/inccounter_bg.wasm and b/tools/cluster/tests/wasm/inccounter_bg.wasm differ diff --git a/tools/devnet/docker-compose.yml b/tools/devnet/docker-compose.yml index c2b370017e..fcea1419c7 100644 --- a/tools/devnet/docker-compose.yml +++ b/tools/devnet/docker-compose.yml @@ -17,10 +17,10 @@ services: - "7000/tcp" # Wasp Dashboard - "9090/tcp" # Wasp WebAPI ports: - - "127.0.0.1:4000:4000/tcp" # Peering - - "127.0.0.1:5550:5550/tcp" # Nano MSG - - "127.0.0.1:7000:7000/tcp" # Wasp Dashboard - - "127.0.0.1:9090:9090/tcp" # Wasp WebAPI + - "${HOST:-127.0.0.1}:4000:4000/tcp" # Peering + - "${HOST:-127.0.0.1}:5550:5550/tcp" # Nano MSG + - "${HOST:-127.0.0.1}:7000:7000/tcp" # Wasp Dashboard + - "${HOST:-127.0.0.1}:9090:9090/tcp" # Wasp WebAPI devnet_goshimmer: restart: always container_name: devnet_goshimmer @@ -42,11 +42,11 @@ services: - ./goshimmer.config.json:/tmp/config.json:ro - ./snapshot.bin:/tmp/snapshot.bin:ro ports: - - "127.0.0.1:5000:5000/tcp" # TX Stream - - "127.0.0.1:8080:8080/tcp" # GoShimmer API - - "127.0.0.1:8081:8081/tcp" # GoShimmer Dashboard - - "127.0.0.1:9000:9000/tcp" # Analysis Dashboard - - "127.0.0.1:9312:9312/tcp" # Prometheus + - "${HOST:-127.0.0.1}:5000:5000/tcp" # TX Stream + - "${HOST:-127.0.0.1}:8080:8080/tcp" # GoShimmer API + - "${HOST:-127.0.0.1}:8081:8081/tcp" # GoShimmer Dashboard + - "${HOST:-127.0.0.1}:9000:9000/tcp" # Analysis Dashboard + - "${HOST:-127.0.0.1}:9312:9312/tcp" # Prometheus expose: - "1888/tcp" # Analysis Server (within Docker network) - "5000/tcp" # TXStream diff --git a/tools/schema/generator/clientbase.go b/tools/schema/generator/clientbase.go new file mode 100644 index 0000000000..4ccbf673c2 --- /dev/null +++ b/tools/schema/generator/clientbase.go @@ -0,0 +1,57 @@ +package generator + +import ( + "fmt" + "os" + + "github.com/iotaledger/wasp/tools/schema/model" +) + +type ClientBase struct { + GenBase +} + +func (g *ClientBase) Generate() error { + g.folder = g.rootFolder + "/" + g.s.PackageName + "client/" + if g.s.CoreContracts { + g.folder = g.rootFolder + "/wasmclient/" + g.s.PackageName + "/" + } + err := os.MkdirAll(g.folder, 0o755) + if err != nil { + return err + } + info, err := os.Stat(g.folder + "service" + g.extension) + if err == nil && info.ModTime().After(g.s.SchemaTime) { + fmt.Printf("skipping %s code generation\n", g.language) + return nil + } + + fmt.Printf("generating %s code\n", g.language) + return g.generateCode() +} + +func (g *ClientBase) generateCode() error { + err := g.createSourceFile("events", !g.s.CoreContracts) + if err != nil { + return err + } + err = g.createSourceFile("service", true) + if err != nil { + return err + } + if !g.s.CoreContracts { + return g.generateFuncs(g.appendEvents) + } + return nil +} + +func (g *ClientBase) appendEvents(existing model.StringMap) { + for _, g.currentEvent = range g.s.Events { + name := g.s.ContractName + capitalize(g.currentEvent.Name) + if existing[name] == "" { + g.log("currentEvent: " + g.currentEvent.Name) + g.setMultiKeyValues("evtName", g.currentEvent.Name) + g.emit("funcSignature") + } + } +} diff --git a/tools/schema/generator/clienttemplates/alltemplates.go b/tools/schema/generator/clienttemplates/alltemplates.go deleted file mode 100644 index 2fca82b07b..0000000000 --- a/tools/schema/generator/clienttemplates/alltemplates.go +++ /dev/null @@ -1,87 +0,0 @@ -package clienttemplates - -import "github.com/iotaledger/wasp/tools/schema/model" - -var config = map[string]string{ - "language": "Client", - "extension": ".ts", - "rootFolder": "client", - "funcRegexp": `N/A`, -} - -var Templates = []map[string]string{ - config, - common, - appTs, - eventsTs, - serviceTs, -} - -var TypeDependent = model.StringMapMap{ - "msgConvert": { - "Address": "message[++index]", - "AgentID": "message[++index]", - "Bool": "message[++index][0]!='0'", - "ChainID": "message[++index]", - "Color": "message[++index]", - "Hash": "message[++index]", - "Hname": "message[++index]", - "Int8": "Number(message[++index])", - "Int16": "Number(message[++index])", - "Int32": "Number(message[++index])", - "Int64": "BigInt(message[++index])", - "RequestID": "message[++index]", - "String": "message[++index]", - "Uint8": "Number(message[++index])", - "Uint16": "Number(message[++index])", - "Uint32": "Number(message[++index])", - "Uint64": "BigInt(message[++index])", - }, - "fldDefault": { - "Address": "''", - "AgentID": "''", - "Bool": "false", - "ChainID": "''", - "Color": "''", - "Hash": "''", - "Hname": "''", - "Int8": "0", - "Int16": "0", - "Int32": "0", - "Int64": "BigInt(0)", - "RequestID": "''", - "String": "''", - "Uint8": "0", - "Uint16": "0", - "Uint32": "0", - "Uint64": "BigInt(0)", - }, - "resConvert": { - "Address": "toString", - "AgentID": "toString", - "Bool": "readUInt8", - "ChainID": "toString", - "Color": "toString", - "Hash": "toString", - "Hname": "toString", - "Int8": "readInt8", - "Int16": "readInt16LE", - "Int32": "readInt32LE", - "Int64": "readBigInt64LE", - "RequestID": "toString", - "String": "toString", - "Uint8": "readUInt8", - "Uint16": "readUInt16LE", - "Uint32": "readUInt32LE", - "Uint64": "readBigUInt64LE", - }, - "resConvert2": { - "Bool": "!=0", - }, -} - -var common = map[string]string{ - // ******************************* - "tmp": ` -tmp`, -} diff --git a/tools/schema/generator/clienttemplates/app.go b/tools/schema/generator/clienttemplates/app.go deleted file mode 100644 index cee2726e7a..0000000000 --- a/tools/schema/generator/clienttemplates/app.go +++ /dev/null @@ -1,22 +0,0 @@ -package clienttemplates - -var appTs = map[string]string{ - // ******************************* - "app.ts": ` -import * as wasmlib from "./wasmlib" -import * as events from "./events" -import * as service from "./service" - -let $pkgName$+Service: service.$PkgName$+Service; - -export function subscribeTo$Package$+Events(): void { -$#each events appOnEvent -} -`, - // ******************************* - "appOnEvent": ` - - $pkgName$+Service.on('$package$+_$evtName', (event: events.Event$EvtName) => { - }); -`, -} diff --git a/tools/schema/generator/clienttemplates/events.go b/tools/schema/generator/clienttemplates/events.go deleted file mode 100644 index ca14b503d1..0000000000 --- a/tools/schema/generator/clienttemplates/events.go +++ /dev/null @@ -1,58 +0,0 @@ -package clienttemplates - -var eventsTs = map[string]string{ - // ******************************* - "events.ts": ` -import * as wasmlib from "./wasmlib" -import * as service from "./service" - -$#each events eventInterface - -export interface $Package$+Events { -$#each events eventSignature -} - -export function handleVmMessage(message: string[]): void { - const messageHandlers: wasmlib.MessageHandlers = { -$#each events eventHandler - }; - - const topicIndex = 3; - const topic = message[topicIndex]; - - if (typeof messageHandlers[topic] != 'undefined') { - messageHandlers[topic](topicIndex); - } -} -`, - // ******************************* - "eventSignature": ` - $package$+_$evtName: (event: Event$EvtName) => void; -`, - // ******************************* - "eventInterface": ` - -export interface Event$EvtName { - timestamp: wasmlib.Int32; -$#each event eventInterfaceField -} -`, - // ******************************* - "eventInterfaceField": ` - $fldName: wasmlib.$FldType; -`, - // ******************************* - "eventHandler": ` - '$package.$evtName': (index) => { - const evt: Event$EvtName = { - timestamp: Number(message[++index]), -$#each event eventHandlerField - }; - this.emitter.emit('$package$+_$evtName', evt); - }, -`, - // ******************************* - "eventHandlerField": ` - $fldName: $msgConvert, -`, -} diff --git a/tools/schema/generator/clienttemplates/service.go b/tools/schema/generator/clienttemplates/service.go deleted file mode 100644 index f67dc8de6d..0000000000 --- a/tools/schema/generator/clienttemplates/service.go +++ /dev/null @@ -1,82 +0,0 @@ -package clienttemplates - -var serviceTs = map[string]string{ - // ******************************* - "service.ts": ` -import * as wasmlib from "./wasmlib" -import * as events from "./events" -$#each func serviceResults - -export class $PkgName$+Service extends wasmlib.Service { - - constructor(client: BasicClient, chainId: string) { - super(client, chainId, 0x$hscName); - } -$#each func serviceFunction -} -`, - // ******************************* - "serviceResults": ` -$#if result serviceHasResults -`, - // ******************************* - "serviceHasResults": ` - -export interface $FuncName$+Result { -$#each result serviceResult -} -`, - // ******************************* - "serviceResult": ` - $fldName: wasmlib.$FldType; -`, - // ******************************* - "serviceFunction": ` -$#set sep $empty -$#set params $empty -$#each param serviceParam -$#emit service$Kind -`, - // ******************************* - "serviceParam": ` -$#set params $params$sep$fldName: wasmlib.$FldType -$#set sep , -`, - // ******************************* - "serviceFunc": ` - - public async $funcName($params): Promise { - const args: wasmlib.Argument[] = [ -$#each param serviceFuncParam - ]; - await this.postRequest(0x$funcHname, args); - } -`, - // ******************************* - "serviceFuncParam": ` - { key: '$fldName', value: $fldName, }, -`, - // ******************************* - "serviceView": ` - - public async $funcName($params): Promise<$FuncName$+Result> { - const args: wasmlib.Argument[] = [ -$#each param serviceFuncParam - ]; - const response = await this.callView(0x$funcHname, args); - let result: $FuncName$+Result = {}; - -$#each result serviceViewResult - - return result; - } -`, - // ******************************* - "serviceViewResult": ` - let $fldName = response['$fldName']; - result.$fldName = $fldDefault; - if ($fldName) { - result.$fldName = $fldName.$resConvert($fldName)$resConvert2; - } -`, -} diff --git a/tools/schema/generator/emitter.go b/tools/schema/generator/emitter.go index 7f965c837c..85310d21e5 100644 --- a/tools/schema/generator/emitter.go +++ b/tools/schema/generator/emitter.go @@ -208,7 +208,8 @@ func (g *GenBase) emitEachFunc(funcs []*model.Func, template string) { func (g *GenBase) emitEachMandatoryField(template string) { mandatoryFields := make([]*model.Field, 0) for _, g.currentField = range g.currentFunc.Params { - if !g.currentField.Optional { + fld := g.currentField + if !fld.Optional && fld.TypeID != 0 && !fld.Array && fld.MapKey == "" { mandatoryFields = append(mandatoryFields, g.currentField) } } @@ -279,6 +280,8 @@ func (g *GenBase) emitIf(line string) { condition = g.keys["kind"] == KeyFunc case KeyInit: condition = g.currentFunc.Name == KeyInit + case KeyMandatory: + condition = !g.currentField.Optional case KeyMap: condition = g.currentField.MapKey != "" case KeyMut: @@ -435,7 +438,7 @@ func (g *GenBase) setFieldKeys(pad bool, maxCamelLength, maxSnakeLength int) { func (g *GenBase) setFuncKeys(pad bool, maxCamelLength, maxSnakeLength int) { g.setMultiKeyValues("funcName", g.currentFunc.Name) g.setMultiKeyValues("kind", g.currentFunc.Kind) - g.keys["funcHname"] = iscp.Hn(g.keys["funcName"]).String() + g.keys["hFuncName"] = iscp.Hn(g.keys["funcName"]).String() grant := g.currentFunc.Access comment := "" index := strings.Index(grant, "//") diff --git a/tools/schema/generator/generator.go b/tools/schema/generator/generator.go index 221813c841..106ed72eb9 100644 --- a/tools/schema/generator/generator.go +++ b/tools/schema/generator/generator.go @@ -190,12 +190,12 @@ func (g *GenBase) generateCode() error { return err } if !g.s.CoreContracts { - return g.generateFuncs() + return g.generateFuncs(g.appendFuncs) } return nil } -func (g *GenBase) generateFuncs() error { +func (g *GenBase) generateFuncs(appendFuncs func(existing model.StringMap)) error { scFileName := g.folder + g.s.PackageName + g.extension if g.exists(scFileName) != nil { // generate initial SC function file @@ -229,12 +229,7 @@ func (g *GenBase) generateFuncs() error { } // append any new funcs - for _, g.currentFunc = range g.s.Funcs { - if existing[g.funcName(g.currentFunc)] == "" { - g.setFuncKeys(false, 0, 0) - g.emit("funcSignature") - } - } + appendFuncs(existing) }) if err != nil { return err @@ -242,6 +237,15 @@ func (g *GenBase) generateFuncs() error { return os.Remove(scOriginal) } +func (g *GenBase) appendFuncs(existing model.StringMap) { + for _, g.currentFunc = range g.s.Funcs { + if existing[g.funcName(g.currentFunc)] == "" { + g.setFuncKeys(false, 0, 0) + g.emit("funcSignature") + } + } +} + func (g *GenBase) generateTests() error { err := os.MkdirAll("test", 0o755) if err != nil { diff --git a/tools/schema/generator/generator_client.go b/tools/schema/generator/generator_client.go deleted file mode 100644 index bc48b6369f..0000000000 --- a/tools/schema/generator/generator_client.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2020 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -package generator - -import ( - "fmt" - "os" - - "github.com/iotaledger/wasp/tools/schema/generator/clienttemplates" - "github.com/iotaledger/wasp/tools/schema/model" -) - -type ClientGenerator struct { - GenBase -} - -func NewClientGenerator(s *model.Schema) *ClientGenerator { - g := &ClientGenerator{} - g.init(s, clienttemplates.TypeDependent, clienttemplates.Templates) - return g -} - -func (g *ClientGenerator) Generate() error { - g.folder = g.rootFolder + "/" - err := os.MkdirAll(g.folder, 0o755) - if err != nil { - return err - } - info, err := os.Stat(g.folder + "events" + g.extension) - if err == nil && info.ModTime().After(g.s.SchemaTime) { - fmt.Printf("skipping %s code generation\n", g.language) - return nil - } - - fmt.Printf("generating %s code\n", g.language) - return g.generateCode() -} - -func (g *ClientGenerator) generateCode() error { - err := g.createSourceFile("events", len(g.s.Events) != 0) - if err != nil { - return err - } - err = g.createSourceFile("app", len(g.s.Events) != 0) - if err != nil { - return err - } - err = g.createSourceFile("service", len(g.s.Events) != 0) - if err != nil { - return err - } - return nil -} diff --git a/tools/schema/generator/generator_goclient.go b/tools/schema/generator/generator_goclient.go new file mode 100644 index 0000000000..319b55c529 --- /dev/null +++ b/tools/schema/generator/generator_goclient.go @@ -0,0 +1,19 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package generator + +import ( + "github.com/iotaledger/wasp/tools/schema/generator/goclienttemplates" + "github.com/iotaledger/wasp/tools/schema/model" +) + +type GoClientGenerator struct { + ClientBase +} + +func NewGoClientGenerator(s *model.Schema) *GoClientGenerator { + g := &GoClientGenerator{} + g.init(s, goclienttemplates.TypeDependent, goclienttemplates.Templates) + return g +} diff --git a/tools/schema/generator/generator_tsclient.go b/tools/schema/generator/generator_tsclient.go new file mode 100644 index 0000000000..97e1e98baa --- /dev/null +++ b/tools/schema/generator/generator_tsclient.go @@ -0,0 +1,41 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package generator + +import ( + "github.com/iotaledger/wasp/tools/schema/generator/tsclienttemplates" + "github.com/iotaledger/wasp/tools/schema/model" +) + +type TsClientGenerator struct { + ClientBase +} + +func NewTsClientGenerator(s *model.Schema) *TsClientGenerator { + g := &TsClientGenerator{} + g.init(s, tsclienttemplates.TypeDependent, tsclienttemplates.Templates) + return g +} + +func (g *TsClientGenerator) Generate() error { + err := g.ClientBase.Generate() + if err != nil { + return err + } + if g.s.CoreContracts { + return nil + } + + // now generate language-specific files + + err = g.createSourceFile("index", true) + if err != nil { + return err + } + + tsconfig := "tsconfig.json" + return g.createFile(g.folder+tsconfig, false, func() { + g.emit(tsconfig) + }) +} diff --git a/tools/schema/generator/goclienttemplates/alltemplates.go b/tools/schema/generator/goclienttemplates/alltemplates.go new file mode 100644 index 0000000000..351de3f721 --- /dev/null +++ b/tools/schema/generator/goclienttemplates/alltemplates.go @@ -0,0 +1,168 @@ +package goclienttemplates + +import "github.com/iotaledger/wasp/tools/schema/model" + +var config = map[string]string{ + "language": "Go Client", + "extension": ".go", + "rootFolder": "go", + "funcRegexp": `^func On(\w+).+$`, +} + +var Templates = []map[string]string{ + config, // always first one + common, + eventsGo, + funcsGo, + serviceGo, +} + +var TypeDependent = model.StringMapMap{ + "fldLangType": { + "Address": "wasmclient.Address", + "AgentID": "wasmclient.AgentID", + "Bool": "bool", + "Bytes": "[]byte", + "ChainID": "wasmclient.ChainID", + "Color": "wasmclient.Color", + "Hash": "wasmclient.Hash", + "Hname": "wasmclient.Hname", + "Int8": "int8", + "Int16": "int16", + "Int32": "int32", + "Int64": "int64", + "RequestID": "wasmclient.RequestID", + "String": "string", + "Uint8": "uint8", + "Uint16": "uint16", + "Uint32": "uint32", + "Uint64": "uint64", + }, + "fldTypeID": { + "Address": "wasmlib.TYPE_ADDRESS", + "AgentID": "wasmlib.TYPE_AGENT_ID", + "Bool": "wasmlib.TYPE_BOOL", + "Bytes": "wasmlib.TYPE_BYTES", + "ChainID": "wasmlib.TYPE_CHAIN_ID", + "Color": "wasmlib.TYPE_COLOR", + "Hash": "wasmlib.TYPE_HASH", + "Hname": "wasmlib.TYPE_HNAME", + "Int8": "wasmlib.TYPE_INT8", + "Int16": "wasmlib.TYPE_INT16", + "Int32": "wasmlib.TYPE_INT32", + "Int64": "wasmlib.TYPE_INT64", + "RequestID": "wasmlib.TYPE_REQUEST_ID", + "String": "wasmlib.TYPE_STRING", + "Uint8": "wasmlib.TYPE_INT8", + "Uint16": "wasmlib.TYPE_INT16", + "Uint32": "wasmlib.TYPE_INT32", + "Uint64": "wasmlib.TYPE_INT64", + "": "wasmlib.TYPE_BYTES", + }, + "argEncode": { + "Address": "wasmclient.Base58Decode", + "AgentID": "wasmclient.Base58Decode", + "Bool": "codec.EncodeBool", + "Bytes": "[]byte", + "ChainID": "wasmclient.Base58Decode", + "Color": "wasmclient.Base58Decode", + "Hash": "wasmclient.Base58Decode", + "Hname": "wasmclient.Base58Decode", + "Int8": "codec.EncodeInt8", + "Int16": "codec.EncodeInt16", + "Int32": "codec.EncodeInt32", + "Int64": "codec.EncodeInt64", + "RequestID": "wasmclient.Base58Decode", + "String": "codec.EncodeString", + "Uint8": "codec.EncodeUint8", + "Uint16": "codec.EncodeUint16", + "Uint32": "codec.EncodeUint32", + "Uint64": "codec.EncodeUint64", + }, + "argDecode": { + "Address": "wasmclient.Base58Encode", + "AgentID": "wasmclient.Base58Encode", + "Bool": "codec.DecodeBool", + "Bytes": "[]byte", + "ChainID": "wasmclient.Base58Encode", + "Color": "wasmclient.Base58Encode", + "Hash": "wasmclient.Base58Encode", + "Hname": "wasmclient.Base58Encode", + "Int8": "codec.DecodeInt8", + "Int16": "codec.DecodeInt16", + "Int32": "codec.DecodeInt32", + "Int64": "codec.DecodeInt64", + "RequestID": "wasmclient.Base58Encode", + "String": "codec.DecodeString", + "Uint8": "codec.DecodeUint8", + "Uint16": "codec.DecodeUint16", + "Uint32": "codec.DecodeUint32", + "Uint64": "codec.DecodeUint64", + }, + "msgConvert": { + "Address": "e.Next()", + "AgentID": "e.Next()", + "Bool": "e.NextBool()", + "ChainID": "e.Next()", + "Color": "e.Next()", + "Hash": "e.Next()", + "Hname": "e.Next()", + "Int8": "e.NextInt8()", + "Int16": "e.NextInt16()", + "Int32": "e.NextInt32()", + "Int64": "e.NextInt64()", + "RequestID": "e.Next()", + "String": "e.Next()", + "Uint8": "e.NextUint8()", + "Uint16": "e.NextUint16()", + "Uint32": "e.NextUint32()", + "Uint64": "e.NextUint64()", + }, + "fldDefault": { + "Address": "''", + "AgentID": "''", + "Bool": "false", + "ChainID": "''", + "Color": "''", + "Hash": "''", + "Hname": "''", + "Int8": "0", + "Int16": "0", + "Int32": "0", + "Int64": "BigInt(0)", + "RequestID": "''", + "String": "''", + "Uint8": "0", + "Uint16": "0", + "Uint32": "0", + "Uint64": "BigInt(0)", + }, + "resConvert": { + "Address": "toString()", + "AgentID": "toString()", + "Bool": "readUInt8(0)!=0", + "ChainID": "toString()", + "Color": "toString()", + "Hash": "toString()", + "Hname": "toString()", + "Int8": "readInt8(0)", + "Int16": "readInt16LE(0)", + "Int32": "readInt32LE(0)", + "Int64": "readBigInt64LE(0)", + "RequestID": "toString()", + "String": "toString()", + "Uint8": "readUInt8(0)", + "Uint16": "readUInt16LE(0)", + "Uint32": "readUInt32LE(0)", + "Uint64": "readBigUInt64LE(0)", + }, +} + +var common = map[string]string{ + // ******************************* + "clientHeader": ` +package $package$+client + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmclient" +`, +} diff --git a/tools/schema/generator/goclienttemplates/events.go b/tools/schema/generator/goclienttemplates/events.go new file mode 100644 index 0000000000..feabf1b3d1 --- /dev/null +++ b/tools/schema/generator/goclienttemplates/events.go @@ -0,0 +1,40 @@ +package goclienttemplates + +var eventsGo = map[string]string{ + // ******************************* + "events.go": ` +$#emit clientHeader + +var EventHandlers = map[string]func([]string) { +$#each events eventHandler +} +$#each events eventClass +`, + // ******************************* + "eventHandler": ` + "$package.$evtName": on$PkgName$EvtName$+Thunk, +`, + // ******************************* + "eventClass": ` + +type Event$EvtName struct { + wasmclient.Event +$#each event eventClassField +} + +func on$PkgName$EvtName$+Thunk(message []string) { + e := &Event$EvtName{} + e.Init(message) +$#each event eventHandlerField + On$PkgName$EvtName(e) +} +`, + // ******************************* + "eventClassField": ` + $FldName $fldLangType +`, + // ******************************* + "eventHandlerField": ` + e.$FldName = e.Next$FldType() +`, +} diff --git a/tools/schema/generator/goclienttemplates/funcs.go b/tools/schema/generator/goclienttemplates/funcs.go new file mode 100644 index 0000000000..ca29c3d132 --- /dev/null +++ b/tools/schema/generator/goclienttemplates/funcs.go @@ -0,0 +1,15 @@ +package goclienttemplates + +var funcsGo = map[string]string{ + // ******************************* + "funcs.go": ` +$#emit clientHeader +$#each events funcSignature +`, + // ******************************* + "funcSignature": ` + +func On$PkgName$EvtName(event *Event$EvtName) { +} +`, +} diff --git a/tools/schema/generator/goclienttemplates/service.go b/tools/schema/generator/goclienttemplates/service.go new file mode 100644 index 0000000000..9dc96e37d6 --- /dev/null +++ b/tools/schema/generator/goclienttemplates/service.go @@ -0,0 +1,166 @@ +package goclienttemplates + +var serviceGo = map[string]string{ + // ******************************* + "service.go": ` +$#emit clientHeader + +const ( +$#each params constArg + +$#each results constRes +) +$#each func funcStruct + +///////////////////////////// $PkgName$+Service ///////////////////////////// + +type $PkgName$+Service struct { + wasmclient.Service +} + +func New$PkgName$+Service(cl *wasmclient.ServiceClient, chainID string) (*$PkgName$+Service, error) { + s := &$PkgName$+Service{} +$#set eventHandlers EventHandlers +$#if core noEventHandlers + err := s.Service.Init(cl, chainID, 0x$hscName, $eventHandlers) + return s, err +} +$#each func serviceFunction +`, + // ******************************* + "noEventHandlers": ` +$#set eventHandlers nil +`, + // ******************************* + "constArg": ` + Arg$FldName = "$fldAlias" +`, + // ******************************* + "constRes": ` + Res$FldName = "$fldAlias" +`, + // ******************************* + "funcStruct": ` + +///////////////////////////// $funcName ///////////////////////////// + +type $FuncName$Kind struct { + wasmclient.Client$Kind +$#if param funcArgsMember +} +$#each param funcArgSetter +$#if func funcPost viewCall +`, + // ******************************* + "funcArgsMember": ` + args wasmclient.Arguments +`, + // ******************************* + "funcArgSetter": ` +$#if array funcArgSetterArray funcArgSetterBasic +`, + // ******************************* + "funcArgSetterBasic": ` + +func (f *$FuncName$Kind) $FldName(v $fldLangType) { + f.args.Set(Arg$FldName, f.args.From$FldType(v)) +} +`, + // ******************************* + "funcArgSetterArray": ` + +func (f *$FuncName$Kind) $FldName(a []$fldLangType) { + for i, v := range a { + f.args.Set(f.args.IndexedKey(Arg$FldName, i), f.args.From$FldType(v)) + } + f.args.Set(Arg$FldName, f.args.SetInt32(int32(len(a)))) +} +`, + // ******************************* + "funcPost": ` + +func (f *$FuncName$Kind) Post() wasmclient.Request { +$#each mandatory mandatoryCheck +$#if param execWithArgs execNoArgs + return f.ClientFunc.Post(0x$hFuncName, $args) +} +`, + // ******************************* + "viewCall": ` + +func (f *$FuncName$Kind) Call() $FuncName$+Results { +$#each mandatory mandatoryCheck +$#if param execWithArgs execNoArgs + f.ClientView.Call("$funcName", $args) + return $FuncName$+Results{res: f.Results()} +} +$#if result resultStruct +`, + // ******************************* + "mandatoryCheck": ` + f.args.Mandatory(Arg$FldName) +`, + // ******************************* + "execWithArgs": ` +$#set args &f.args +`, + // ******************************* + "execNoArgs": ` +$#set args nil +`, + // ******************************* + "resultStruct": ` + +type $FuncName$+Results struct { + res wasmclient.Results +} +$#each result callResultGetter +`, + // ******************************* + "callResultGetter": ` +$#if map callResultGetterMap callResultGetterBasic +`, + // ******************************* + "callResultGetterMap": ` + +func (r *$FuncName$+Results) $FldName() map[$fldKeyLangType]$fldLangType { + res := make(map[$fldKeyLangType]$fldLangType) + r.res.ForEach(func(key []byte, val []byte) { + res[r.res.To$fldMapKey(key)] = r.res.To$FldType(val) + }) + return res +} +`, + // ******************************* + "callResultGetterBasic": ` +$#if mandatory else callResultOptional + +func (r *$FuncName$+Results) $FldName() $fldLangType { + return r.res.To$FldType(r.res.Get(Res$FldName)) +} +`, + // ******************************* + "callResultOptional": ` + +func (r *$FuncName$+Results) $FldName$+Exists() bool { + return r.res.Exists(Res$FldName) +} +`, + // ******************************* + "serviceResultExtract": ` + if buf, ok := result["$fldName"]; ok { + r.$FldName = buf.$resConvert + } +`, + // ******************************* + "serviceResult": ` + $FldName $fldLangType +`, + // ******************************* + "serviceFunction": ` + +func (s *$PkgName$+Service) $FuncName() $FuncName$Kind { + return $FuncName$Kind{Client$Kind: s.AsClient$Kind()} +} +`, +} diff --git a/tools/schema/generator/gotemplates/alltemplates.go b/tools/schema/generator/gotemplates/alltemplates.go index f4d0fd736b..3fe42a9552 100644 --- a/tools/schema/generator/gotemplates/alltemplates.go +++ b/tools/schema/generator/gotemplates/alltemplates.go @@ -10,7 +10,7 @@ var config = map[string]string{ } var Templates = []map[string]string{ - config, + config, // always first one common, constsGo, contractGo, diff --git a/tools/schema/generator/gotemplates/consts.go b/tools/schema/generator/gotemplates/consts.go index ac7d6e350c..81474d2c23 100644 --- a/tools/schema/generator/gotemplates/consts.go +++ b/tools/schema/generator/gotemplates/consts.go @@ -56,6 +56,6 @@ $#each state constField `, // ******************************* "constHFunc": ` - H$Kind$FuncName$funcPad = wasmlib.ScHname(0x$funcHname) + H$Kind$FuncName$funcPad = wasmlib.ScHname(0x$hFuncName) `, } diff --git a/tools/schema/generator/gotemplates/main.go b/tools/schema/generator/gotemplates/main.go index e03d43c541..9a2798990b 100644 --- a/tools/schema/generator/gotemplates/main.go +++ b/tools/schema/generator/gotemplates/main.go @@ -7,7 +7,7 @@ var mainGo = map[string]string{ package main -import "github.com/iotaledger/wasp/packages/vm/wasmclient" +import "github.com/iotaledger/wasp/packages/vm/wasmvmhost" import "$module/go/$package" @@ -16,7 +16,7 @@ func main() { //export on_load func onLoad() { - h := &wasmclient.WasmVMHost{} + h := &wasmvmhost.WasmVMHost{} h.ConnectWasmHost() $package.OnLoad() } diff --git a/tools/schema/generator/gotemplates/proxy.go b/tools/schema/generator/gotemplates/proxy.go index 4ea6a2f3f0..4e4725c4fb 100644 --- a/tools/schema/generator/gotemplates/proxy.go +++ b/tools/schema/generator/gotemplates/proxy.go @@ -8,9 +8,14 @@ $#if map typedefProxyMap `, // ******************************* "proxyMethods": ` -$#set varID idxMap[Idx$Kind$FldName] +$#set varID wasmlib.KeyID($Kind$FldName) +$#if init setInitVarID $#if core setCoreVarID $#if array proxyArray proxyMethods2 +`, + // ******************************* + "setInitVarID": ` +$#set varID idxMap[Idx$Kind$FldName] `, // ******************************* "proxyMethods2": ` @@ -48,7 +53,7 @@ func (s $TypeName) $FldName() Map$fldMapKey$+To$mut$FldType { } `, // ******************************* - "proxyMapOther": `55544444.0 + "proxyMapOther": ` func (s $TypeName) $FldName() Map$fldMapKey$+To$mut$FldType { mapID := wasmlib.GetObjectID(s.id, $varID, wasmlib.TYPE_MAP) diff --git a/tools/schema/generator/gotemplates/state.go b/tools/schema/generator/gotemplates/state.go index 00dbd4163e..5cd4a0bd9a 100644 --- a/tools/schema/generator/gotemplates/state.go +++ b/tools/schema/generator/gotemplates/state.go @@ -19,6 +19,14 @@ $#each state proxyContainers type $TypeName struct { id int32 } +$#if mut stateProxyImmutableFunc $#each state proxyMethods +`, + // ******************************* + "stateProxyImmutableFunc": ` + +func (s $TypeName) AsImmutable() Immutable$Package$+State { + return Immutable$Package$+State(s) +} `, } diff --git a/tools/schema/generator/rstemplates/alltemplates.go b/tools/schema/generator/rstemplates/alltemplates.go index 394bf05480..0764cd0b16 100644 --- a/tools/schema/generator/rstemplates/alltemplates.go +++ b/tools/schema/generator/rstemplates/alltemplates.go @@ -10,7 +10,7 @@ var config = map[string]string{ } var Templates = []map[string]string{ - config, + config, // always first one common, cargoToml, constsRs, diff --git a/tools/schema/generator/rstemplates/consts.go b/tools/schema/generator/rstemplates/consts.go index 4c3a5bcc4b..95913a1a8d 100644 --- a/tools/schema/generator/rstemplates/consts.go +++ b/tools/schema/generator/rstemplates/consts.go @@ -46,6 +46,6 @@ pub$crate const $KIND$+_$FUNC_NAME$func_pad : &str = "$funcName"; `, // ******************************* "constHFunc": ` -pub$crate const H$KIND$+_$FUNC_NAME$func_pad : ScHname = ScHname(0x$funcHname); +pub$crate const H$KIND$+_$FUNC_NAME$func_pad : ScHname = ScHname(0x$hFuncName); `, } diff --git a/tools/schema/generator/rstemplates/proxy.go b/tools/schema/generator/rstemplates/proxy.go index 9070f680a3..b391095c33 100644 --- a/tools/schema/generator/rstemplates/proxy.go +++ b/tools/schema/generator/rstemplates/proxy.go @@ -10,9 +10,14 @@ $#if map typedefProxyMap "proxyMethods": ` $#if separator newline $#set separator $true -$#set varID idx_map(IDX_$Kind$FLD_NAME) +$#set varID $Kind$FLD_NAME.get_key_id() +$#if init setInitVarID $#if core setCoreVarID $#if array proxyArray proxyMethods2 +`, + // ******************************* + "setInitVarID": ` +$#set varID idx_map(IDX_$Kind$FLD_NAME) `, // ******************************* "proxyMethods2": ` @@ -48,7 +53,7 @@ $#if this proxyMapThis proxyMapOther } `, // ******************************* - "proxyMapOther": `55544444.0 + "proxyMapOther": ` pub fn $fld_name(&self) -> Map$fldMapKey$+To$mut$FldType { let map_id = get_object_id(self.id, $varID, TYPE_MAP); Map$fldMapKey$+To$mut$FldType { obj_id: map_id } diff --git a/tools/schema/generator/rstemplates/state.go b/tools/schema/generator/rstemplates/state.go index 2dbdabed25..b5aa40fd8a 100644 --- a/tools/schema/generator/rstemplates/state.go +++ b/tools/schema/generator/rstemplates/state.go @@ -35,7 +35,15 @@ $#if state stateProxyImpl impl $TypeName { $#set separator $false +$#if mut stateProxyImmutableFunc $#each state proxyMethods } +`, + // ******************************* + "stateProxyImmutableFunc": ` +$#set separator $true + pub fn as_immutable(&self) -> Immutable$Package$+State { + Immutable$Package$+State { id: self.id } + } `, } diff --git a/tools/schema/generator/rstemplates/structs.go b/tools/schema/generator/rstemplates/structs.go index 4c74de9f0e..6d0e1fc499 100644 --- a/tools/schema/generator/rstemplates/structs.go +++ b/tools/schema/generator/rstemplates/structs.go @@ -14,6 +14,7 @@ $#each structs structType // ******************************* "structType": ` +#[derive(Clone)] pub struct $StrName { $#each struct structField } @@ -52,6 +53,7 @@ $#emit structMethods // ******************************* "structMethods": ` +#[derive(Clone, Copy)] pub struct $mut$StrName { pub(crate) obj_id: i32, pub(crate) key_id: Key32, diff --git a/tools/schema/generator/rstemplates/typedefs.go b/tools/schema/generator/rstemplates/typedefs.go index 3b6a2fd676..06a3e60021 100644 --- a/tools/schema/generator/rstemplates/typedefs.go +++ b/tools/schema/generator/rstemplates/typedefs.go @@ -36,6 +36,7 @@ $#if exist else typedefProxyArrayNew // ******************************* "typedefProxyArrayNew": ` +#[derive(Clone, Copy)] pub struct $proxy { pub(crate) obj_id: i32, } @@ -89,6 +90,7 @@ $#if exist else typedefProxyMapNew // ******************************* "typedefProxyMapNew": ` +#[derive(Clone, Copy)] pub struct $proxy { pub(crate) obj_id: i32, } diff --git a/tools/schema/generator/tsclienttemplates/alltemplates.go b/tools/schema/generator/tsclienttemplates/alltemplates.go new file mode 100644 index 0000000000..fb9cfbe3b4 --- /dev/null +++ b/tools/schema/generator/tsclienttemplates/alltemplates.go @@ -0,0 +1,109 @@ +package tsclienttemplates + +import "github.com/iotaledger/wasp/tools/schema/model" + +var config = map[string]string{ + "language": "TypeScript Client", + "extension": ".ts", + "rootFolder": "ts", + "funcRegexp": `^export function on(\w+).+$`, +} + +var Templates = []map[string]string{ + config, // always first one + common, + eventsTs, + funcsTs, + indexTs, + serviceTs, +} + +var TypeDependent = model.StringMapMap{ + "fldLangType": { + "Address": "wasmclient.Address", + "AgentID": "wasmclient.AgentID", + "Bool": "boolean", + "Bytes": "wasmclient.Bytes", + "ChainID": "wasmclient.ChainID", + "Color": "wasmclient.Color", + "Hash": "wasmclient.Hash", + "Hname": "wasmclient.Hname", + "Int8": "wasmclient.Int8", + "Int16": "wasmclient.Int16", + "Int32": "wasmclient.Int32", + "Int64": "wasmclient.Int64", + "RequestID": "wasmclient.RequestID", + "String": "string", + "Uint8": "wasmclient.Uint8", + "Uint16": "wasmclient.Uint16", + "Uint32": "wasmclient.Uint32", + "Uint64": "wasmclient.Uint64", + }, + "fldDefault": { + "Address": "''", + "AgentID": "''", + "Bool": "false", + "ChainID": "''", + "Color": "''", + "Hash": "''", + "Hname": "''", + "Int8": "0", + "Int16": "0", + "Int32": "0", + "Int64": "BigInt(0)", + "RequestID": "''", + "String": "''", + "Uint8": "0", + "Uint16": "0", + "Uint32": "0", + "Uint64": "BigInt(0)", + }, + "resConvert": { + "Address": "toString()", + "AgentID": "toString()", + "Bool": "readUInt8(0)!=0", + "ChainID": "toString()", + "Color": "toString()", + "Hash": "toString()", + "Hname": "toString()", + "Int8": "readInt8(0)", + "Int16": "readInt16LE(0)", + "Int32": "readInt32LE(0)", + "Int64": "readBigInt64LE(0)", + "RequestID": "toString()", + "String": "toString()", + "Uint8": "readUInt8(0)", + "Uint16": "readUInt16LE(0)", + "Uint32": "readUInt32LE(0)", + "Uint64": "readBigUInt64LE(0)", + }, +} + +var common = map[string]string{ + // ******************************* + "tsconfig.json": ` +{ + "compilerOptions": { + "module": "commonjs", + "lib": ["es2020"], + "target": "es2020", + "sourceMap": true + }, + "exclude": [ + "node_modules" + ], +} +`, + // ******************************* + "importEvents": ` +import * as events from "./events" +`, + // ******************************* + "importService": ` +import * as service from "./service" +`, + // ******************************* + "importWasmLib": ` +import * as wasmclient from "wasmclient" +`, +} diff --git a/tools/schema/generator/tsclienttemplates/events.go b/tools/schema/generator/tsclienttemplates/events.go new file mode 100644 index 0000000000..b7bef5f608 --- /dev/null +++ b/tools/schema/generator/tsclienttemplates/events.go @@ -0,0 +1,38 @@ +package tsclienttemplates + +var eventsTs = map[string]string{ + // ******************************* + "events.ts": ` +$#emit importWasmLib +import * as app from "./$package" + +export const eventHandlers: wasmclient.EventHandlers = new Map([ +$#each events eventHandler +]); +$#each events eventClass +`, + // ******************************* + "eventHandler": ` + ["$package.$evtName", (msg: string[]) => app.on$PkgName$EvtName(new Event$EvtName(msg))], +`, + // ******************************* + "eventClass": ` + +export class Event$EvtName extends wasmclient.Event { +$#each event eventClassField + + public constructor(msg: string[]) { + super(msg) +$#each event eventHandlerField + } +} +`, + // ******************************* + "eventClassField": ` + public readonly $fldName: wasmclient.$FldType; +`, + // ******************************* + "eventHandlerField": ` + this.$fldName = this.next$FldType(); +`, +} diff --git a/tools/schema/generator/tsclienttemplates/funcs.go b/tools/schema/generator/tsclienttemplates/funcs.go new file mode 100644 index 0000000000..02e361eaf3 --- /dev/null +++ b/tools/schema/generator/tsclienttemplates/funcs.go @@ -0,0 +1,16 @@ +package tsclienttemplates + +var funcsTs = map[string]string{ + // ******************************* + "funcs.ts": ` +$#emit importEvents +$#emit importService +$#each events funcSignature +`, + // ******************************* + "funcSignature": ` + +export function on$PkgName$EvtName(event: events.Event$EvtName): void { +} +`, +} diff --git a/tools/schema/generator/tsclienttemplates/index.go b/tools/schema/generator/tsclienttemplates/index.go new file mode 100644 index 0000000000..5c075efe59 --- /dev/null +++ b/tools/schema/generator/tsclienttemplates/index.go @@ -0,0 +1,10 @@ +package tsclienttemplates + +var indexTs = map[string]string{ + // ******************************* + "index.ts": ` +export * from "./$package"; +export * from "./events"; +export * from "./service"; +`, +} diff --git a/tools/schema/generator/tsclienttemplates/service.go b/tools/schema/generator/tsclienttemplates/service.go new file mode 100644 index 0000000000..e27327d93d --- /dev/null +++ b/tools/schema/generator/tsclienttemplates/service.go @@ -0,0 +1,151 @@ +package tsclienttemplates + +var serviceTs = map[string]string{ + // ******************************* + "service.ts": ` +$#emit importWasmLib +$#if core else importEvents + +$#each params constArg + +$#each results constRes +$#each func funcStruct + +///////////////////////////// $PkgName$+Service ///////////////////////////// + +export class $PkgName$+Service extends wasmclient.Service { + + public constructor(cl: wasmclient.ServiceClient) { +$#set eventHandlers events.eventHandlers +$#if core noEventHandlers + super(cl, 0x$hscName, $eventHandlers); + } +$#each func serviceFunction +} +`, + // ******************************* + "noEventHandlers": ` +$#set eventHandlers new Map() +`, + // ******************************* + "constArg": ` +const Arg$FldName = "$fldAlias"; +`, + // ******************************* + "constRes": ` +const Res$FldName = "$fldAlias"; +`, + // ******************************* + "funcStruct": ` + +///////////////////////////// $funcName ///////////////////////////// + +export class $FuncName$Kind extends wasmclient.Client$Kind { +$#if param funcArgsMember +$#each param funcArgSetter +$#if func funcPost viewCall +} +$#if result resultStruct +`, + // ******************************* + "funcArgsMember": ` + private args: wasmclient.Arguments = new wasmclient.Arguments(); +`, + // ******************************* + "funcArgSetter": ` +$#if array funcArgSetterArray funcArgSetterBasic +`, + // ******************************* + "funcArgSetterBasic": ` + + public $fldName(v: $fldLangType): void { + this.args.set(Arg$FldName, this.args.from$FldType(v)); + } +`, + // ******************************* + "funcArgSetterArray": ` + + public $fldName(a: $fldLangType[]): void { + for (let i = 0; i < a.length; i++) { + this.args.set(this.args.indexedKey(Arg$FldName, i), this.args.from$FldType(a[i])); + } + this.args.set(Arg$FldName, this.args.setInt32(a.length)); + } +`, + // ******************************* + "funcPost": ` + + public async post(): Promise { +$#each mandatory mandatoryCheck +$#if param execWithArgs execNoArgs + return await super.post(0x$hFuncName, $args); + } +`, + // ******************************* + "viewCall": ` + + public async call(): Promise<$FuncName$+Results> { +$#each mandatory mandatoryCheck +$#if param execWithArgs execNoArgs + const res = new $FuncName$+Results(); + await this.callView("$funcName", $args, res); + return res; + } +`, + // ******************************* + "mandatoryCheck": ` + this.args.mandatory(Arg$FldName); +`, + // ******************************* + "execWithArgs": ` +$#set args this.args +`, + // ******************************* + "execNoArgs": ` +$#set args null +`, + // ******************************* + "resultStruct": ` + +export class $FuncName$+Results extends wasmclient.Results { +$#each result callResultGetter +} +`, + // ******************************* + "callResultGetter": ` +$#if map callResultGetterMap callResultGetterBasic +`, + // ******************************* + "callResultGetterMap": ` + + $fldName(): Map<$fldKeyLangType, $fldLangType> { + const res = new Map<$fldKeyLangType, $fldLangType>(); + this.forEach((key, val) => { + res.set(this.to$fldMapKey(key), this.to$FldType(val)); + }); + return res; + } +`, + // ******************************* + "callResultGetterBasic": ` +$#if mandatory else callResultOptional + + $fldName(): $fldLangType { + return this.to$FldType(this.get(Res$FldName)); + } +`, + // ******************************* + "callResultOptional": ` + + $fldName$+Exists(): boolean { + return this.exists(Res$FldName) + } +`, + // ******************************* + "serviceFunction": ` + + public $funcName(): $FuncName$Kind { + return new $FuncName$Kind(this); + } +`, +} diff --git a/tools/schema/generator/tstemplates/alltemplates.go b/tools/schema/generator/tstemplates/alltemplates.go index 8fc4865ace..9fa0a18071 100644 --- a/tools/schema/generator/tstemplates/alltemplates.go +++ b/tools/schema/generator/tstemplates/alltemplates.go @@ -10,7 +10,7 @@ var config = map[string]string{ } var Templates = []map[string]string{ - config, + config, // always first one common, constsTs, contractTs, diff --git a/tools/schema/generator/tstemplates/consts.go b/tools/schema/generator/tstemplates/consts.go index 002eade14c..5f56e70bf0 100644 --- a/tools/schema/generator/tstemplates/consts.go +++ b/tools/schema/generator/tstemplates/consts.go @@ -44,6 +44,6 @@ export const $Kind$FuncName$funcPad = "$funcName"; `, // ******************************* "constHFunc": ` -export const H$Kind$FuncName$funcPad = new wasmlib.ScHname(0x$funcHname); +export const H$Kind$FuncName$funcPad = new wasmlib.ScHname(0x$hFuncName); `, } diff --git a/tools/schema/generator/tstemplates/contract.go b/tools/schema/generator/tstemplates/contract.go index a2cc9ba26b..51788b0edb 100644 --- a/tools/schema/generator/tstemplates/contract.go +++ b/tools/schema/generator/tstemplates/contract.go @@ -39,7 +39,7 @@ $#if events PackageEventsExist `, // ******************************* "PackageEventsExist": ` - events: sc.$Package$+Events = new sc.$Package$+Events(); + events: sc.$Package$+Events = new sc.$Package$+Events(); `, // ******************************* "ImmutableFuncNameParams": ` diff --git a/tools/schema/generator/tstemplates/proxy.go b/tools/schema/generator/tstemplates/proxy.go index 1cef0b8798..2e2f1ddaac 100644 --- a/tools/schema/generator/tstemplates/proxy.go +++ b/tools/schema/generator/tstemplates/proxy.go @@ -10,9 +10,14 @@ $#if map typedefProxyMap "proxyMethods": ` $#if separator newline $#set separator $true -$#set varID sc.idxMap[sc.Idx$Kind$FldName] +$#set varID wasmlib.Key32.fromString(sc.$Kind$FldName) +$#if init setInitVarID $#if core setCoreVarID $#if array proxyArray proxyMethods2 +`, + // ******************************* + "setInitVarID": ` +$#set varID sc.idxMap[sc.Idx$Kind$FldName] `, // ******************************* "proxyMethods2": ` diff --git a/tools/schema/generator/tstemplates/state.go b/tools/schema/generator/tstemplates/state.go index f624be1471..979756a368 100644 --- a/tools/schema/generator/tstemplates/state.go +++ b/tools/schema/generator/tstemplates/state.go @@ -17,7 +17,17 @@ $#each state proxyContainers export class $TypeName extends wasmlib.ScMapID { $#set separator $false +$#if mut stateProxyImmutableFunc $#each state proxyMethods } +`, + // ******************************* + "stateProxyImmutableFunc": ` +$#set separator $true + asImmutable(): sc.Immutable$Package$+State { + const imm = new sc.Immutable$Package$+State(); + imm.mapID = this.mapID; + return imm; + } `, } diff --git a/tools/schema/main.go b/tools/schema/main.go index bcdb2543b6..3595845ca3 100644 --- a/tools/schema/main.go +++ b/tools/schema/main.go @@ -98,29 +98,29 @@ func generateCoreInterfaces() { } func generateSchema(file *os.File) error { - info, err := file.Stat() - if err != nil { - return err - } - s, err := loadSchema(file) if err != nil { return err } s.CoreContracts = *flagCore - s.SchemaTime = info.ModTime() - if *flagForce { - // make as if it has just been updated - s.SchemaTime = time.Now() - } + s.SchemaTime = time.Now() + if !*flagForce { + // force regeneration when schema definition file is newer + info, err := file.Stat() + if err != nil { + return err + } + s.SchemaTime = info.ModTime() - if *flagClient { - g := generator.NewClientGenerator(s) - err = g.Generate() + // also force regeneration when schema tool itself is newer + info, err = os.Stat(os.Args[0]) if err != nil { return err } + if info.ModTime().After(s.SchemaTime) { + s.SchemaTime = info.ModTime() + } } if *flagGo { @@ -129,6 +129,13 @@ func generateSchema(file *os.File) error { if err != nil { return err } + if *flagClient { + cg := generator.NewGoClientGenerator(s) + err = cg.Generate() + if err != nil { + return err + } + } } if *flagRust { @@ -145,6 +152,13 @@ func generateSchema(file *os.File) error { if err != nil { return err } + if *flagClient { + cg := generator.NewTsClientGenerator(s) + err = cg.Generate() + if err != nil { + return err + } + } } return nil } diff --git a/tools/wasp-cli/chain/activate.go b/tools/wasp-cli/chain/activate.go index dcaa785003..e765e3a0f9 100644 --- a/tools/wasp-cli/chain/activate.go +++ b/tools/wasp-cli/chain/activate.go @@ -7,18 +7,18 @@ import ( var activateCmd = &cobra.Command{ Use: "activate", - Short: "Activate the chain", + Short: "Activate the chain on this node", Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { - log.Check(MultiClient().ActivateChain(GetCurrentChainID())) + log.Check(Client().WaspClient.ActivateChain(GetCurrentChainID())) }, } var deactivateCmd = &cobra.Command{ Use: "deactivate", - Short: "Deactivate the chain", + Short: "Deactivate the chain on this node", Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { - log.Check(MultiClient().DeactivateChain(GetCurrentChainID())) + log.Check(Client().WaspClient.DeactivateChain(GetCurrentChainID())) }, } diff --git a/tools/wasp-cli/chain/client.go b/tools/wasp-cli/chain/client.go index 5b129d4e10..be437b0fc7 100644 --- a/tools/wasp-cli/chain/client.go +++ b/tools/wasp-cli/chain/client.go @@ -1,8 +1,10 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package chain import ( "github.com/iotaledger/wasp/client/chainclient" - "github.com/iotaledger/wasp/client/multiclient" "github.com/iotaledger/wasp/client/scclient" "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/tools/wasp-cli/config" @@ -18,10 +20,6 @@ func Client() *chainclient.Client { ) } -func MultiClient() *multiclient.MultiClient { - return multiclient.New(config.CommitteeAPI(chainCommittee())) -} - func SCClient(contractHname iscp.Hname) *scclient.SCClient { return scclient.New(Client(), contractHname) } diff --git a/tools/wasp-cli/chain/committee.go b/tools/wasp-cli/chain/committee.go deleted file mode 100644 index 4ca9c60a20..0000000000 --- a/tools/wasp-cli/chain/committee.go +++ /dev/null @@ -1,18 +0,0 @@ -package chain - -import ( - "github.com/iotaledger/wasp/tools/wasp-cli/config" - "github.com/iotaledger/wasp/tools/wasp-cli/log" -) - -func chainCommittee() []int { - chainID := GetCurrentChainID() - committee, err := config.WaspClient().GetCommitteeForChain(chainID) - log.Check(err) - - r := []int{} - for _, peering := range committee.Nodes { - r = append(r, config.FindNodeBy(config.HostKindPeering, peering)) - } - return r -} diff --git a/tools/wasp-cli/chain/deploy.go b/tools/wasp-cli/chain/deploy.go index 15b55329e8..6788b3ad07 100644 --- a/tools/wasp-cli/chain/deploy.go +++ b/tools/wasp-cli/chain/deploy.go @@ -1,8 +1,12 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package chain import ( "os" + "github.com/iotaledger/wasp/client" "github.com/iotaledger/wasp/packages/apilib" "github.com/iotaledger/wasp/tools/wasp-cli/config" "github.com/iotaledger/wasp/tools/wasp-cli/log" @@ -12,7 +16,6 @@ import ( func deployCmd() *cobra.Command { var ( - peers []int committee []int quorum int description string @@ -25,29 +28,26 @@ func deployCmd() *cobra.Command { Run: func(cmd *cobra.Command, args []string) { alias := GetChainAlias() - if peers == nil { - if committee != nil { - peers = committee - } else { - peers = []int{0, 1, 2, 3} - } + if committee == nil { + committee = []int{0, 1, 2, 3} } - if committee == nil { - committee = peers + committeePubKeys := make([]string, 0) + for _, api := range config.CommitteeAPI(committee) { + peerInfo, err := client.NewWaspClient(api).GetPeeringSelf() + log.Check(err) + committeePubKeys = append(committeePubKeys, peerInfo.PubKey) } chainid, _, err := apilib.DeployChainWithDKG(apilib.CreateChainParams{ - Node: config.GoshimmerClient(), - AllAPIHosts: config.CommitteeAPI(peers), - AllPeeringHosts: config.CommitteePeering(peers), - CommitteeAPIHosts: config.CommitteeAPI(committee), - CommitteePeeringHosts: config.CommitteePeering(committee), - N: uint16(len(committee)), - T: uint16(quorum), - OriginatorKeyPair: wallet.Load().KeyPair(), - Description: description, - Textout: os.Stdout, + Node: config.GoshimmerClient(), + CommitteeAPIHosts: config.CommitteeAPI(committee), + CommitteePubKeys: committeePubKeys, + N: uint16(len(committee)), + T: uint16(quorum), + OriginatorKeyPair: wallet.Load().KeyPair(), + Description: description, + Textout: os.Stdout, }) log.Check(err) @@ -55,8 +55,7 @@ func deployCmd() *cobra.Command { }, } - cmd.Flags().IntSliceVarP(&peers, "peers", "", nil, "indices of peer nodes (default: 0,1,2,3)") - cmd.Flags().IntSliceVarP(&committee, "committee", "", nil, "subset of peers acting as committee nodes (default: same as peers)") + cmd.Flags().IntSliceVarP(&committee, "committee", "", nil, "peers acting as committee nodes (default: 0,1,2,3)") cmd.Flags().IntVarP(&quorum, "quorum", "", 3, "quorum") cmd.Flags().StringVarP(&description, "description", "", "", "description") return cmd diff --git a/tools/wasp-cli/chain/info.go b/tools/wasp-cli/chain/info.go index a3bfb59b15..6922f7f53d 100644 --- a/tools/wasp-cli/chain/info.go +++ b/tools/wasp-cli/chain/info.go @@ -1,10 +1,16 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package chain import ( + "strconv" + "github.com/iotaledger/wasp/packages/kv/codec" "github.com/iotaledger/wasp/packages/kv/collections" "github.com/iotaledger/wasp/packages/vm/core/governance" "github.com/iotaledger/wasp/packages/vm/core/root" + "github.com/iotaledger/wasp/packages/webapi/model" "github.com/iotaledger/wasp/tools/wasp-cli/config" "github.com/iotaledger/wasp/tools/wasp-cli/log" "github.com/spf13/cobra" @@ -15,17 +21,41 @@ var infoCmd = &cobra.Command{ Short: "Show information about the chain", Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { - chain, err := config.WaspClient().GetChainRecord(GetCurrentChainID()) + chainInfo, err := config.WaspClient().GetChainInfo(GetCurrentChainID()) log.Check(err) - committee, err := config.WaspClient().GetCommitteeForChain(chain.ChainID) - log.Check(err) + printNodesRowHdr := []string{"PubKey", "NetID", "Alive", "Committee", "Access", "AccessAPI"} + printNodesRowFmt := func(n *model.ChainNodeStatus) []string { + return []string{ + n.Node.PubKey, + n.Node.NetID, + strconv.FormatBool(n.Node.IsAlive), + strconv.FormatBool(n.ForCommittee), + strconv.FormatBool(n.ForAccess), + n.AccessAPI, + } + } + printNodes := func(label string, nodes []*model.ChainNodeStatus) { + if nodes == nil { + log.Printf("%s: N/A\n", label) + } + log.Printf("%s: %v\n", label, len(nodes)) + rows := make([][]string, 0) + for _, n := range nodes { + rows = append(rows, printNodesRowFmt(n)) + } + log.PrintTable(printNodesRowHdr, rows) + } + + log.Printf("Chain ID: %s\n", chainInfo.ChainID) + log.Printf("Active: %v\n", chainInfo.Active) - log.Printf("Chain ID: %s\n", chain.ChainID.Base58()) - log.Printf("Committee nodes: %+v\n", committee.Nodes) - log.Printf("Active: %v\n", chain.Active) + if chainInfo.Active { + log.Printf("State address: %v\n", chainInfo.StateAddress) + printNodes("Committee nodes", chainInfo.CommitteeNodes) + printNodes("Access nodes", chainInfo.AccessNodes) + printNodes("Candidate nodes", chainInfo.CandidateNodes) - if chain.Active { info, err := SCClient(governance.Contract.Hname()).CallView(governance.FuncGetChainInfo.Name, nil) log.Check(err) diff --git a/tools/wasp-cli/chain/postrequest.go b/tools/wasp-cli/chain/postrequest.go index cae1562aed..1be3c30bfc 100644 --- a/tools/wasp-cli/chain/postrequest.go +++ b/tools/wasp-cli/chain/postrequest.go @@ -3,6 +3,7 @@ package chain import ( "strconv" "strings" + "time" "github.com/iotaledger/goshimmer/packages/ledgerstate" "github.com/iotaledger/wasp/client/chainclient" @@ -34,6 +35,7 @@ func postRequestCmd() *cobra.Command { scClient := SCClient(iscp.Hn(args[0])) if offLedger { + params.Nonce = uint64(time.Now().UnixNano()) util.WithOffLedgerRequest(GetCurrentChainID(), func() (*request.OffLedger, error) { return scClient.PostOffLedgerRequest(fname, params) }) diff --git a/tools/wasp-cli/metrics/consensus.go b/tools/wasp-cli/metrics/consensus.go new file mode 100644 index 0000000000..07dad27713 --- /dev/null +++ b/tools/wasp-cli/metrics/consensus.go @@ -0,0 +1,50 @@ +package metrics + +import ( + "fmt" + "time" + + "github.com/iotaledger/wasp/packages/iscp" + "github.com/iotaledger/wasp/tools/wasp-cli/config" + "github.com/iotaledger/wasp/tools/wasp-cli/log" + "github.com/spf13/cobra" +) + +var timestampNeverConst = time.Time{} + +var consensusMetricsCmd = &cobra.Command{ + Use: "consensus", + Short: "Show current value of collected metrics of consensus", + Args: cobra.NoArgs, + Run: func(cmd *cobra.Command, args []string) { + client := config.WaspClient() + chid, err := iscp.ChainIDFromBase58(chainIDStr) + log.Check(err) + workflowStatus, err := client.GetChainConsensusWorkflowStatus(chid) + log.Check(err) + header := []string{"Flag name", "Value", "Last time set"} + table := make([][]string, 9) + table[0] = makeWorkflowTableRow("State received", workflowStatus.FlagStateReceived, time.Time{}) + table[1] = makeWorkflowTableRow("Batch proposal sent", workflowStatus.FlagBatchProposalSent, workflowStatus.TimeBatchProposalSent) + table[2] = makeWorkflowTableRow("Consensus on batch reached", workflowStatus.FlagConsensusBatchKnown, workflowStatus.TimeConsensusBatchKnown) + table[3] = makeWorkflowTableRow("Virtual machine started", workflowStatus.FlagVMStarted, workflowStatus.TimeVMStarted) + table[4] = makeWorkflowTableRow("Virtual machine result signed", workflowStatus.FlagVMResultSigned, workflowStatus.TimeVMResultSigned) + table[5] = makeWorkflowTableRow("Transaction finalized", workflowStatus.FlagTransactionFinalized, workflowStatus.TimeTransactionFinalized) + table[6] = makeWorkflowTableRow("Transaction posted to L1", workflowStatus.FlagTransactionPosted, workflowStatus.TimeTransactionPosted) // TODO: is not meaningful, if I am not a contributor + table[7] = makeWorkflowTableRow("Transaction seen by L1", workflowStatus.FlagTransactionSeen, workflowStatus.TimeTransactionSeen) + table[8] = makeWorkflowTableRow("Consensus is completed", !(workflowStatus.FlagInProgress), workflowStatus.TimeCompleted) + log.PrintTable(header, table) + }, +} + +func makeWorkflowTableRow(name string, value bool, timestamp time.Time) []string { + res := make([]string, 3) + res[0] = name + res[1] = fmt.Sprintf("%v", value) + if timestamp == timestampNeverConst { + res[2] = "" + } else { + res[2] = timestamp.String() + } + return res +} diff --git a/tools/wasp-cli/metrics/metrics.go b/tools/wasp-cli/metrics/metrics.go index b14acd0388..77e9256f30 100644 --- a/tools/wasp-cli/metrics/metrics.go +++ b/tools/wasp-cli/metrics/metrics.go @@ -20,5 +20,6 @@ func Init(rootCmd *cobra.Command) { rootCmd.AddCommand(metricsCmd) metricsCmd.AddCommand(nodeconnMetricsCmd) + metricsCmd.AddCommand(consensusMetricsCmd) metricsCmd.PersistentFlags().StringVarP(&chainIDStr, "chain", "", "", "chain ID for which metrics should be displayed") }